From 92e87f7e6fa762af05b03a6a82d1e135f78172cb Mon Sep 17 00:00:00 2001 From: tsabi <> Date: Thu, 29 Nov 2012 01:22:00 +0100 Subject: [PATCH 01/18] Mark strings to be translated. Maybe some missed, but most of them marked. bzr revid: tsabi-20121129002200-20tppzvh0ap5tfwe --- addons/web/controllers/main.py | 23 +++++++------ addons/web/static/src/js/chrome.js | 34 +++++++++---------- addons/web/static/src/js/dates.js | 13 +++---- addons/web/static/src/js/formats.js | 14 ++++---- addons/web/static/src/js/view_form.js | 24 ++++++------- addons/web/static/src/js/view_list.js | 14 ++++---- .../web/static/src/js/view_list_editable.js | 6 ++-- addons/web/static/src/js/views.js | 12 +++---- addons/web_calendar/static/src/js/calendar.js | 4 +-- addons/web_kanban/static/src/js/kanban.js | 2 +- .../static/src/js/view_editor.js | 10 +++--- 11 files changed, 80 insertions(+), 76 deletions(-) diff --git a/addons/web/controllers/main.py b/addons/web/controllers/main.py index e36b46ed51a..def93c16ea4 100644 --- a/addons/web/controllers/main.py +++ b/addons/web/controllers/main.py @@ -28,6 +28,7 @@ except ImportError: xlwt = None import openerp +from openerp.tools.translate import _ from .. import http from .. import nonliterals @@ -821,7 +822,7 @@ class Database(openerpweb.Controller): except xmlrpclib.Fault, e: if e.faultCode and e.faultCode.split(':')[0] == 'AccessDenied': return {'error': e.faultCode, 'title': 'Drop Database'} - return {'error': 'Could not drop database !', 'title': 'Drop Database'} + return {'error': _('Could not drop database !'), 'title': _('Drop Database')} @openerpweb.httprequest def backup(self, req, backup_db, backup_pwd, token): @@ -839,7 +840,7 @@ class Database(openerpweb.Controller): {'fileToken': int(token)} ) except xmlrpclib.Fault, e: - return simplejson.dumps([[],[{'error': e.faultCode, 'title': 'backup Database'}]]) + return simplejson.dumps([[],[{'error': e.faultCode, 'title': _('Backup Database')}]]) @openerpweb.httprequest def restore(self, req, db_file, restore_pwd, new_db): @@ -860,8 +861,8 @@ class Database(openerpweb.Controller): return req.session.proxy("db").change_admin_password(old_password, new_password) except xmlrpclib.Fault, e: if e.faultCode and e.faultCode.split(':')[0] == 'AccessDenied': - return {'error': e.faultCode, 'title': 'Change Password'} - return {'error': 'Error, password not changed !', 'title': 'Change Password'} + return {'error': e.faultCode, 'title': _('Change Password')} + return {'error': _('Error, password not changed !'), 'title': _('Change Password')} class Session(openerpweb.Controller): _cp_path = "/web/session" @@ -897,16 +898,16 @@ class Session(openerpweb.Controller): old_password, new_password,confirm_password = operator.itemgetter('old_pwd', 'new_password','confirm_pwd')( dict(map(operator.itemgetter('name', 'value'), fields))) if not (old_password.strip() and new_password.strip() and confirm_password.strip()): - return {'error':'You cannot leave any password empty.','title': 'Change Password'} + return {'error':_('You cannot leave any password empty.'),'title': _('Change Password')} if new_password != confirm_password: - return {'error': 'The new password and its confirmation must be identical.','title': 'Change Password'} + return {'error': _('The new password and its confirmation must be identical.'),'title': _('Change Password')} try: if req.session.model('res.users').change_password( old_password, new_password): return {'new_password':new_password} except Exception: - return {'error': 'The old password you provided is incorrect, your password was not changed.', 'title': 'Change Password'} - return {'error': 'Error, password not changed !', 'title': 'Change Password'} + return {'error': _('The old password you provided is incorrect, your password was not changed.'), 'title': _('Change Password')} + return {'error': _('Error, password not changed !'), 'title': _('Change Password')} @openerpweb.jsonrequest def sc_list(self, req): @@ -918,7 +919,7 @@ class Session(openerpweb.Controller): try: return req.session.proxy("db").list_lang() or [] except Exception, e: - return {"error": e, "title": "Languages"} + return {"error": e, "title": _("Languages")} @openerpweb.jsonrequest def modules(self, req): @@ -1450,7 +1451,7 @@ class SearchView(View): if not isinstance(parsed_domain, nonliterals.BaseDomain) else req.session.eval_domain(parsed_domain)) except Exception: - logger.exception("Failed to parse custom filter %s in %s", + logger.exception(_("Failed to parse custom filter %s in %s"), filter['name'], model) filter['disabled'] = True del filter['context'] @@ -1571,7 +1572,7 @@ class Binary(openerpweb.Controller): res = Model.default_get(fields, context) filecontent = base64.b64decode(res.get(field, '')) if not filecontent: - raise ValueError("No content found for field '%s' on '%s:%s'" % + raise ValueError(_("No content found for field '%s' on '%s:%s'") % (field, model, id)) else: filename = '%s_%s' % (model.replace('.', '_'), id) diff --git a/addons/web/static/src/js/chrome.js b/addons/web/static/src/js/chrome.js index 940bf800851..91cca8468d1 100644 --- a/addons/web/static/src/js/chrome.js +++ b/addons/web/static/src/js/chrome.js @@ -289,7 +289,7 @@ instance.web.CrashManager = instance.web.Class.extend({ }); instance.web.Loading = instance.web.Widget.extend({ - template: 'Loading', + template: _t("Loading"), init: function(parent) { this._super(parent); this.count = 0; @@ -390,11 +390,11 @@ instance.web.DatabaseManager = instance.web.Widget.extend({ self.$el.find("form[name=restore_db_form]").validate({ submitHandler: self.do_restore }); self.$el.find("form[name=change_pwd_form]").validate({ messages: { - old_pwd: "Please enter your previous password", - new_pwd: "Please enter your new password", + old_pwd: _t("Please enter your previous password"), + new_pwd: _t("Please enter your new password"), confirm_pwd: { - required: "Please confirm your new password", - equalTo: "The confirmation does not match the password" + required: _t("Please confirm your new password"), + equalTo: _t("The confirmation does not match the password") } }, submitHandler: self.do_change_password @@ -478,7 +478,7 @@ instance.web.DatabaseManager = instance.web.Widget.extend({ self.display_error(result); return; } - self.do_notify("Duplicating database", "The database has been duplicated."); + self.do_notify(_t("Duplicating database"), _t("The database has been duplicated.")); self.start(); }); }, @@ -488,7 +488,7 @@ instance.web.DatabaseManager = instance.web.Widget.extend({ fields = $form.serializeArray(), $db_list = $form.find('[name=drop_db]'), db = $db_list.val(); - if (!db || !confirm("Do you really want to delete the database: " + db + " ?")) { + if (!db || !confirm(_.str.sprintf(_t("Do you really want to delete the database: %s ?"), db))) { return; } self.rpc("/web/database/drop", {'fields': fields}).done(function(result) { @@ -496,7 +496,7 @@ instance.web.DatabaseManager = instance.web.Widget.extend({ self.display_error(result); return; } - self.do_notify("Dropping database", "The database '" + db + "' has been dropped"); + self.do_notify(_t("Dropping database"), _.str.sprintf(_t("The database %s has been dropped"), db)); self.start(); }); }, @@ -511,7 +511,7 @@ instance.web.DatabaseManager = instance.web.Widget.extend({ error: function(error){ if(error){ self.display_error({ - title: 'Backup Database', + title: _t("Backup Database"), error: 'AccessDenied' }); } @@ -534,13 +534,13 @@ instance.web.DatabaseManager = instance.web.Widget.extend({ if (body.indexOf('403 Forbidden') !== -1) { self.display_error({ - title: 'Access Denied', - error: 'Incorrect super-administrator password' + title: _t("Access Denied"), + error: _t("Incorrect super-administrator password") }); } else { self.display_error({ - title: 'Restore Database', - error: 'Could not restore the database' + title: _t("Restore Database"), + error: _t("Could not restore the database") }); } }, @@ -560,7 +560,7 @@ instance.web.DatabaseManager = instance.web.Widget.extend({ return; } self.unblockUI(); - self.do_notify("Changed Password", "Password has been changed successfully"); + self.do_notify(_t("Changed Password"), _t("Password has been changed successfully")); }); }, do_exit: function () { @@ -642,7 +642,7 @@ instance.web.Login = instance.web.Widget.extend({ } var db = this.$("form [name=db]").val(); if (!db) { - this.do_warn("Login", "No database selected !"); + this.do_warn(_t("Login"), _t("No database selected !")); return false; } var login = this.$("form input[name=login]").val(); @@ -678,7 +678,7 @@ instance.web.Login = instance.web.Widget.extend({ self.trigger('login_successful'); }, function () { self.$(".oe_login_pane").fadeIn("fast", function() { - self.show_error("Invalid username or password"); + self.show_error(_t("Invalid username or password")); }); }); }, @@ -765,7 +765,7 @@ instance.web.ChangePassword = instance.web.Widget.extend({ template: "ChangePassword", start: function() { var self = this; - this.getParent().dialog_title = "Change Password"; + this.getParent().dialog_title = _t("Change Password"); var $button = self.$el.find('.oe_form_button'); $button.appendTo(this.getParent().$buttons); $button.eq(2).click(function(){ diff --git a/addons/web/static/src/js/dates.js b/addons/web/static/src/js/dates.js index 3db48c8412a..1a48463df2c 100644 --- a/addons/web/static/src/js/dates.js +++ b/addons/web/static/src/js/dates.js @@ -1,5 +1,6 @@ openerp.web.dates = function(instance) { +var _t = instance.web._t; /** * Converts a string to a Date javascript object using OpenERP's @@ -18,11 +19,11 @@ instance.web.str_to_datetime = function(str) { var regex = /^(\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d)(?:\.\d+)?$/; var res = regex.exec(str); if ( !res ) { - throw new Error("'" + str + "' is not a valid datetime"); + throw new Error(_.str.sprintf(_t("'%s' is not a valid datetime"), str)); } var obj = Date.parseExact(res[1] + " UTC", 'yyyy-MM-dd HH:mm:ss zzz'); if (! obj) { - throw new Error("'" + str + "' is not a valid datetime"); + throw new Error(_.str.sprintf(_t("'%s' is not a valid datetime"), str)); } return obj; }; @@ -45,11 +46,11 @@ instance.web.str_to_date = function(str) { var regex = /^\d\d\d\d-\d\d-\d\d$/; var res = regex.exec(str); if ( !res ) { - throw new Error("'" + str + "' is not a valid date"); + throw new Error(_.str.sprintf(_t("'%s' is not a valid date"), str)); } var obj = Date.parseExact(str, 'yyyy-MM-dd'); if (! obj) { - throw new Error("'" + str + "' is not a valid date"); + throw new Error(_.str.sprintf(_t("'%s' is not a valid date"), str)); } return obj; }; @@ -72,11 +73,11 @@ instance.web.str_to_time = function(str) { var regex = /^(\d\d:\d\d:\d\d)(?:\.\d+)?$/; var res = regex.exec(str); if ( !res ) { - throw new Error("'" + str + "' is not a valid time"); + throw new Error(_.str.sprintf(_t("'%s' is not a valid time"), str)); } var obj = Date.parseExact("1970-01-01 " + res[1], 'yyyy-MM-dd HH:mm:ss'); if (! obj) { - throw new Error("'" + str + "' is not a valid time"); + throw new Error(_.str.sprintf(_t("'%s' is not a valid time"), str)); } return obj; }; diff --git a/addons/web/static/src/js/formats.js b/addons/web/static/src/js/formats.js index e586b94db6b..9432b02826f 100644 --- a/addons/web/static/src/js/formats.js +++ b/addons/web/static/src/js/formats.js @@ -224,7 +224,7 @@ instance.web.parse_value = function (value, descriptor, value_if_empty) { } while(tmp !== value); tmp = Number(value); if (isNaN(tmp)) - throw new Error(value + " is not a correct integer"); + throw new Error(_.str.sprintf(_t("'%s' is not a correct integer"), value)); return tmp; case 'float': var tmp = Number(value); @@ -239,7 +239,7 @@ instance.web.parse_value = function (value, descriptor, value_if_empty) { var reformatted_value = tmp.replace(instance.web._t.database.parameters.decimal_point, "."); var parsed = Number(reformatted_value); if (isNaN(parsed)) - throw new Error(value + " is not a correct float"); + throw new Error(_.str.sprintf(_t("'%s' is not a correct float"), value)); return parsed; case 'float_time': var factor = 1; @@ -263,7 +263,7 @@ instance.web.parse_value = function (value, descriptor, value_if_empty) { datetime = Date.parse(value); if (datetime !== null) return instance.web.datetime_to_str(datetime); - throw new Error(value + " is not a valid datetime"); + throw new Error(_.str.sprintf(_t("'%s' is not a correct datetime"), value)); case 'date': var date = Date.parseExact(value, date_pattern); if (date !== null) @@ -271,7 +271,7 @@ instance.web.parse_value = function (value, descriptor, value_if_empty) { date = Date.parse(value); if (date !== null) return instance.web.date_to_str(date); - throw new Error(value + " is not a valid date"); + throw new Error(_.str.sprintf(_t("'%s' is not a correct date"), value)); case 'time': var time = Date.parseExact(value, time_pattern); if (time !== null) @@ -279,7 +279,7 @@ instance.web.parse_value = function (value, descriptor, value_if_empty) { time = Date.parse(value); if (time !== null) return instance.web.time_to_str(time); - throw new Error(value + " is not a valid time"); + throw new Error(_.str.sprintf(_t("'%s' is not a correct time"), value)); } return value; }; @@ -294,7 +294,7 @@ instance.web.auto_str_to_date = function(value, type) { try { return instance.web.str_to_time(value); } catch(e) {} - throw new Error("'" + value + "' is not a valid date, datetime nor time"); + throw new Error(_.str.sprintf(_t("'%s' is not a correct date, datetime nor time"), value)); }; instance.web.auto_date_to_str = function(value, type) { @@ -306,7 +306,7 @@ instance.web.auto_date_to_str = function(value, type) { case 'time': return instance.web.time_to_str(value); default: - throw new Error(type + " is not convertible to date, datetime nor time"); + throw new Error(_.str.sprintf(_t("'%s' is not convertible to date, datetime nor time"), type)); } }; diff --git a/addons/web/static/src/js/view_form.js b/addons/web/static/src/js/view_form.js index 927d585a5be..dd9b2be5fb0 100644 --- a/addons/web/static/src/js/view_form.js +++ b/addons/web/static/src/js/view_form.js @@ -148,7 +148,7 @@ instance.web.FormView = instance.web.View.extend(instance.web.form.FieldManagerM load_form: function(data) { var self = this; if (!data) { - throw new Error("No data provided."); + throw new Error(_t("No data provided.")); } if (this.arch) { throw "Form view does not support multiple calls to load_form"; @@ -316,12 +316,12 @@ instance.web.FormView = instance.web.View.extend(instance.web.form.FieldManagerM var self = this, set_values = []; if (!record) { this.set({ 'title' : undefined }); - this.do_warn("Form", "The record could not be found in the database.", true); + this.do_warn(_t("Form"), _t("The record could not be found in the database."), true); return $.Deferred().reject(); } this.datarecord = record; this._actualize_mode(); - this.set({ 'title' : record.id ? record.display_name : "New" }); + this.set({ 'title' : record.id ? record.display_name : _t("New") }); _(this.fields).each(function (field, f) { field._dirty_flag = false; @@ -431,7 +431,7 @@ instance.web.FormView = instance.web.View.extend(instance.web.form.FieldManagerM var onchange = _.str.trim(on_change); var call = onchange.match(/^\s?(.*?)\((.*?)\)\s?$/); if (!call) { - throw new Error("Wrong on change format: " + onchange); + throw new Error(_.str.sprintf( _t("Wrong on change format: %s"), onchange )); } var method = call[1]; @@ -872,7 +872,7 @@ instance.web.FormView = instance.web.View.extend(instance.web.form.FieldManagerM }).value(); warnings.unshift(''); - this.do_warn("The following fields are invalid :", warnings.join('')); + this.do_warn(_t("The following fields are invalid:", warnings.join('')); }, /** * Reload the form after saving @@ -1241,11 +1241,11 @@ instance.web.form.FormRenderingEngine = instance.web.form.FormRenderingEngineInt _.each(this.fields_to_init, function($elem) { var name = $elem.attr("name"); if (!self.fvg.fields[name]) { - throw new Error("Field '" + name + "' specified in view could not be found."); + throw new Error(_.str.sprintf(_t("Field '%s' specified in view could not be found."), name)); } var obj = self.fields_registry.get_any([$elem.attr('widget'), self.fvg.fields[name].type]); if (!obj) { - throw new Error("Widget type '"+ $elem.attr('widget') + "' is not implemented"); + throw new Error(_.str.sprintf(_t("Widget type '%s' is not implemented"), $elem.attr('widget'))); } var w = new (obj)(self.view, instance.web.xml_to_json($elem[0])); var $label = self.labels[$elem.attr("name")]; @@ -2319,7 +2319,7 @@ instance.web.form.FieldEmail = instance.web.form.FieldChar.extend({ }, on_button_clicked: function() { if (!this.get('value') || !this.is_syntax_valid()) { - this.do_warn("E-mail error", "Can't send email to invalid e-mail address"); + this.do_warn(_t("E-mail error"), _t("Can't send email to invalid e-mail address")); } else { location.href = 'mailto:' + this.get('value'); } @@ -2348,7 +2348,7 @@ instance.web.form.FieldUrl = instance.web.form.FieldChar.extend({ }, on_button_clicked: function() { if (!this.get('value')) { - this.do_warn("Resource error", "This resource is empty"); + this.do_warn(_t("Resource error"), _t("This resource is empty")); } else { var url = $.trim(this.get('value')); if(/^www\./i.test(url)) @@ -3385,7 +3385,7 @@ instance.web.form.FieldOne2Many = instance.web.form.AbstractField.extend({ var views = []; _.each(modes, function(mode) { if (! _.include(["list", "tree", "graph", "kanban"], mode)) { - throw new Error(_.str.sprintf("View type '%s' is not supported in One2Many.", mode)); + throw new Error(_.str.sprintf(_t("View type '%s' is not supported in One2Many."), mode)); } var view = { view_id: false, @@ -4840,7 +4840,7 @@ instance.web.form.FieldBinary = instance.web.form.AbstractField.extend(instance. }, on_file_uploaded: function(size, name, content_type, file_base64) { if (size === false) { - this.do_warn("File Upload", "There was a problem while uploading your file"); + this.do_warn(_t("File Upload"), _t("There was a problem while uploading your file")); // TODO: use openerp web crashmanager console.warn("Error while uploading file : ", name); } else { @@ -5009,7 +5009,7 @@ instance.web.form.FieldMany2ManyBinaryMultiFiles = instance.web.form.AbstractFie this.field_manager = field_manager; this.node = node; if(this.field.type != "many2many" || this.field.relation != 'ir.attachment') { - throw "The type of the field '"+this.field.string+"' must be a many2many field with a relation to 'ir.attachment' model."; + throw _.str.sprintf(_t("The type of the field '%s' must be a many2many field with a relation to 'ir.attachment' model."), this.field.string); } this.ds_file = new instance.web.DataSetSearch(this, 'ir.attachment'); this.fileupload_id = _.uniqueId('oe_fileupload_temp'); diff --git a/addons/web/static/src/js/view_list.js b/addons/web/static/src/js/view_list.js index 13c41d48599..5008d1765a6 100644 --- a/addons/web/static/src/js/view_list.js +++ b/addons/web/static/src/js/view_list.js @@ -389,7 +389,7 @@ instance.web.ListView = instance.web.View.extend( /** @lends instance.web.ListVi if (range_stop > total) { range_stop = total; } - spager = _.str.sprintf('%d-%d of %d', range_start, range_stop, total); + spager = _.str.sprintf(_t("%d-%d of %d"), range_start, range_stop, total); } this.$pager.find('.oe_list_pager_state').text(spager); @@ -887,8 +887,8 @@ instance.web.ListView.List = instance.web.Class.extend( /** @lends instance.web. var $row; if (attribute === 'id') { if (old_value) { - throw new Error("Setting 'id' attribute on existing record " - + JSON.stringify(record.attributes)); + throw new Error(_.str.sprintf( _t("Setting 'id' attribute on existing record %s"), + JSON.stringify(record.attributes) )); } if (!_.contains(self.dataset.ids, value)) { // add record to dataset if not already in (added by @@ -956,7 +956,7 @@ instance.web.ListView.List = instance.web.Class.extend( /** @lends instance.web. if (row_id) { e.stopPropagation(); if (!self.dataset.select_id(row_id)) { - throw new Error("Could not find id in dataset"); + throw new Error(_t("Could not find id in dataset")); } self.row_clicked(e); } @@ -1016,7 +1016,7 @@ instance.web.ListView.List = instance.web.Class.extend( /** @lends instance.web. var command = value[0]; // 1. an array of m2m commands (usually (6, false, ids)) if (command[0] !== 6) { - throw new Error(_t("Unknown m2m command ") + command[0]); + throw new Error(_.str.sprintf( _t("Unknown m2m command %s"), command[0])); } ids = command[2]; } else { @@ -1324,7 +1324,7 @@ instance.web.ListView.Groups = instance.web.Class.extend( /** @lends instance.we } // group_label is html-clean (through format or explicit // escaping if format failed), can inject straight into HTML - $group_column.html(_.str.sprintf("%s (%d)", + $group_column.html(_.str.sprintf(_t("%s (%d)"), group_label, group.length)); if (group.length && group.openable) { @@ -1743,7 +1743,7 @@ var Record = instance.web.Class.extend(/** @lends Record# */{ } else if (val instanceof Array) { output[k] = val[0]; } else { - throw new Error("Can't convert value " + val + " to context"); + throw new Error(_.str.sprintf(_t("Can't convert value %s to context"), val)); } } return output; diff --git a/addons/web/static/src/js/view_list_editable.js b/addons/web/static/src/js/view_list_editable.js index 7fe6a8ec42b..e3f35e2068c 100644 --- a/addons/web/static/src/js/view_list_editable.js +++ b/addons/web/static/src/js/view_list_editable.js @@ -3,7 +3,9 @@ * @namespace */ openerp.web.list_editable = function (instance) { - // editability status of list rows + var _t = instance.web._t; + + // editability status of list rows instance.web.ListView.prototype.defaults.editable = null; // TODO: not sure second @lends on existing item is correct, to check @@ -775,7 +777,7 @@ openerp.web.list_editable = function (instance) { cancel: function (force) { if (!(force || this.form.can_be_discarded())) { return $.Deferred().reject({ - message: "The form's data can not be discarded"}).promise(); + message: _t("The form's data can not be discarded")}).promise(); } var record = this.record; this.record = null; diff --git a/addons/web/static/src/js/views.js b/addons/web/static/src/js/views.js index ddedcdd2ff6..600a0b065c1 100644 --- a/addons/web/static/src/js/views.js +++ b/addons/web/static/src/js/views.js @@ -786,7 +786,7 @@ instance.web.ViewManagerAction = instance.web.ViewManager.extend({ break; case 'tests': this.do_action({ - name: "JS Tests", + name: _t("JS Tests"), target: 'new', type : 'ir.actions.act_url', url: '/web/tests?mod=*' @@ -814,7 +814,7 @@ instance.web.ViewManagerAction = instance.web.ViewManager.extend({ break; case 'translate': this.do_action({ - name: "Technical Translation", + name: _t("Technical Translation"), res_model : 'ir.translation', domain : [['type', '!=', 'object'], '|', ['name', '=', this.dataset.model], ['name', 'ilike', this.dataset.model + ',']], views: [[false, 'list'], [false, 'form']], @@ -1395,7 +1395,7 @@ instance.web.json_node_to_xml = function(node, human_readable, indent) { return sindent + node; } else if (typeof(node.tag) !== 'string' || !node.children instanceof Array || !node.attrs instanceof Object) { throw new Error( - _.str.sprintf("Node [%s] is not a JSONified XML node", + _.str.sprintf(_t("Node [%s] is not a JSONified XML node"), JSON.stringify(node))); } for (var attr in node.attrs) { @@ -1429,7 +1429,7 @@ instance.web.xml_to_str = function(node) { } else if (window.ActiveXObject) { return node.xml; } else { - throw new Error("Could not serialize XML"); + throw new Error(_t("Could not serialize XML")); } }; instance.web.str_to_xml = function(s) { @@ -1437,7 +1437,7 @@ instance.web.str_to_xml = function(s) { var dp = new DOMParser(); var r = dp.parseFromString(s, "text/xml"); if (r.body && r.body.firstChild && r.body.firstChild.nodeName == 'parsererror') { - throw new Error("Could not parse string to xml"); + throw new Error(_t("Could not parse string to xml")); } return r; } @@ -1445,7 +1445,7 @@ instance.web.str_to_xml = function(s) { try { xDoc = new ActiveXObject("MSXML2.DOMDocument"); } catch (e) { - throw new Error("Could not find a DOM Parser: " + e.message); + throw new Error(_.str.sprintf( _t("Could not find a DOM Parser: %s"), e.message)); } xDoc.async = false; xDoc.preserveWhiteSpace = true; diff --git a/addons/web_calendar/static/src/js/calendar.js b/addons/web_calendar/static/src/js/calendar.js index 5fd9b6677a0..46d25e749a2 100644 --- a/addons/web_calendar/static/src/js/calendar.js +++ b/addons/web_calendar/static/src/js/calendar.js @@ -88,7 +88,7 @@ instance.web_calendar.CalendarView = instance.web.View.extend({ this.fields = this.fields_view.fields; if (!this.date_start) { - throw new Error("Calendar view has not defined 'date_start' attribute."); + throw new Error(_t("Calendar view has not defined 'date_start' attribute.")); } //* Calendar Fields * @@ -96,7 +96,7 @@ instance.web_calendar.CalendarView = instance.web.View.extend({ if (this.date_delay) { if (this.fields[this.date_delay].type != 'float') { - throw new Error("Calendar view has a 'date_delay' type != float"); + throw new Error(_t("Calendar view has a 'date_delay' type != float")); } this.calendar_fields.date_delay = {'name': this.date_delay, 'kind': this.fields[this.date_delay].type}; } diff --git a/addons/web_kanban/static/src/js/kanban.js b/addons/web_kanban/static/src/js/kanban.js index 4e9157e1d75..c93d7d333e4 100644 --- a/addons/web_kanban/static/src/js/kanban.js +++ b/addons/web_kanban/static/src/js/kanban.js @@ -409,7 +409,7 @@ instance.web_kanban.KanbanView = instance.web.View.extend({ new_group.do_save_sequences(); }).fail(function(error, evt) { evt.preventDefault(); - alert("An error has occured while moving the record to this group."); + alert(_t("An error has occured while moving the record to this group.")); self.do_reload(); // TODO: use draggable + sortable in order to cancel the dragging when the rcp fails }); } diff --git a/addons/web_view_editor/static/src/js/view_editor.js b/addons/web_view_editor/static/src/js/view_editor.js index a844c0f3be8..6b70914f332 100644 --- a/addons/web_view_editor/static/src/js/view_editor.js +++ b/addons/web_view_editor/static/src/js/view_editor.js @@ -161,7 +161,7 @@ instance.web_view_editor.ViewEditor = instance.web.Widget.extend({ } }); msg += ""; - this.do_warn("The following fields are invalid :", msg); + this.do_warn(_t("The following fields are invalid :"), msg); }, add_node_name : function(node) { if(node.tagName.toLowerCase() == "button" || node.tagName.toLowerCase() == "field"){ @@ -260,7 +260,7 @@ instance.web_view_editor.ViewEditor = instance.web.Widget.extend({ "arch": view_arch_list}); }); } else { - self.do_warn("Please select view in list :"); + self.do_warn(_t("Please select view in list :")); } }); }, @@ -387,10 +387,10 @@ instance.web_view_editor.ViewEditor = instance.web.Widget.extend({ self.inherited_view(selected_row); } }else{ - alert("Can't Update View"); + alert(_t("Can't Update View")); } }else{ - alert("Select an element"); + alert(_t("Select an element")); } }}, {text: _t("Preview"), click: function() { @@ -983,7 +983,7 @@ instance.web_view_editor.ViewEditor = instance.web.Widget.extend({ } else { table_selector.append('' + node.string + '' + type_widget.render() ); if (node.name == "field_value") { - table_selector.append(' '); + table_selector.append(' '); } } type_widget.start(); From e2435d4f004a20636aef8a8ee2cc03c8cfc3e78c Mon Sep 17 00:00:00 2001 From: tsabi <> Date: Thu, 29 Nov 2012 02:18:22 +0100 Subject: [PATCH 02/18] fixed a typo that maked javascript error bzr revid: tsabi-20121129011822-fv9v0l72231y0093 --- addons/web/static/src/js/view_form.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/web/static/src/js/view_form.js b/addons/web/static/src/js/view_form.js index dd9b2be5fb0..06c1a3d989b 100644 --- a/addons/web/static/src/js/view_form.js +++ b/addons/web/static/src/js/view_form.js @@ -872,7 +872,7 @@ instance.web.FormView = instance.web.View.extend(instance.web.form.FieldManagerM }).value(); warnings.unshift(''); - this.do_warn(_t("The following fields are invalid:", warnings.join('')); + this.do_warn(_t("The following fields are invalid:"), warnings.join('')); }, /** * Reload the form after saving From 72109e7541c1748e066ff4fe8b60a3cfa052d247 Mon Sep 17 00:00:00 2001 From: tsabi Date: Thu, 29 Nov 2012 12:53:06 +0100 Subject: [PATCH 03/18] fix tab problem bzr revid: csaba.toth@i3rendszerhaz.hu-20121129115306-ifncjymnmuk989eq --- addons/web/static/src/js/view_list_editable.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/web/static/src/js/view_list_editable.js b/addons/web/static/src/js/view_list_editable.js index e3f35e2068c..17f757d4e72 100644 --- a/addons/web/static/src/js/view_list_editable.js +++ b/addons/web/static/src/js/view_list_editable.js @@ -3,9 +3,9 @@ * @namespace */ openerp.web.list_editable = function (instance) { - var _t = instance.web._t; + var _t = instance.web._t; - // editability status of list rows + // editability status of list rows instance.web.ListView.prototype.defaults.editable = null; // TODO: not sure second @lends on existing item is correct, to check From 83b7823f257b17403a11908c9b359244635cf0b7 Mon Sep 17 00:00:00 2001 From: tsabi Date: Thu, 29 Nov 2012 12:54:54 +0100 Subject: [PATCH 04/18] some more change in the new pyeval.js file bzr revid: csaba.toth@i3rendszerhaz.hu-20121129115454-rpviywfnosjdmovm --- addons/web/static/src/js/pyeval.js | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/addons/web/static/src/js/pyeval.js b/addons/web/static/src/js/pyeval.js index 265449f9f64..417459b3a63 100644 --- a/addons/web/static/src/js/pyeval.js +++ b/addons/web/static/src/js/pyeval.js @@ -2,6 +2,7 @@ * py.js helpers and setup */ openerp.web.pyeval = function (instance) { + var _t = instance.web._t; instance.web.pyeval = {}; var obj = function () {}; @@ -71,7 +72,7 @@ openerp.web.pyeval = function (instance) { var ymd2ord = function (year, month, day) { var dim = days_in_month(year, month); if (!(1 <= day && day <= dim)) { - throw new Error("ValueError: day must be in 1.." + dim); + throw new Error(_.str.sprintf(_t("ValueError: day must be in 1..%d"), dim)); } return days_before_year(year) + days_before_month(year, month) @@ -277,10 +278,11 @@ openerp.web.pyeval = function (instance) { }); var s = _.str.sprintf("%d:%02d:%02d", hh, mm, ss); if (this.days) { - s = _.str.sprintf("%d day%s, %s", - this.days, - (this.days != 1 && this.days != -1) ? 's' : '', - s); + if (this.days != 1 && this.days != -1) { + s = _.str.sprintf(_t("%d days, %s"), this.days, s); + } else { + s = _.str.sprintf(_t("%d day, %s"), this.days, s); + }; } if (this.microseconds) { s = _.str.sprintf("%s.%06d", s, this.microseconds); @@ -726,7 +728,7 @@ openerp.web.pyeval = function (instance) { case 'context': case 'compound_context': return instance.web.pyeval.eval('contexts', [arg]); default: - throw new Error(instance.web._t("Unknown nonliteral type " + arg.__ref)); + throw new Error(_t("Unknown nonliteral type ") + arg.__ref); } }; /** @@ -760,11 +762,11 @@ openerp.web.pyeval = function (instance) { } catch (e) { d.resolve({ error: { code: 400, - message: instance.web._t("Evaluation Error"), + message: _t("Evaluation Error"), data: { type: 'local_exception', debug: _.str.sprintf( - instance.web._t("Local evaluation failure\n%s\n\n%s"), + _t("Local evaluation failure\n%s\n\n%s"), e.message, JSON.stringify(source)) } }}); From 7bfab22e1f6699890d79512f2b7f8ac486fa52f0 Mon Sep 17 00:00:00 2001 From: Fabien Meghazi Date: Thu, 29 Nov 2012 13:07:38 +0100 Subject: [PATCH 05/18] [FIX] Propagate context to kanban's add_group() action bzr revid: fme@openerp.com-20121129120738-fgulo5hqib2uqeqa --- addons/web_kanban/static/src/js/kanban.js | 1 + 1 file changed, 1 insertion(+) diff --git a/addons/web_kanban/static/src/js/kanban.js b/addons/web_kanban/static/src/js/kanban.js index 4e9157e1d75..4eabcf0533b 100644 --- a/addons/web_kanban/static/src/js/kanban.js +++ b/addons/web_kanban/static/src/js/kanban.js @@ -190,6 +190,7 @@ instance.web_kanban.KanbanView = instance.web.View.extend({ views: [[false, 'form']], type: 'ir.actions.act_window', target: "new", + context: self.dataset.get_context(), flags: { action_buttons: true, } From bd61641572949ab2c9b1a07267cd7d7344d17a7d Mon Sep 17 00:00:00 2001 From: Fabien Pinckaers Date: Thu, 29 Nov 2012 14:06:55 +0100 Subject: [PATCH 06/18] [FIX] project issue bzr revid: fp@tinyerp.com-20121129130655-rm5hrk8m7tsy8g4v --- addons/project/project.py | 6 ++++++ addons/project/project_demo.xml | 21 +++++++++++++++++++-- 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/addons/project/project.py b/addons/project/project.py index c6577b00e6a..b7c88f3532b 100644 --- a/addons/project/project.py +++ b/addons/project/project.py @@ -49,11 +49,17 @@ class project_task_type(osv.osv): 'fold': fields.boolean('Hide in views if empty', help="This stage is not visible, for example in status bar or kanban view, when there are no records in that stage to display."), } + def _get_default_project_id(self, cr, uid, ctx={}): + proj = ctx.get('default_project_id', False) + if type(proj) is int: + return [proj] + return proj _defaults = { 'sequence': 1, 'state': 'open', 'fold': False, 'case_default': True, + 'project_ids': _get_default_project_id } _order = 'sequence' diff --git a/addons/project/project_demo.xml b/addons/project/project_demo.xml index ee887c2728c..d2bf7d0a2df 100644 --- a/addons/project/project_demo.xml +++ b/addons/project/project_demo.xml @@ -36,6 +36,10 @@ Implement new website for Sale and Warehouse Management for a customer. project.task + + + + @@ -45,6 +49,10 @@ public project.task + + + + @@ -58,6 +66,9 @@ + + + @@ -67,24 +78,30 @@ Website Design Templates project.task - + + + + 2 Data Import/Export Plugin project.task - + + + + From 9f76458404ff3d99824149d09121952c4f2fc775 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Thu, 29 Nov 2012 14:13:01 +0100 Subject: [PATCH 07/18] [FIX] groupby on editable list Because of the "meta" columns (e.g. group name column), ListView#columns would end up with a different number of elements than ListView#fields_view.arch.children, and when zipping them together (to build the form view for edition) things wouldn't match anymore. It would seem simply filtering out meta columns (and only keep those actually specified by the view) is sufficient to fix the issue and have everything line up again. I'm midly impressed. bzr revid: xmo@openerp.com-20121129131301-scc38i4l55ea7lis --- addons/web/static/src/js/view_list_editable.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/addons/web/static/src/js/view_list_editable.js b/addons/web/static/src/js/view_list_editable.js index 7fe6a8ec42b..79b91a41b3c 100644 --- a/addons/web/static/src/js/view_list_editable.js +++ b/addons/web/static/src/js/view_list_editable.js @@ -383,7 +383,8 @@ openerp.web.list_editable = function (instance) { version: '7.0' }); _(view.arch.children).chain() - .zip(this.columns) + .zip(_(this.columns).filter(function (c) { + return !(c instanceof instance.web.list.MetaColumn);})) .each(function (ar) { var widget = ar[0], column = ar[1]; var modifiers = _.extend({}, column.modifiers); From 759f11f11077514bbf5e45ffa88a69ec1d0066ef Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Thu, 29 Nov 2012 14:27:38 +0100 Subject: [PATCH 08/18] [FIX] py.js: bug in tokenization of single-quoted empty string bzr revid: xmo@openerp.com-20121129132738-fcnam8bkqyt7h8ey --- addons/web/static/lib/py.js/.hg_archival.txt | 4 ++-- addons/web/static/lib/py.js/lib/py.js | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/addons/web/static/lib/py.js/.hg_archival.txt b/addons/web/static/lib/py.js/.hg_archival.txt index 33dcdd88830..771b798ac84 100644 --- a/addons/web/static/lib/py.js/.hg_archival.txt +++ b/addons/web/static/lib/py.js/.hg_archival.txt @@ -1,5 +1,5 @@ repo: 076b192d0d8ab2b92d1dbcfa3da055382f30eaea -node: ccf62e5d0291f66a39f4049f3e880004e59c3654 +node: 2b62048dd1d86c45e4bf0442b5da4122534132bf branch: default latesttag: 0.7 -latesttagdistance: 4 +latesttagdistance: 5 diff --git a/addons/web/static/lib/py.js/lib/py.js b/addons/web/static/lib/py.js/lib/py.js index 854232a0d80..04ecd3aeb5c 100644 --- a/addons/web/static/lib/py.js/lib/py.js +++ b/addons/web/static/lib/py.js/lib/py.js @@ -311,7 +311,7 @@ var py = {}; } else if (string_pattern.test(token)) { var m = string_pattern.exec(token); tokens.push(create(symbols['(string)'], { - value: m[2] || m[3] + value: (m[2] !== undefined ? m[2] : m[3]) })); } else if (token in symbols) { var symbol; From 184593003b3aec7d40660ae13002f4a4a205fa12 Mon Sep 17 00:00:00 2001 From: niv-openerp Date: Thu, 29 Nov 2012 14:40:51 +0100 Subject: [PATCH 09/18] [FIX] race condition problem with m2m bzr revid: nicolas.vanhoren@openerp.com-20121129134051-5hiw9z5hi99fxtve --- addons/web/static/src/js/view_form.js | 76 ++++++++++++--------------- 1 file changed, 35 insertions(+), 41 deletions(-) diff --git a/addons/web/static/src/js/view_form.js b/addons/web/static/src/js/view_form.js index 49f4e30815f..ad5fcdd29d8 100644 --- a/addons/web/static/src/js/view_form.js +++ b/addons/web/static/src/js/view_form.js @@ -4069,13 +4069,12 @@ instance.web.form.FieldMany2ManyTags = instance.web.form.AbstractField.extend(in If you see this options, do not use it, it's basically a dirty hack to make one precise o2m to behave the way we want. */ -instance.web.form.FieldMany2Many = instance.web.form.AbstractField.extend({ +instance.web.form.FieldMany2Many = instance.web.form.AbstractField.extend(instance.web.form.ReinitializeFieldMixin, { multi_selection: false, disable_utility_classes: true, init: function(field_manager, node) { this._super(field_manager, node); this.is_loaded = $.Deferred(); - this.initial_is_loaded = this.is_loaded; this.dataset = new instance.web.form.Many2ManyDataSet(this, this.field.relation); this.dataset.m2m = this; var self = this; @@ -4083,24 +4082,44 @@ instance.web.form.FieldMany2Many = instance.web.form.AbstractField.extend({ self.dataset_changed(); }); this.set_value([]); + this.list_dm = new instance.web.DropMisordered(); + this.render_value_dm = new instance.web.DropMisordered(); }, - start: function() { - this.$el.addClass('oe_form_field oe_form_field_many2many'); - + initialize_content: function() { var self = this; - self.load_view(); - this.is_loaded.done(function() { - self.on("change:effective_readonly", self, function() { - self.is_loaded = self.is_loaded.then(function() { - self.list_view.destroy(); - return $.when(self.load_view()).done(function() { - self.render_value(); - }); - }); + this.$el.addClass('oe_form_field oe_form_field_many2many'); + + this.list_view = new instance.web.form.Many2ManyListView(this, this.dataset, false, { + 'addable': this.get("effective_readonly") ? null : _t("Add"), + 'deletable': this.get("effective_readonly") ? false : true, + 'selectable': this.multi_selection, + 'sortable': false, + 'reorderable': false, + 'import_enabled': false, }); + var embedded = (this.field.views || {}).tree; + if (embedded) { + this.list_view.set_embedded_view(embedded); + } + this.list_view.m2m_field = this; + var loaded = $.Deferred(); + this.list_view.on("list_view_loaded", this, function() { + loaded.resolve(); }); - this._super.apply(this, arguments); + this.list_view.appendTo(this.$el); + + var old_def = self.is_loaded; + self.is_loaded = $.Deferred().done(function() { + old_def.resolve(); + }); + this.list_dm.add(loaded).then(function() { + self.is_loaded.resolve(); + }); + }, + destroy_content: function() { + this.list_view.destroy(); + this.list_view = undefined; }, set_value: function(value_) { value_ = value_ || []; @@ -4115,35 +4134,10 @@ instance.web.form.FieldMany2Many = instance.web.form.AbstractField.extend({ is_false: function () { return _(this.get("value")).isEmpty(); }, - load_view: function() { - var self = this; - this.list_view = new instance.web.form.Many2ManyListView(this, this.dataset, false, { - 'addable': self.get("effective_readonly") ? null : _t("Add"), - 'deletable': self.get("effective_readonly") ? false : true, - 'selectable': self.multi_selection, - 'sortable': false, - 'reorderable': false, - 'import_enabled': false, - }); - var embedded = (this.field.views || {}).tree; - if (embedded) { - this.list_view.set_embedded_view(embedded); - } - this.list_view.m2m_field = this; - var loaded = $.Deferred(); - this.list_view.on("list_view_loaded", self, function() { - self.initial_is_loaded.resolve(); - loaded.resolve(); - }); - $.async_when().done(function () { - self.list_view.appendTo(self.$el); - }); - return loaded; - }, render_value: function() { var self = this; this.dataset.set_ids(this.get("value")); - this.is_loaded = this.is_loaded.then(function() { + this.render_value_dm.add(this.is_loaded).then(function() { return self.list_view.reload_content(); }); }, From 001c45160831ea3bb7e735bad82d2d4043cc7b8b Mon Sep 17 00:00:00 2001 From: Vo Minh Thu Date: Thu, 29 Nov 2012 15:07:45 +0100 Subject: [PATCH 10/18] [REV] reverted install-all commit (vmt@openerp.com-20121128142106-pdkcruhyz0sjltk8) bzr revid: vmt@openerp.com-20121129140745-wn2o9ek3beuf7y3y --- openerp/cli/server.py | 10 ++---- openerp/modules/graph.py | 24 +++++++++------ openerp/modules/loading.py | 63 +++++++++++++++++++------------------- 3 files changed, 48 insertions(+), 49 deletions(-) diff --git a/openerp/cli/server.py b/openerp/cli/server.py index 9352ad37ef0..f030f801967 100644 --- a/openerp/cli/server.py +++ b/openerp/cli/server.py @@ -94,11 +94,7 @@ def setup_pid_file(): def preload_registry(dbname): """ Preload a registry, and start the cron.""" try: - config = openerp.tools.config - update_module = True if config['init'] or config['update'] else False - db, registry = openerp.pooler.get_db_and_pool( - dbname, update_module=update_module, pooljobs=False, - force_demo=not config['without_demo']) + db, registry = openerp.pooler.get_db_and_pool(dbname, update_module=openerp.tools.config['init'] or openerp.tools.config['update'], pooljobs=False) # jobs will start to be processed later, when openerp.cron.start_master_thread() is called by openerp.service.start_services() registry.schedule_cron_jobs() @@ -109,9 +105,7 @@ def run_test_file(dbname, test_file): """ Preload a registry, possibly run a test file, and start the cron.""" try: config = openerp.tools.config - update_module = True if config['init'] or config['update'] else False - db, registry = openerp.pooler.get_db_and_pool( - dbname, update_module=update_module, pooljobs=False, force_demo=not config['without_demo']) + db, registry = openerp.pooler.get_db_and_pool(dbname, update_module=config['init'] or config['update'], pooljobs=False) cr = db.cursor() _logger.info('loading test file %s', test_file) openerp.tools.convert_yaml_import(cr, 'base', file(test_file), 'test', {}, 'test', True) diff --git a/openerp/modules/graph.py b/openerp/modules/graph.py index f7e9bc7c77a..56b17e3239a 100644 --- a/openerp/modules/graph.py +++ b/openerp/modules/graph.py @@ -87,19 +87,15 @@ class Graph(dict): for k, v in additional_data[package.name].items(): setattr(package, k, v) - def add_module(self, cr, module, force_demo=False): - self.add_modules(cr, [module], force_demo) + def add_module(self, cr, module, force=None): + self.add_modules(cr, [module], force) - def add_modules(self, cr, module_list, force_demo=False): + def add_modules(self, cr, module_list, force=None): + if force is None: + force = [] packages = [] len_graph = len(self) for module in module_list: - if force_demo: - cr.execute(""" - UPDATE ir_module_module - SET demo='t' - WHERE name = %s""", - (module,)) # This will raise an exception if no/unreadable descriptor file. # NOTE The call to load_information_from_description_file is already # done by db.initialize, so it is possible to not do it again here. @@ -125,6 +121,9 @@ class Graph(dict): current.remove(package) node = self.add_node(package, info) node.data = info + for kind in ('init', 'demo', 'update'): + if package in tools.config[kind] or 'all' in tools.config[kind] or kind in force: + setattr(node, kind, True) else: later.add(package) packages.append((package, info)) @@ -186,11 +185,18 @@ class Node(Singleton): node.depth = self.depth + 1 if node not in self.children: self.children.append(node) + for attr in ('init', 'update', 'demo'): + if hasattr(self, attr): + setattr(node, attr, True) self.children.sort(lambda x, y: cmp(x.name, y.name)) return node def __setattr__(self, name, value): super(Singleton, self).__setattr__(name, value) + if name in ('init', 'update', 'demo'): + tools.config[name][self.name] = 1 + for child in self.children: + setattr(child, name, value) if name == 'depth': for child in self.children: setattr(child, name, value + 1) diff --git a/openerp/modules/loading.py b/openerp/modules/loading.py index 13b02bd7a6e..bcda1690c91 100644 --- a/openerp/modules/loading.py +++ b/openerp/modules/loading.py @@ -42,7 +42,6 @@ from openerp import SUPERUSER_ID from openerp import SUPERUSER_ID from openerp.tools.translate import _ -from openerp.tools import assertion_report from openerp.modules.module import initialize_sys_path, \ load_openerp_module, init_module_models @@ -158,7 +157,7 @@ def load_module_graph(cr, graph, status=None, perform_checks=True, skip_modules= models = pool.load(cr, package) loaded_modules.append(package.name) - if package.state in ('to install', 'to upgrade'): + if hasattr(package, 'init') or hasattr(package, 'update') or package.state in ('to install', 'to upgrade'): init_module_models(cr, package.name, models) pool._init_modules.add(package.name) status['progress'] = float(index) / len(graph) @@ -172,19 +171,18 @@ def load_module_graph(cr, graph, status=None, perform_checks=True, skip_modules= idref = {} - if package.state == 'to install': + mode = 'update' + if hasattr(package, 'init') or package.state == 'to install': mode = 'init' - else: - mode = 'update' - if package.state in ('to install', 'to upgrade'): + if hasattr(package, 'init') or hasattr(package, 'update') or package.state in ('to install', 'to upgrade'): if package.state=='to upgrade': # upgrading the module information modobj.write(cr, SUPERUSER_ID, [module_id], modobj.get_values_from_terp(package.data)) load_init_xml(module_name, idref, mode) load_update_xml(module_name, idref, mode) load_data(module_name, idref, mode) - if package.dbdemo and package.state != 'installed': + if hasattr(package, 'demo') or (package.dbdemo and package.state != 'installed'): status['progress'] = (index + 0.75) / len(graph) load_demo_xml(module_name, idref, mode) load_demo(module_name, idref, mode) @@ -214,6 +212,9 @@ def load_module_graph(cr, graph, status=None, perform_checks=True, skip_modules= modobj.update_translations(cr, SUPERUSER_ID, [module_id], None) package.state = 'installed' + for kind in ('init', 'demo', 'update'): + if hasattr(package, kind): + delattr(package, kind) cr.commit() @@ -268,7 +269,10 @@ def load_modules(db, force_demo=False, status=None, update_module=False): if not openerp.modules.db.is_initialized(cr): _logger.info("init db") openerp.modules.db.initialize(cr) - update_module = True + tools.config["init"]["all"] = 1 + tools.config['update']['all'] = 1 + if not tools.config['without_demo']: + tools.config["demo"]['all'] = 1 # This is a brand new pool, just created in pooler.get_db_and_pool() pool = pooler.get_pool(cr.dbname) @@ -278,51 +282,43 @@ def load_modules(db, force_demo=False, status=None, update_module=False): # STEP 1: LOAD BASE (must be done before module dependencies can be computed for later steps) graph = openerp.modules.graph.Graph() - graph.add_module(cr, 'base', force_demo) + graph.add_module(cr, 'base', force) if not graph: _logger.critical('module base cannot be loaded! (hint: verify addons-path)') raise osv.osv.except_osv(_('Could not load base module'), _('module base cannot be loaded! (hint: verify addons-path)')) # processed_modules: for cleanup step after install # loaded_modules: to avoid double loading - # After load_module_graph(), 'base' has been installed or updated and its state is 'installed'. - report = assertion_report.assertion_report() - loaded_modules, processed_modules = load_module_graph(cr, graph, status, report=report) + report = pool._assertion_report + loaded_modules, processed_modules = load_module_graph(cr, graph, status, perform_checks=(not update_module), report=report) if tools.config['load_language']: for lang in tools.config['load_language'].split(','): tools.load_language(cr, lang) # STEP 2: Mark other modules to be loaded/updated - # This is a one-shot use of tools.config[init|update] from the command line - # arguments. It is directly cleared to not interfer with later create/update - # issued via RPC. if update_module: modobj = pool.get('ir.module.module') - if ('base' in tools.config['init']) or ('base' in tools.config['update']) \ - or ('all' in tools.config['init']) or ('all' in tools.config['update']): + if ('base' in tools.config['init']) or ('base' in tools.config['update']): _logger.info('updating modules list') modobj.update_list(cr, SUPERUSER_ID) - if 'all' in tools.config['init']: - ids = modobj.search(cr, 1, []) - tools.config['init'] = dict.fromkeys([m['name'] for m in modobj.read(cr, 1, ids, ['name'])], 1) - _check_module_names(cr, itertools.chain(tools.config['init'].keys(), tools.config['update'].keys())) - mods = [k for k in tools.config['init'] if tools.config['init'][k] and k not in ('base', 'all')] - ids = modobj.search(cr, SUPERUSER_ID, ['&', ('state', '=', 'uninstalled'), ('name', 'in', mods)]) - if ids: - modobj.button_install(cr, SUPERUSER_ID, ids) # goes from 'uninstalled' to 'to install' + mods = [k for k in tools.config['init'] if tools.config['init'][k]] + if mods: + ids = modobj.search(cr, SUPERUSER_ID, ['&', ('state', '=', 'uninstalled'), ('name', 'in', mods)]) + if ids: + modobj.button_install(cr, SUPERUSER_ID, ids) - mods = [k for k in tools.config['update'] if tools.config['update'][k] and k not in ('base', 'all')] - ids = modobj.search(cr, SUPERUSER_ID, ['&', ('state', '=', 'installed'), ('name', 'in', mods)]) - if ids: - modobj.button_upgrade(cr, SUPERUSER_ID, ids) # goes from 'installed' to 'to upgrade' + mods = [k for k in tools.config['update'] if tools.config['update'][k]] + if mods: + ids = modobj.search(cr, SUPERUSER_ID, ['&', ('state', '=', 'installed'), ('name', 'in', mods)]) + if ids: + modobj.button_upgrade(cr, SUPERUSER_ID, ids) + + cr.execute("update ir_module_module set state=%s where name=%s", ('installed', 'base')) - # Remove that funky global one-shot thingy. - for kind in ('init', 'demo', 'update'): - tools.config[kind] = {} # STEP 3: Load marked modules (skipping base which was done in STEP 1) # IMPORTANT: this is done in two parts, first loading all installed or @@ -374,6 +370,9 @@ def load_modules(db, force_demo=False, status=None, update_module=False): # Cleanup orphan records pool.get('ir.model.data')._process_end(cr, SUPERUSER_ID, processed_modules) + for kind in ('init', 'demo', 'update'): + tools.config[kind] = {} + cr.commit() # STEP 5: Cleanup menus From c166c19ed18a2737d7a885641ebb7b0d25f2b0ed Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Thu, 29 Nov 2012 15:17:59 +0100 Subject: [PATCH 11/18] [REM] dead code from evaluation being client-side only bzr revid: xmo@openerp.com-20121129141759-wj4je85nkrfznql1 --- addons/web/session.py | 30 ------------------------------ 1 file changed, 30 deletions(-) diff --git a/addons/web/session.py b/addons/web/session.py index 523aaa9f1fa..65e3beab84a 100644 --- a/addons/web/session.py +++ b/addons/web/session.py @@ -188,34 +188,4 @@ class OpenERPSession(object): context['lang'] = lang - @property - def base_eval_context(self): - """ Default evaluation context for the session. - - Used to evaluate contexts and domains. - """ - base = dict( - uid=self._uid, - current_date=datetime.date.today().strftime('%Y-%m-%d'), - time=time, - datetime=datetime, - relativedelta=dateutil.relativedelta.relativedelta - ) - base.update(self.context) - return base - - def evaluation_context(self, context=None): - """ Returns the session's evaluation context, augmented with the - provided context if any. - - :param dict context: to add merge in the session's base eval context - :returns: the augmented context - :rtype: dict - """ - d = dict(self.base_eval_context) - if context: - d.update(context) - d['context'] = d - return d - # vim:et:ts=4:sw=4: From 5b71f38603fb198bce32b810ecde04276744ae6b Mon Sep 17 00:00:00 2001 From: Fabien Pinckaers Date: Thu, 29 Nov 2012 15:52:19 +0100 Subject: [PATCH 12/18] [FIX] bzr revid: fp@tinyerp.com-20121129145219-q6wqvzy61mki2j26 --- addons/project/project_demo.xml | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/addons/project/project_demo.xml b/addons/project/project_demo.xml index d2bf7d0a2df..f5fbf878fd0 100644 --- a/addons/project/project_demo.xml +++ b/addons/project/project_demo.xml @@ -40,7 +40,7 @@ - + @@ -53,7 +53,7 @@ - + @@ -63,13 +63,11 @@ project.task public - + - + @@ -78,13 +76,11 @@ Website Design Templates project.task - + - + @@ -99,7 +95,7 @@ - + From 64c486e59f1b093bfbf1461b7462b7fccafdcd05 Mon Sep 17 00:00:00 2001 From: Christophe Simonis Date: Thu, 29 Nov 2012 16:20:38 +0100 Subject: [PATCH 13/18] [FIX] setup.py: include docutils on windows bzr revid: chs@openerp.com-20121129152038-hx3km5x55x0oj9r1 --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 6efec4e6125..4f1435c0603 100755 --- a/setup.py +++ b/setup.py @@ -64,7 +64,7 @@ def py2exe_options(): "skip_archive": 1, "optimize": 2, "dist_dir": 'dist', - "packages": [ "DAV", "HTMLParser", "PIL", "asynchat", "asyncore", "commands", "dateutil", "decimal", "email", "encodings", "imaplib", "lxml", "lxml._elementpath", "lxml.builder", "lxml.etree", "lxml.objectify", "mako", "openerp", "poplib", "pychart", "pydot", "pyparsing", "reportlab", "select", "simplejson", "smtplib", "uuid", "vatnumber", "vobject", "xml", "xml.dom", "yaml", ], + "packages": [ "DAV", "HTMLParser", "PIL", "asynchat", "asyncore", "commands", "dateutil", "decimal", "docutils", "email", "encodings", "imaplib", "lxml", "lxml._elementpath", "lxml.builder", "lxml.etree", "lxml.objectify", "mako", "openerp", "poplib", "pychart", "pydot", "pyparsing", "reportlab", "select", "simplejson", "smtplib", "uuid", "vatnumber", "vobject", "xml", "xml.dom", "yaml", ], "excludes" : ["Tkconstants","Tkinter","tcl"], } } From cd9e7a32652aeecaac15f199f25a22e21b505ca1 Mon Sep 17 00:00:00 2001 From: "dle@openerp.com" <> Date: Thu, 29 Nov 2012 16:24:44 +0100 Subject: [PATCH 14/18] [FIX]Hide useless columns in bank statement bzr revid: dle@openerp.com-20121129152444-vislwoifnro7khcw --- .../account_bank_statement_view.xml | 6 +++--- addons/account_voucher/account_voucher_view.xml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/addons/account_bank_statement_extensions/account_bank_statement_view.xml b/addons/account_bank_statement_extensions/account_bank_statement_view.xml index adc2963c803..d64eb68bc99 100644 --- a/addons/account_bank_statement_extensions/account_bank_statement_view.xml +++ b/addons/account_bank_statement_extensions/account_bank_statement_view.xml @@ -43,10 +43,10 @@ - - + + - + diff --git a/addons/account_voucher/account_voucher_view.xml b/addons/account_voucher/account_voucher_view.xml index 4dc753deedc..1e1481c3f2b 100644 --- a/addons/account_voucher/account_voucher_view.xml +++ b/addons/account_voucher/account_voucher_view.xml @@ -213,7 +213,7 @@ - + From cc6f0aa20a558e24886d48d5746a95994893295a Mon Sep 17 00:00:00 2001 From: niv-openerp Date: Thu, 29 Nov 2012 16:36:01 +0100 Subject: [PATCH 15/18] [FIX] potential problem with pyeval datetime/date today()/now() methods. Now only returns the same timezone than server (UTC). bzr revid: nicolas.vanhoren@openerp.com-20121129153601-vtpnvkc0vylo9hux --- addons/web/static/src/js/pyeval.js | 10 +++++----- addons/web/static/test/evals.js | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/addons/web/static/src/js/pyeval.js b/addons/web/static/src/js/pyeval.js index 265449f9f64..68a7453c958 100644 --- a/addons/web/static/src/js/pyeval.js +++ b/addons/web/static/src/js/pyeval.js @@ -398,14 +398,14 @@ openerp.web.pyeval = function (instance) { now: py.classmethod.fromJSON(function () { var d = new Date(); return py.PY_call(datetime.datetime, - [d.getFullYear(), d.getMonth() + 1, d.getDate(), - d.getHours(), d.getMinutes(), d.getSeconds(), - d.getMilliseconds() * 1000]); + [d.getUTCFullYear(), d.getUTCMonth() + 1, d.getUTCDate(), + d.getUTCHours(), d.getUTCMinutes(), d.getUTCSeconds(), + d.getUTCMilliseconds() * 1000]); }), today: py.classmethod.fromJSON(function () { var d = new Date(); return py.PY_call(datetime.datetime, - [d.getFullYear(), d.getMonth() + 1, d.getDate()]); + [d.getUTCFullYear(), d.getUTCMonth() + 1, d.getUTCDate()]); }), combine: py.classmethod.fromJSON(function () { var args = py.PY_parseArgs(arguments, 'date time'); @@ -442,7 +442,7 @@ openerp.web.pyeval = function (instance) { today: py.classmethod.fromJSON(function () { var d = new Date(); return py.PY_call( - datetime.date, [d.getFullYear(), d.getMonth() + 1, d.getDate()]); + datetime.date, [d.getUTCFullYear(), d.getUTCMonth() + 1, d.getUTCDate()]); }), __eq__: function (other) { return (this.year === other.year diff --git a/addons/web/static/test/evals.js b/addons/web/static/test/evals.js index 8e836dade7e..ac6e1f8b0f8 100644 --- a/addons/web/static/test/evals.js +++ b/addons/web/static/test/evals.js @@ -16,8 +16,8 @@ openerp.testing.section('eval.types', { strictEqual( py.eval("time.strftime('%Y-%m-%d %H:%M:%S')", context), _.str.sprintf('%04d-%02d-%02d %02d:%02d:%02d', - d.getFullYear(), d.getMonth() + 1, d.getDate(), - d.getHours(), d.getMinutes(), d.getSeconds())); + d.getUTCFullYear(), d.getUTCMonth() + 1, d.getUTCDate(), + d.getUTCHours(), d.getUTCMinutes(), d.getUTCSeconds())); }); // Port from pypy/lib_pypy/test_datetime.py var makeEq = function (instance, c2) { From f9b9e7c4cb040d6dce43e8ba3616a1453a1d0db9 Mon Sep 17 00:00:00 2001 From: niv-openerp Date: Thu, 29 Nov 2012 17:07:46 +0100 Subject: [PATCH 16/18] [IMP] added context_today() bzr revid: nicolas.vanhoren@openerp.com-20121129160746-c3c691zk5fxhzse0 --- addons/web/static/src/js/pyeval.js | 17 ++++++++++++----- addons/web/static/test/evals.js | 7 +++++++ 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/addons/web/static/src/js/pyeval.js b/addons/web/static/src/js/pyeval.js index 68a7453c958..4ee9fea0584 100644 --- a/addons/web/static/src/js/pyeval.js +++ b/addons/web/static/src/js/pyeval.js @@ -402,11 +402,6 @@ openerp.web.pyeval = function (instance) { d.getUTCHours(), d.getUTCMinutes(), d.getUTCSeconds(), d.getUTCMilliseconds() * 1000]); }), - today: py.classmethod.fromJSON(function () { - var d = new Date(); - return py.PY_call(datetime.datetime, - [d.getUTCFullYear(), d.getUTCMonth() + 1, d.getUTCDate()]); - }), combine: py.classmethod.fromJSON(function () { var args = py.PY_parseArgs(arguments, 'date time'); return py.PY_call(datetime.datetime, [ @@ -479,6 +474,17 @@ openerp.web.pyeval = function (instance) { return py.PY_call(datetime.date, [year, month, day]) } }); + /** + Returns the current local date, which means the date on the client (which can be different + compared to the date of the server). + + @return {datetime.date} + */ + var context_today = function() { + var d = new Date(); + return py.PY_call( + datetime.date, [d.getFullYear(), d.getMonth() + 1, d.getDate()]); + }; datetime.time = py.type('time', null, { __init__: function () { var zero = py.float.fromJSON(0); @@ -691,6 +697,7 @@ openerp.web.pyeval = function (instance) { return { uid: py.float.fromJSON(instance.session.uid), datetime: datetime, + context_today: context_today, time: time, relativedelta: relativedelta, current_date: py.PY_call( diff --git a/addons/web/static/test/evals.js b/addons/web/static/test/evals.js index ac6e1f8b0f8..e2dab6e9a17 100644 --- a/addons/web/static/test/evals.js +++ b/addons/web/static/test/evals.js @@ -19,6 +19,13 @@ openerp.testing.section('eval.types', { d.getUTCFullYear(), d.getUTCMonth() + 1, d.getUTCDate(), d.getUTCHours(), d.getUTCMinutes(), d.getUTCSeconds())); }); + test('context_today', function (instance) { + var d = new Date(); + var context = instance.web.pyeval.context(); + strictEqual( + py.eval("context_today().strftime('%Y-%m-%d')", context), + String(_.str.sprintf('%04d-%02d-%02d', d.getFullYear(), d.getMonth() + 1, d.getDate()))); + }); // Port from pypy/lib_pypy/test_datetime.py var makeEq = function (instance, c2) { var ctx = instance.web.pyeval.context(); From f56badd8252fa62726f68266567d17f5181aa73f Mon Sep 17 00:00:00 2001 From: Fabien Pinckaers Date: Thu, 29 Nov 2012 17:14:58 +0100 Subject: [PATCH 17/18] [IMP] project_issue private note for phu bzr revid: fp@tinyerp.com-20121129161458-232bfavt2f9lln41 --- addons/project_issue/project_issue.py | 2 +- addons/project_issue/project_issue_view.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/project_issue/project_issue.py b/addons/project_issue/project_issue.py index fe5ce9f325b..55aa0fd557b 100644 --- a/addons/project_issue/project_issue.py +++ b/addons/project_issue/project_issue.py @@ -225,7 +225,7 @@ class project_issue(base_stage, osv.osv): Define Responsible user and Email account for mail gateway.'), 'partner_id': fields.many2one('res.partner', 'Contact', select=1), 'company_id': fields.many2one('res.company', 'Company'), - 'description': fields.text('Description'), + 'description': fields.text('Private Note'), 'state': fields.related('stage_id', 'state', type="selection", store=True, selection=_ISSUE_STATE, string="Status", readonly=True, help='The status is set to \'Draft\', when a case is created.\ diff --git a/addons/project_issue/project_issue_view.xml b/addons/project_issue/project_issue_view.xml index 9e25fbca6a6..b7cdfbb0372 100644 --- a/addons/project_issue/project_issue_view.xml +++ b/addons/project_issue/project_issue_view.xml @@ -130,7 +130,7 @@ - + From 720f9093bcfff0996764e655a5b48bfa51062682 Mon Sep 17 00:00:00 2001 From: Fabien Pinckaers Date: Thu, 29 Nov 2012 17:25:31 +0100 Subject: [PATCH 18/18] [IMP] layout issue forms bzr revid: fp@tinyerp.com-20121129162531-26hx9nwmq7f94kp4 --- addons/project_issue/project_issue_view.xml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/addons/project_issue/project_issue_view.xml b/addons/project_issue/project_issue_view.xml index b7cdfbb0372..60cc6448a46 100644 --- a/addons/project_issue/project_issue_view.xml +++ b/addons/project_issue/project_issue_view.xml @@ -111,21 +111,21 @@ - - - + + + +