[MERGE] from trunk
authorFrédéric van der Essen <fva@openerp.com>
Thu, 20 Mar 2014 13:40:17 +0000 (14:40 +0100)
committerFrédéric van der Essen <fva@openerp.com>
Thu, 20 Mar 2014 13:40:17 +0000 (14:40 +0100)
bzr revid: fva@openerp.com-20140320134017-wi6qdofziia3q12l

506 files changed:
addons/hw_escpos/controllers/main.py
addons/hw_escpos/escpos/constants.py
addons/hw_escpos/escpos/escpos.py
addons/web/__init__.py
addons/web/__openerp__.py
addons/web/cli/__init__.py [new file with mode: 0644]
addons/web/cli/test_js.py [new file with mode: 0644]
addons/web/controllers/main.py
addons/web/controllers/testing.py
addons/web/i18n/ar.po
addons/web/i18n/bg.po
addons/web/i18n/bn.po
addons/web/i18n/bs.po
addons/web/i18n/ca.po
addons/web/i18n/cs.po
addons/web/i18n/da.po
addons/web/i18n/de.po
addons/web/i18n/en_AU.po
addons/web/i18n/en_GB.po
addons/web/i18n/es.po
addons/web/i18n/es_CL.po
addons/web/i18n/es_CR.po
addons/web/i18n/es_DO.po
addons/web/i18n/es_EC.po
addons/web/i18n/es_MX.po
addons/web/i18n/es_PE.po
addons/web/i18n/et.po
addons/web/i18n/eu.po
addons/web/i18n/fa.po
addons/web/i18n/fi.po
addons/web/i18n/fr.po
addons/web/i18n/fr_CA.po
addons/web/i18n/gl.po
addons/web/i18n/gu.po
addons/web/i18n/he.po
addons/web/i18n/hi.po
addons/web/i18n/hr.po
addons/web/i18n/hu.po
addons/web/i18n/id.po
addons/web/i18n/it.po
addons/web/i18n/ja.po
addons/web/i18n/ka.po
addons/web/i18n/ko.po
addons/web/i18n/lo.po
addons/web/i18n/lt.po
addons/web/i18n/lv.po
addons/web/i18n/mk.po
addons/web/i18n/mn.po
addons/web/i18n/nb.po
addons/web/i18n/nl.po
addons/web/i18n/nl_BE.po
addons/web/i18n/pl.po
addons/web/i18n/pt.po
addons/web/i18n/pt_BR.po
addons/web/i18n/ro.po
addons/web/i18n/ru.po
addons/web/i18n/sk.po
addons/web/i18n/sl.po
addons/web/i18n/sq.po
addons/web/i18n/sr@latin.po
addons/web/i18n/sv.po
addons/web/i18n/th.po
addons/web/i18n/tr.po
addons/web/i18n/uk.po
addons/web/i18n/vi.po
addons/web/i18n/zh_CN.po
addons/web/i18n/zh_TW.po
addons/web/static/lib/cleditor/jquery.cleditor.css
addons/web/static/lib/cleditor/jquery.cleditor.js
addons/web/static/lib/cleditor/jquery.cleditor.min.js [new file with mode: 0644]
addons/web/static/lib/fontawesome/css/font-awesome.css
addons/web/static/lib/underscore/underscore.js
addons/web/static/src/css/Makefile
addons/web/static/src/css/base.css
addons/web/static/src/css/base.sass
addons/web/static/src/img/throbber-large.gif [deleted file]
addons/web/static/src/js/chrome.js
addons/web/static/src/js/data.js
addons/web/static/src/js/data_export.js
addons/web/static/src/js/formats.js
addons/web/static/src/js/search.js
addons/web/static/src/js/testing.js
addons/web/static/src/js/view_form.js
addons/web/static/src/js/view_list.js
addons/web/static/src/js/views.js
addons/web/static/src/xml/base.xml
addons/web/static/test/data.js
addons/web/static/test/jsonrpc.js [new file with mode: 0644]
addons/web/tests/qunitsuite/suite.py
addons/web/tests/test_js.py
addons/web/views/database_selector.html
addons/web/views/webclient_templates.xml
addons/web_calendar/i18n/ar.po
addons/web_calendar/i18n/bg.po
addons/web_calendar/i18n/bn.po
addons/web_calendar/i18n/bs.po
addons/web_calendar/i18n/ca.po
addons/web_calendar/i18n/cs.po
addons/web_calendar/i18n/da.po
addons/web_calendar/i18n/de.po
addons/web_calendar/i18n/en_AU.po
addons/web_calendar/i18n/en_GB.po
addons/web_calendar/i18n/es.po
addons/web_calendar/i18n/es_CL.po
addons/web_calendar/i18n/es_CR.po
addons/web_calendar/i18n/es_DO.po
addons/web_calendar/i18n/es_EC.po
addons/web_calendar/i18n/es_MX.po
addons/web_calendar/i18n/es_PE.po
addons/web_calendar/i18n/et.po
addons/web_calendar/i18n/eu.po
addons/web_calendar/i18n/fa.po
addons/web_calendar/i18n/fi.po
addons/web_calendar/i18n/fr.po
addons/web_calendar/i18n/fr_CA.po
addons/web_calendar/i18n/gl.po
addons/web_calendar/i18n/gu.po
addons/web_calendar/i18n/hr.po
addons/web_calendar/i18n/hu.po
addons/web_calendar/i18n/id.po
addons/web_calendar/i18n/it.po
addons/web_calendar/i18n/ja.po
addons/web_calendar/i18n/ka.po
addons/web_calendar/i18n/ko.po
addons/web_calendar/i18n/lt.po
addons/web_calendar/i18n/mk.po
addons/web_calendar/i18n/mn.po
addons/web_calendar/i18n/nb.po
addons/web_calendar/i18n/nl.po
addons/web_calendar/i18n/nl_BE.po
addons/web_calendar/i18n/pl.po
addons/web_calendar/i18n/pt.po
addons/web_calendar/i18n/pt_BR.po
addons/web_calendar/i18n/ro.po
addons/web_calendar/i18n/ru.po
addons/web_calendar/i18n/sk.po
addons/web_calendar/i18n/sl.po
addons/web_calendar/i18n/sq.po
addons/web_calendar/i18n/sr@latin.po
addons/web_calendar/i18n/sv.po
addons/web_calendar/i18n/th.po
addons/web_calendar/i18n/tr.po
addons/web_calendar/i18n/uk.po
addons/web_calendar/i18n/zh_CN.po
addons/web_calendar/i18n/zh_TW.po
addons/web_calendar/static/src/js/web_calendar.js
addons/web_diagram/i18n/ar.po
addons/web_diagram/i18n/bg.po
addons/web_diagram/i18n/bn.po
addons/web_diagram/i18n/bs.po
addons/web_diagram/i18n/ca.po
addons/web_diagram/i18n/cs.po
addons/web_diagram/i18n/da.po
addons/web_diagram/i18n/de.po
addons/web_diagram/i18n/en_AU.po
addons/web_diagram/i18n/en_GB.po
addons/web_diagram/i18n/es.po
addons/web_diagram/i18n/es_CL.po
addons/web_diagram/i18n/es_CR.po
addons/web_diagram/i18n/es_DO.po
addons/web_diagram/i18n/es_EC.po
addons/web_diagram/i18n/es_MX.po
addons/web_diagram/i18n/es_PE.po
addons/web_diagram/i18n/et.po
addons/web_diagram/i18n/fa.po
addons/web_diagram/i18n/fi.po
addons/web_diagram/i18n/fr.po
addons/web_diagram/i18n/gl.po
addons/web_diagram/i18n/gu.po
addons/web_diagram/i18n/hr.po
addons/web_diagram/i18n/hu.po
addons/web_diagram/i18n/id.po
addons/web_diagram/i18n/it.po
addons/web_diagram/i18n/ja.po
addons/web_diagram/i18n/ka.po
addons/web_diagram/i18n/ko.po
addons/web_diagram/i18n/lt.po
addons/web_diagram/i18n/mk.po
addons/web_diagram/i18n/mn.po
addons/web_diagram/i18n/nb.po
addons/web_diagram/i18n/nl.po
addons/web_diagram/i18n/nl_BE.po
addons/web_diagram/i18n/pl.po
addons/web_diagram/i18n/pt.po
addons/web_diagram/i18n/pt_BR.po
addons/web_diagram/i18n/ro.po
addons/web_diagram/i18n/ru.po
addons/web_diagram/i18n/sl.po
addons/web_diagram/i18n/sq.po
addons/web_diagram/i18n/sr@latin.po
addons/web_diagram/i18n/sv.po
addons/web_diagram/i18n/th.po
addons/web_diagram/i18n/tr.po
addons/web_diagram/i18n/zh_CN.po
addons/web_diagram/i18n/zh_TW.po
addons/web_gantt/i18n/ar.po
addons/web_gantt/i18n/bg.po
addons/web_gantt/i18n/bn.po
addons/web_gantt/i18n/bs.po
addons/web_gantt/i18n/ca.po
addons/web_gantt/i18n/cs.po
addons/web_gantt/i18n/da.po
addons/web_gantt/i18n/de.po
addons/web_gantt/i18n/en_AU.po
addons/web_gantt/i18n/en_GB.po
addons/web_gantt/i18n/es.po
addons/web_gantt/i18n/es_CL.po
addons/web_gantt/i18n/es_CR.po
addons/web_gantt/i18n/es_DO.po
addons/web_gantt/i18n/es_EC.po
addons/web_gantt/i18n/es_MX.po
addons/web_gantt/i18n/et.po
addons/web_gantt/i18n/fa.po
addons/web_gantt/i18n/fi.po
addons/web_gantt/i18n/fr.po
addons/web_gantt/i18n/gl.po
addons/web_gantt/i18n/gu.po
addons/web_gantt/i18n/he.po
addons/web_gantt/i18n/hr.po
addons/web_gantt/i18n/hu.po
addons/web_gantt/i18n/it.po
addons/web_gantt/i18n/ja.po
addons/web_gantt/i18n/ka.po
addons/web_gantt/i18n/ko.po
addons/web_gantt/i18n/lo.po
addons/web_gantt/i18n/lt.po
addons/web_gantt/i18n/mk.po
addons/web_gantt/i18n/mn.po
addons/web_gantt/i18n/nb.po
addons/web_gantt/i18n/nl.po
addons/web_gantt/i18n/nl_BE.po
addons/web_gantt/i18n/pl.po
addons/web_gantt/i18n/pt.po
addons/web_gantt/i18n/pt_BR.po
addons/web_gantt/i18n/ro.po
addons/web_gantt/i18n/ru.po
addons/web_gantt/i18n/sl.po
addons/web_gantt/i18n/sq.po
addons/web_gantt/i18n/sr@latin.po
addons/web_gantt/i18n/sv.po
addons/web_gantt/i18n/th.po
addons/web_gantt/i18n/tr.po
addons/web_gantt/i18n/zh_CN.po
addons/web_graph/i18n/ar.po
addons/web_graph/i18n/bg.po
addons/web_graph/i18n/bn.po
addons/web_graph/i18n/bs.po
addons/web_graph/i18n/ca.po
addons/web_graph/i18n/cs.po
addons/web_graph/i18n/da.po
addons/web_graph/i18n/de.po
addons/web_graph/i18n/en_AU.po
addons/web_graph/i18n/en_GB.po
addons/web_graph/i18n/es.po
addons/web_graph/i18n/es_CL.po
addons/web_graph/i18n/es_CR.po
addons/web_graph/i18n/es_DO.po
addons/web_graph/i18n/es_EC.po
addons/web_graph/i18n/es_MX.po
addons/web_graph/i18n/et.po
addons/web_graph/i18n/fa.po
addons/web_graph/i18n/fi.po
addons/web_graph/i18n/fr.po
addons/web_graph/i18n/fr_CA.po
addons/web_graph/i18n/gl.po
addons/web_graph/i18n/gu.po
addons/web_graph/i18n/he.po
addons/web_graph/i18n/hr.po
addons/web_graph/i18n/hu.po
addons/web_graph/i18n/it.po
addons/web_graph/i18n/ja.po
addons/web_graph/i18n/ka.po
addons/web_graph/i18n/ko.po
addons/web_graph/i18n/lt.po
addons/web_graph/i18n/mk.po
addons/web_graph/i18n/mn.po
addons/web_graph/i18n/nb.po
addons/web_graph/i18n/nl.po
addons/web_graph/i18n/nl_BE.po
addons/web_graph/i18n/pl.po
addons/web_graph/i18n/pt.po
addons/web_graph/i18n/pt_BR.po
addons/web_graph/i18n/ro.po
addons/web_graph/i18n/ru.po
addons/web_graph/i18n/sl.po
addons/web_graph/i18n/sq.po
addons/web_graph/i18n/sr@latin.po
addons/web_graph/i18n/sv.po
addons/web_graph/i18n/th.po
addons/web_graph/i18n/tr.po
addons/web_graph/i18n/zh_CN.po
addons/web_graph/static/src/css/graph.css
addons/web_graph/static/src/js/graph_view.js
addons/web_graph/static/src/js/graph_widget.js
addons/web_graph/static/src/xml/web_graph.xml
addons/web_kanban/i18n/ar.po
addons/web_kanban/i18n/bg.po
addons/web_kanban/i18n/bn.po
addons/web_kanban/i18n/bs.po
addons/web_kanban/i18n/ca.po
addons/web_kanban/i18n/cs.po
addons/web_kanban/i18n/da.po
addons/web_kanban/i18n/de.po
addons/web_kanban/i18n/en_AU.po
addons/web_kanban/i18n/en_GB.po
addons/web_kanban/i18n/es.po
addons/web_kanban/i18n/es_CL.po
addons/web_kanban/i18n/es_CR.po
addons/web_kanban/i18n/es_DO.po
addons/web_kanban/i18n/es_EC.po
addons/web_kanban/i18n/es_MX.po
addons/web_kanban/i18n/et.po
addons/web_kanban/i18n/fa.po
addons/web_kanban/i18n/fi.po
addons/web_kanban/i18n/fr.po
addons/web_kanban/i18n/fr_CA.po
addons/web_kanban/i18n/gl.po
addons/web_kanban/i18n/gu.po
addons/web_kanban/i18n/he.po
addons/web_kanban/i18n/hr.po
addons/web_kanban/i18n/hu.po
addons/web_kanban/i18n/it.po
addons/web_kanban/i18n/ja.po
addons/web_kanban/i18n/ka.po
addons/web_kanban/i18n/ko.po
addons/web_kanban/i18n/lt.po
addons/web_kanban/i18n/mk.po
addons/web_kanban/i18n/mn.po
addons/web_kanban/i18n/nb.po
addons/web_kanban/i18n/nl.po
addons/web_kanban/i18n/nl_BE.po
addons/web_kanban/i18n/pl.po
addons/web_kanban/i18n/pt.po
addons/web_kanban/i18n/pt_BR.po
addons/web_kanban/i18n/ro.po
addons/web_kanban/i18n/ru.po
addons/web_kanban/i18n/sl.po
addons/web_kanban/i18n/sr@latin.po
addons/web_kanban/i18n/sv.po
addons/web_kanban/i18n/th.po
addons/web_kanban/i18n/tr.po
addons/web_kanban/i18n/zh_CN.po
addons/web_kanban/i18n/zh_TW.po
addons/web_tests_demo/static/test/demo.js
addons/web_tests_demo/tests/__init__.py [deleted file]
addons/web_tests_demo/tests/test_js.py [deleted file]
addons/web_view_editor/i18n/ar.po
addons/web_view_editor/i18n/bs.po
addons/web_view_editor/i18n/cs.po
addons/web_view_editor/i18n/da.po
addons/web_view_editor/i18n/de.po
addons/web_view_editor/i18n/en_AU.po
addons/web_view_editor/i18n/en_GB.po
addons/web_view_editor/i18n/es.po
addons/web_view_editor/i18n/es_DO.po
addons/web_view_editor/i18n/es_EC.po
addons/web_view_editor/i18n/es_MX.po
addons/web_view_editor/i18n/et.po
addons/web_view_editor/i18n/fa.po
addons/web_view_editor/i18n/fi.po
addons/web_view_editor/i18n/fr.po
addons/web_view_editor/i18n/he.po
addons/web_view_editor/i18n/hr.po
addons/web_view_editor/i18n/hu.po
addons/web_view_editor/i18n/it.po
addons/web_view_editor/i18n/ko.po
addons/web_view_editor/i18n/lt.po
addons/web_view_editor/i18n/lv.po
addons/web_view_editor/i18n/mk.po
addons/web_view_editor/i18n/mn.po
addons/web_view_editor/i18n/nb.po
addons/web_view_editor/i18n/nl.po
addons/web_view_editor/i18n/nl_BE.po
addons/web_view_editor/i18n/pl.po
addons/web_view_editor/i18n/pt.po
addons/web_view_editor/i18n/pt_BR.po
addons/web_view_editor/i18n/ro.po
addons/web_view_editor/i18n/ru.po
addons/web_view_editor/i18n/sl.po
addons/web_view_editor/i18n/sv.po
addons/web_view_editor/i18n/th.po
addons/web_view_editor/i18n/tr.po
addons/web_view_editor/i18n/zh_CN.po
addons/web_view_editor/static/src/js/view_editor.js
openerp-wsgi.py
openerp/addons/base/__init__.py
openerp/addons/base/__openerp__.py
openerp/addons/base/i18n/ab.po
openerp/addons/base/i18n/af.po
openerp/addons/base/i18n/am.po
openerp/addons/base/i18n/ar.po
openerp/addons/base/i18n/bg.po
openerp/addons/base/i18n/bn.po
openerp/addons/base/i18n/bs.po
openerp/addons/base/i18n/ca.po
openerp/addons/base/i18n/cs.po
openerp/addons/base/i18n/da.po
openerp/addons/base/i18n/de.po
openerp/addons/base/i18n/el.po
openerp/addons/base/i18n/en_GB.po
openerp/addons/base/i18n/es.po
openerp/addons/base/i18n/es_AR.po
openerp/addons/base/i18n/es_BO.po
openerp/addons/base/i18n/es_CL.po
openerp/addons/base/i18n/es_CR.po
openerp/addons/base/i18n/es_DO.po
openerp/addons/base/i18n/es_EC.po
openerp/addons/base/i18n/es_MX.po
openerp/addons/base/i18n/es_PE.po
openerp/addons/base/i18n/es_VE.po
openerp/addons/base/i18n/et.po
openerp/addons/base/i18n/eu.po
openerp/addons/base/i18n/fa.po
openerp/addons/base/i18n/fa_AF.po
openerp/addons/base/i18n/fi.po
openerp/addons/base/i18n/fr.po
openerp/addons/base/i18n/fr_CA.po
openerp/addons/base/i18n/gl.po
openerp/addons/base/i18n/gu.po
openerp/addons/base/i18n/he.po
openerp/addons/base/i18n/hi.po
openerp/addons/base/i18n/hr.po
openerp/addons/base/i18n/hu.po
openerp/addons/base/i18n/hy.po
openerp/addons/base/i18n/id.po
openerp/addons/base/i18n/is.po
openerp/addons/base/i18n/it.po
openerp/addons/base/i18n/ja.po
openerp/addons/base/i18n/ka.po
openerp/addons/base/i18n/kk.po
openerp/addons/base/i18n/ko.po
openerp/addons/base/i18n/lt.po
openerp/addons/base/i18n/lv.po
openerp/addons/base/i18n/mk.po
openerp/addons/base/i18n/mn.po
openerp/addons/base/i18n/nb.po
openerp/addons/base/i18n/nl.po
openerp/addons/base/i18n/nl_BE.po
openerp/addons/base/i18n/pl.po
openerp/addons/base/i18n/pt.po
openerp/addons/base/i18n/pt_BR.po
openerp/addons/base/i18n/ro.po
openerp/addons/base/i18n/ru.po
openerp/addons/base/i18n/sk.po
openerp/addons/base/i18n/sl.po
openerp/addons/base/i18n/sq.po
openerp/addons/base/i18n/sr.po
openerp/addons/base/i18n/sr@latin.po
openerp/addons/base/i18n/sv.po
openerp/addons/base/i18n/th.po
openerp/addons/base/i18n/tlh.po
openerp/addons/base/i18n/tr.po
openerp/addons/base/i18n/uk.po
openerp/addons/base/i18n/ur.po
openerp/addons/base/i18n/vi.po
openerp/addons/base/i18n/zh_CN.po
openerp/addons/base/i18n/zh_HK.po
openerp/addons/base/i18n/zh_TW.po
openerp/addons/base/ir/__init__.py
openerp/addons/base/ir/ir_actions.py
openerp/addons/base/ir/ir_actions.xml
openerp/addons/base/ir/ir_attachment.py
openerp/addons/base/ir/ir_cron.py
openerp/addons/base/ir/ir_http.py
openerp/addons/base/ir/ir_logging.py [deleted file]
openerp/addons/base/ir/ir_logging_view.xml [deleted file]
openerp/addons/base/ir/ir_model.py
openerp/addons/base/ir/ir_qweb.py
openerp/addons/base/ir/ir_ui_view.py
openerp/addons/base/module/wizard/base_module_import.py
openerp/addons/base/res/res_company.py
openerp/addons/base/res/res_partner.py
openerp/addons/base/res/res_users.py
openerp/addons/base/res/res_users_view.xml
openerp/addons/base/security/ir.model.access.csv
openerp/addons/base/tests/test_base.py
openerp/addons/base/tests/test_fields.py
openerp/addons/base/tests/test_ir_attachment.py
openerp/addons/base/tests/test_ir_sequence.py
openerp/addons/base/tests/test_qweb.py
openerp/addons/base/tests/test_views.py
openerp/addons/test_converter/tests/test_html.py
openerp/addons/test_impex/tests/test_export.py
openerp/cli/server.py
openerp/http.py
openerp/modules/loading.py
openerp/modules/module.py
openerp/netsvc.py
openerp/osv/fields.py
openerp/osv/orm.py
openerp/release.py
openerp/service/db.py
openerp/service/server.py
openerp/service/wsgi_server.py
openerp/sql_db.py
openerp/tests/common.py
openerp/tests/phantomtest.js
openerp/tools/__init__.py
openerp/tools/appdirs.py [deleted file]
openerp/tools/config.py
openerp/tools/debugger.py [deleted file]
openerp/tools/image.py
openerp/tools/osutil.py
openerp/tools/safe_eval.py
openerp/tools/translate.py
setup.py

index e950950..56c56a1 100644 (file)
@@ -12,6 +12,7 @@ import math
 import md5
 import openerp.addons.hw_proxy.controllers.main as hw_proxy
 import subprocess
+import traceback
 from threading import Thread, Lock
 from Queue import Queue, Empty
 
@@ -113,6 +114,9 @@ class EscposDriver(Thread):
                     if timestamp >= time.time() - 1 * 60 * 60:
                         self.print_receipt_body(printer,data)
                         printer.cut()
+                elif task == 'xml_receipt':
+                    if timestamp >= time.time() - 1 * 60 * 60:
+                        printer.receipt(data)
                 elif task == 'cashbox':
                     if timestamp >= time.time() - 12:
                         self.open_cashbox(printer)
@@ -123,7 +127,8 @@ class EscposDriver(Thread):
 
             except Exception as e:
                 self.set_status('error', str(e))
-                _logger.error(e);
+                errmsg = str(e) + '\n' + '-'*60+'\n' + traceback.format_exc() + '-'*60 + '\n'
+                _logger.error(errmsg);
 
     def push_task(self,task, data = None):
         self.lockedstart()
@@ -280,8 +285,6 @@ driver = EscposDriver()
 
 hw_proxy.drivers['escpos'] = driver
 
-driver.push_task('printstatus')
-        
 class EscposProxy(hw_proxy.Proxy):
     
     @http.route('/hw_proxy/open_cashbox', type='json', auth='none', cors='*')
@@ -293,4 +296,9 @@ class EscposProxy(hw_proxy.Proxy):
     def print_receipt(self, receipt):
         _logger.info('ESC/POS: PRINT RECEIPT') 
         driver.push_task('receipt',receipt)
+
+    @http.route('/hw_proxy/print_xml_receipt', type='json', auth='none', cors='*')
+    def print_receipt(self, receipt):
+        _logger.info('ESC/POS: PRINT XML RECEIPT') 
+        driver.push_task('xml_receipt',receipt)
     
index 723c670..6f0be0b 100644 (file)
@@ -22,6 +22,7 @@ PAPER_PART_CUT  = '\x1d\x56\x01' # Partial cut paper
 TXT_NORMAL      = '\x1b\x21\x00' # Normal text
 TXT_2HEIGHT     = '\x1b\x21\x10' # Double height text
 TXT_2WIDTH      = '\x1b\x21\x20' # Double width text
+TXT_DOUBLE      = '\x1b\x21\x30' # Double height & Width
 TXT_UNDERL_OFF  = '\x1b\x2d\x00' # Underline font OFF
 TXT_UNDERL_ON   = '\x1b\x2d\x01' # Underline font 1-dot ON
 TXT_UNDERL2_ON  = '\x1b\x2d\x02' # Underline font 2-dot ON
index a494201..cefa00f 100644 (file)
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+# -*- coding: utf-8 -*-
 '''
 @author: Manuel F Martinez <manpaz@bashlinux.com>
 @organization: Bashlinux
@@ -17,6 +17,10 @@ import io
 import base64
 import math
 import md5
+import re
+import traceback
+import xml.etree.ElementTree as ET
+import xml.dom.minidom as minidom
 
 from PIL import Image
 
@@ -30,13 +34,286 @@ except ImportError:
 from constants import *
 from exceptions import *
 
+def utfstr(stuff):
+    """ converts stuff to string and does without failing if stuff is a utf8 string """
+    if isinstance(stuff,basestring):
+        return stuff
+    else:
+        return str(stuff)
+
+class StyleStack:
+    """ 
+    The stylestack is used by the xml receipt serializer to compute the active styles along the xml
+    document. Styles are just xml attributes, there is no css mechanism. But the style applied by
+    the attributes are inherited by deeper nodes.
+    """
+    def __init__(self):
+        self.stack = []
+        self.defaults = {   # default style values
+            'align':     'left',
+            'underline': 'off',
+            'bold':      'off',
+            'size':      'normal',
+            'font'  :    'a',
+            'width':     48,
+            'indent':    0,
+            'tabwidth':  2,
+            'bullet':    ' - ',
+            'line-ratio':0.5,
+
+            'value-decimals':           2,
+            'value-symbol':             '',
+            'value-symbol-position':    'after',
+            'value-autoint':            'off',
+            'value-decimals-separator':  '.',
+            'value-thousands-separator': ',',
+            'value-width':               0,
+            
+        }
+
+        self.types = { # attribute types, default is string and can be ommitted
+            'width':    'int',
+            'indent':   'int',
+            'tabwidth': 'int',
+            'line-ratio':       'float',
+            'value-decimals':   'int',
+            'value-width':      'int',
+        }
+
+        self.cmds = { 
+            # translation from styles to escpos commands
+            # some style do not correspond to escpos command are used by
+            # the serializer instead
+            'align': {
+                'left':     TXT_ALIGN_LT,
+                'right':    TXT_ALIGN_RT,
+                'center':   TXT_ALIGN_CT,
+            },
+            'underline': {
+                'off':      TXT_UNDERL_OFF,
+                'on':       TXT_UNDERL_ON,
+                'double':   TXT_UNDERL2_ON,
+            },
+            'bold': {
+                'off':      TXT_BOLD_OFF,
+                'on':       TXT_BOLD_ON,
+            },
+            'font': {
+                'a':        TXT_FONT_A,
+                'b':        TXT_FONT_B,
+            },
+            'size': {
+                'normal':           TXT_NORMAL,
+                'double-height':    TXT_2HEIGHT,
+                'double-width':     TXT_2WIDTH,
+                'double':           TXT_DOUBLE,
+            }
+        }
+
+        self.push(self.defaults) 
+
+    def get(self,style):
+        """ what's the value of a style at the current stack level"""
+        level = len(self.stack) -1
+        while level >= 0:
+            if style in self.stack[level]:
+                return self.stack[level][style]
+            else:
+                level = level - 1
+        return None
+
+    def enforce_type(self, attr, val):
+        """converts a value to the attribute's type"""
+        if not attr in self.types:
+            return utfstr(val)
+        elif self.types[attr] == 'int':
+            return int(float(val))
+        elif self.types[attr] == 'float':
+            return float(val)
+        else:
+            return utfstr(val)
+
+    def push(self, style={}):
+        """push a new level on the stack with a style dictionnary containing style:value pairs"""
+        _style = {}
+        for attr in style:
+            if attr in self.cmds and not style[attr] in self.cmds[attr]:
+                print 'WARNING: ESC/POS PRINTING: ignoring invalid value: '+utfstr(style[attr])+' for style: '+utfstr(attr)
+            else:
+                _style[attr] = self.enforce_type(attr, style[attr])
+        self.stack.append(_style)
+
+    def set(self, style={}):
+        """overrides style values at the current stack level"""
+        _style = {}
+        for attr in style:
+            if attr in self.cmds and not style[attr] in self.cmds[attr]:
+                print 'WARNING: ESC/POS PRINTING: ignoring invalid value: '+utfstr(style[attr])+' for style: '+utfstr(attr)
+            else:
+                self.stack[-1][attr] = self.enforce_type(attr, style[attr])
+
+    def pop(self):
+        """ pop a style stack level """
+        if len(self.stack) > 1 :
+            self.stack = self.stack[:-1]
+
+    def to_escpos(self):
+        """ converts the current style to an escpos command string """
+        cmd = ''
+        for style in self.cmds:
+            cmd += self.cmds[style][self.get(style)]
+        return cmd
+
+class XmlSerializer:
+    """ 
+    Converts the xml inline / block tree structure to a string,
+    keeping track of newlines and spacings.
+    The string is outputted asap to the provided escpos driver.
+    """
+    def __init__(self,escpos):
+        self.escpos = escpos
+        self.stack = ['block']
+        self.dirty = False
+
+    def start_inline(self,stylestack=None):
+        """ starts an inline entity with an optional style definition """
+        print 'start_inline'
+        self.stack.append('inline')
+        if self.dirty:
+            self.escpos._raw(' ')
+        if stylestack:
+            self.style(stylestack)
+
+    def start_block(self,stylestack=None):
+        """ starts a block entity with an optional style definition """
+        print 'start_block'
+        if self.dirty:
+            print 'cleanup before block'
+            self.escpos._raw('\n')
+            self.dirty = False
+        self.stack.append('block')
+        if stylestack:
+            self.style(stylestack)
+
+    def end_entity(self):
+        """ ends the entity definition. (but does not cancel the active style!) """
+        print 'end_entity'
+        if self.stack[-1] == 'block' and self.dirty:
+            print 'cleanup after block'
+            self.escpos._raw('\n')
+            self.dirty = False
+        if len(self.stack) > 1:
+            self.stack = self.stack[:-1]
+
+    def pre(self,text):
+        """ puts a string of text in the entity keeping the whitespace intact """
+        if text:
+            self.escpos.text(text)
+            self.dirty = True
+
+    def text(self,text):
+        """ puts text in the entity. Whitespace and newlines are stripped to single spaces. """
+        if text:
+            text = utfstr(text)
+            text = text.strip()
+            text = re.sub('\s+',' ',text)
+            if text:
+                print 'printing text:'+text
+                self.dirty = True
+                self.escpos.text(text)
+
+    def linebreak(self):
+        """ inserts a linebreak in the entity """
+        self.dirty = False
+        self.escpos._raw('\n')
+
+    def style(self,stylestack):
+        """ apply a style to the entity (only applies to content added after the definition) """
+        self.raw(stylestack.to_escpos())
+
+    def raw(self,raw):
+        """ puts raw text or escpos command in the entity without affecting the state of the serializer """
+        self.escpos._raw(raw)
+
+class XmlLineSerializer:
+    """ 
+    This is used to convert a xml tree into a single line, with a left and a right part.
+    The content is not output to escpos directly, and is intended to be fedback to the
+    XmlSerializer as the content of a block entity.
+    """
+    def __init__(self, indent=0, tabwidth=2, width=48, ratio=0.5):
+        self.tabwidth = tabwidth
+        self.indent = indent
+        self.width  = max(0, width - int(tabwidth*indent))
+        self.lwidth = int(self.width*ratio)
+        self.rwidth = max(0, self.width - self.lwidth)
+        self.clwidth = 0
+        self.crwidth = 0
+        self.lbuffer  = ''
+        self.rbuffer  = ''
+        self.left    = True
+
+    def _txt(self,txt):
+        print '_txt: ',txt
+        if self.left:
+            if self.clwidth < self.lwidth:
+                txt = txt[:max(0, self.lwidth - self.clwidth)]
+                self.lbuffer += txt
+                self.clwidth += len(txt)
+        else:
+            if self.crwidth < self.rwidth:
+                txt = txt[:max(0, self.rwidth - self.crwidth)]
+                self.rbuffer += txt
+                self.crwidth  += len(txt)
+
+    def start_inline(self,stylestack=None):
+        print 'LINE:start_entity'
+        if (self.left and self.clwidth) or (not self.left and self.crwidth):
+            self._txt(' ')
+
+    def start_block(self,stylestack=None):
+        self.start_inline(stylestack)
+
+    def end_entity(self):
+        pass
+
+    def pre(self,text):
+        if text:
+            self._txt(text)
+    def text(self,text):
+        if text:
+            text = utfstr(text)
+            text = text.strip()
+            text = re.sub('\s+',' ',text)
+            if text:
+                print 'LINE:printing text:'+text
+                self._txt(text)
+
+    def linebreak(self):
+        pass
+    def style(self,stylestack):
+        pass
+    def raw(self,raw):
+        pass
+
+    def start_right(self):
+        self.left = False
+
+    def get_line(self):
+        print 'LBUFFER: '+self.lbuffer
+        print self.clwidth
+        print 'RBUFFER: '+self.rbuffer
+        print self.crwidth
+
+        return ' ' * self.indent * self.tabwidth + self.lbuffer + ' ' * (self.width - self.clwidth - self.crwidth) + self.rbuffer
+    
+
 class Escpos:
     """ ESC/POS Printer object """
     device    = None
     encoding  = None
     img_cache = {}
 
-
     def _check_image_size(self, size):
         """ Check and fix the size of the image to 32 bits """
         if size % 32 == 0:
@@ -48,7 +325,6 @@ class Escpos:
             else:
                 return (image_border / 2, (image_border / 2) + 1)
 
-
     def _print_image(self, line, size):
         """ Print formatted image """
         i = 0
@@ -101,7 +377,6 @@ class Escpos:
 
         return raw
 
-
     def _convert_image(self, im):
         """ Parse image and prepare it to a printable format """
         pixels   = []
@@ -197,8 +472,7 @@ class Escpos:
         # Convert the RGB image in printable image
         self._convert_image(im)
 
-
-    def barcode(self, code, bc, width, height, pos, font):
+    def barcode(self, code, bc, width=255, height=2, pos='below', font='a'):
         """ Print Barcode """
         # Align Bar Code()
         self._raw(TXT_ALIGN_CT)
@@ -249,6 +523,197 @@ class Escpos:
         else:
             raise exception.BarcodeCodeError()
 
+    def receipt(self,xml):
+        """
+        Prints an xml based receipt definition
+        """
+
+        def strclean(string):
+            if not string:
+                string = ''
+            string = string.strip()
+            string = re.sub('\s+',' ',string)
+            return string
+
+        def format_value(value, decimals=3, width=0, decimals_separator='.', thousands_separator=',', autoint=False, symbol='', position='after'):
+            decimals = max(0,int(decimals))
+            width    = max(0,int(width))
+            value    = float(value)
+
+            if autoint and math.floor(value) == value:
+                decimals = 0
+            if width == 0:
+                width = ''
+
+            if thousands_separator:
+                formatstr = "{:"+str(width)+",."+str(decimals)+"f}"
+            else:
+                formatstr = "{:"+str(width)+"."+str(decimals)+"f}"
+
+
+            print formatstr
+            print value
+            ret = formatstr.format(value)
+            print ret
+            ret = ret.replace(',','COMMA')
+            ret = ret.replace('.','DOT')
+            ret = ret.replace('COMMA',thousands_separator)
+            ret = ret.replace('DOT',decimals_separator)
+            print 'RET '+ret
+
+            if symbol:
+                if position == 'after':
+                    ret = ret + symbol
+                else:
+                    ret = symbol + ret
+            return ret
+
+        def print_elem(stylestack, serializer, elem, indent=0):
+
+            elem_styles = {
+                'h1': {'bold': 'on', 'size':'double'},
+                'h2': {'size':'double'},
+                'h3': {'bold': 'on', 'size':'double-height'},
+                'h4': {'size': 'double-height'},
+                'h5': {'bold': 'on'},
+                'em': {'font': 'b'},
+                'b':  {'bold': 'on'},
+            }
+
+            stylestack.push()
+            if elem.tag in elem_styles:
+                stylestack.set(elem_styles[elem.tag])
+            stylestack.set(elem.attrib)
+
+            if elem.tag in ('p','div','section','article','receipt','header','footer','li','h1','h2','h3','h4','h5'):
+                serializer.start_block(stylestack)
+                serializer.text(elem.text)
+                for child in elem:
+                    print_elem(stylestack,serializer,child)
+                    serializer.start_inline(stylestack)
+                    serializer.text(child.tail)
+                    serializer.end_entity()
+                serializer.end_entity()
+
+            elif elem.tag in ('span','em','b','left','right'):
+                serializer.start_inline(stylestack)
+                serializer.text(elem.text)
+                for child in elem:
+                    print_elem(stylestack,serializer,child)
+                    serializer.start_inline(stylestack)
+                    serializer.text(child.tail)
+                    serializer.end_entity()
+                serializer.end_entity()
+
+            elif elem.tag == 'value':
+                serializer.start_inline(stylestack)
+                serializer.pre(format_value( 
+                                              elem.text,
+                                              decimals=stylestack.get('value-decimals'),
+                                              width=stylestack.get('value-width'),
+                                              decimals_separator=stylestack.get('value-decimals-separator'),
+                                              thousands_separator=stylestack.get('value-thousands-separator'),
+                                              autoint=(stylestack.get('autoint') == 'on'),
+                                              symbol=stylestack.get('value-symbol'),
+                                              position=stylestack.get('value-symbol-position') 
+                                            ))
+                serializer.end_entity()
+
+            elif elem.tag == 'line':
+                width = stylestack.get('width')
+                if stylestack.get('size') in ('double', 'double-width'):
+                    width = width / 2
+
+                lineserializer = XmlLineSerializer(stylestack.get('indent')+indent,stylestack.get('tabwidth'),width,stylestack.get('line-ratio'))
+                serializer.start_block(stylestack)
+                for child in elem:
+                    if child.tag == 'left':
+                        print_elem(stylestack,lineserializer,child,indent=indent)
+                    elif child.tag == 'right':
+                        lineserializer.start_right()
+                        print_elem(stylestack,lineserializer,child,indent=indent)
+                serializer.pre(lineserializer.get_line())
+                serializer.end_entity()
+
+            elif elem.tag == 'ul':
+                serializer.start_block(stylestack)
+                bullet = stylestack.get('bullet')
+                for child in elem:
+                    if child.tag == 'li':
+                        serializer.style(stylestack)
+                        serializer.raw(' ' * indent * stylestack.get('tabwidth') + bullet)
+                    print_elem(stylestack,serializer,child,indent=indent+1)
+                serializer.end_entity()
+
+            elif elem.tag == 'ol':
+                cwidth = len(str(len(elem))) + 2
+                i = 1
+                serializer.start_block(stylestack)
+                for child in elem:
+                    if child.tag == 'li':
+                        serializer.style(stylestack)
+                        serializer.raw(' ' * indent * stylestack.get('tabwidth') + ' ' + (str(i)+')').ljust(cwidth))
+                        i = i + 1
+                    print_elem(stylestack,serializer,child,indent=indent+1)
+                serializer.end_entity()
+
+            elif elem.tag == 'pre':
+                serializer.start_block(stylestack)
+                serializer.pre(elem.text)
+                serializer.end_entity()
+
+            elif elem.tag == 'hr':
+                width = stylestack.get('width')
+                if stylestack.get('size') in ('double', 'double-width'):
+                    width = width / 2
+                serializer.start_block(stylestack)
+                serializer.text('-'*width)
+                serializer.end_entity()
+
+            elif elem.tag == 'br':
+                serializer.linebreak()
+
+            elif elem.tag == 'img':
+                if src in elem.attrib and 'data:' in elem.attrib['src']:
+                    self.print_base64_image(elem.attrib['src'])
+
+            elif elem.tag == 'barcode' and 'encoding' in elem.attrib:
+                serializer.start_block(stylestack)
+                self.barcode(strclean(elem.text),elem.attrib['encoding'])
+                serializer.end_entity()
+
+            elif elem.tag == 'cut':
+                self.cut()
+            elif elem.tag == 'partialcut':
+                self.cut(mode='part')
+            elif elem.tag == 'cashdraw':
+                self.cashdraw(2)
+                self.cashdraw(5)
+
+            stylestack.pop()
+
+        try:
+            stylestack      = StyleStack() 
+            serializer      = XmlSerializer(self)
+            root            = ET.fromstring(xml)
+
+            self._raw(stylestack.to_escpos())
+
+            print_elem(stylestack,serializer,root)
+
+            if 'open-cashdrawer' in root.attrib and root.attrib['open-cashdrawer'] == 'true':
+                self.cashdraw(2)
+                self.cashdraw(5)
+            if not 'cut' in root.attrib or root.attrib['cut'] == 'true' :
+                self.cut()
+
+        except Exception as e:
+            errmsg = str(e)+'\n'+'-'*48+'\n'+traceback.format_exc() + '-'*48+'\n'
+            self.text(errmsg)
+            self.cut()
+
+            raise e
+
     def text(self,txt):
         """ Print Utf8 encoded alpha-numeric text """
         if not txt:
index 8f0b06e..5a0289c 100644 (file)
@@ -6,5 +6,6 @@ sys.modules['openerp.addons.web.http'] = openerp.http
 http = openerp.http
 
 import controllers
+import cli
 
 wsgi_postload = http.wsgi_postload
index f1d7d75..72f1610 100644 (file)
@@ -87,6 +87,7 @@ This module provides the core of the OpenERP Web Client.
         "static/test/data.js",
         "static/test/list-utils.js",
         "static/test/formats.js",
+        "static/test/jsonrpc.js",
         "static/test/rpc-misordered.js",
         "static/test/evals.js",
         "static/test/search.js",
diff --git a/addons/web/cli/__init__.py b/addons/web/cli/__init__.py
new file mode 100644 (file)
index 0000000..823c140
--- /dev/null
@@ -0,0 +1 @@
+import test_js
diff --git a/addons/web/cli/test_js.py b/addons/web/cli/test_js.py
new file mode 100644 (file)
index 0000000..b3a8e63
--- /dev/null
@@ -0,0 +1,35 @@
+import logging
+import optparse
+import sys
+
+import unittest2
+
+import openerp
+import openerp.addons.web.tests
+
+_logger = logging.getLogger(__name__)
+
+class TestJs(openerp.cli.Command):
+    def run(self, args):
+        self.parser = parser = optparse.OptionParser()
+        parser.add_option("-d", "--database", dest="db_name", default=False, help="specify the database name")
+        parser.add_option("--xmlrpc-port", dest="xmlrpc_port", default=8069, help="specify the TCP port for the XML-RPC protocol", type="int")
+        # proably need to add both --superadmin-password and --database-admin-password
+        self.parser.parse_args(args)
+
+        # test ony uses db_name xmlrpc_port admin_passwd, so use the server one for the actual parsing
+
+        config = openerp.tools.config
+        config.parse_config(args)
+        # needed until runbot is fixed
+        config['db_password'] = config['admin_passwd']
+
+        # run js tests
+        openerp.netsvc.init_alternative_logger()
+        suite = unittest2.TestSuite()
+        suite.addTests(unittest2.TestLoader().loadTestsFromModule(openerp.addons.web.tests.test_js))
+        r = unittest2.TextTestRunner(verbosity=2).run(suite)
+        if r.errors or r.failures:
+            sys.exit(1)
+
+# vim:et:ts=4:sw=4:
index fb6cded..e463fec 100644 (file)
@@ -14,7 +14,6 @@ import hashlib
 import os
 import re
 import simplejson
-import sys
 import time
 import urllib2
 import zlib
@@ -34,18 +33,14 @@ import openerp.modules.registry
 from openerp.tools.translate import _
 from openerp import http
 
-from openerp.http import request, serialize_exception as _serialize_exception
+from openerp.http import request, serialize_exception as _serialize_exception, LazyResponse
 
 _logger = logging.getLogger(__name__)
 
-if hasattr(sys, 'frozen'):
-    # When running on compiled windows binary, we don't have access to package loader.
-    path = os.path.realpath(os.path.join(os.path.dirname(__file__), '..', 'views'))
-    loader = jinja2.FileSystemLoader(path)
-else:
-    loader = jinja2.PackageLoader('openerp.addons.web', "views")
-
-env = jinja2.Environment(loader=loader, autoescape=True)
+env = jinja2.Environment(
+    loader=jinja2.PackageLoader('openerp.addons.web', "views"),
+    autoescape=True
+)
 env.filters["json"] = simplejson.dumps
 
 #----------------------------------------------------------
@@ -124,12 +119,6 @@ def redirect_with_hash(*args, **kw):
     """
     return http.redirect_with_hash(*args, **kw)
 
-def abort_and_redirect(url):
-    r = request.httprequest
-    response = werkzeug.utils.redirect(url, 302)
-    response = r.app.get_response(r, response, explicit_session=False)
-    werkzeug.exceptions.abort(response)
-
 def ensure_db(redirect='/web/database/selector'):
     # This helper should be used in web client auth="none" routes
     # if those routes needs a db to work with.
@@ -151,8 +140,12 @@ def ensure_db(redirect='/web/database/selector'):
         # may depend on data injected by the database route dispatcher.
         # Thus, we redirect the user to the same page but with the session cookie set.
         # This will force using the database route dispatcher...
+        r = request.httprequest
+        response = werkzeug.utils.redirect(r.url, 302)
         request.session.db = db
-        abort_and_redirect(request.httprequest.url)
+        response = r.app.get_response(r, response, explicit_session=False)
+        werkzeug.exceptions.abort(response)
+        return
 
     # if db not provided, use the session one
     if not db:
@@ -170,7 +163,6 @@ def ensure_db(redirect='/web/database/selector'):
     # always switch the session to the computed db
     if db != request.session.db:
         request.session.logout()
-        abort_and_redirect(request.httprequest.url)
 
     request.session.db = db
 
@@ -364,13 +356,7 @@ def manifest_glob(extension, addons=None, db=None, include_remotes=False):
                     r.append((None, pattern))
             else:
                 for path in glob.glob(os.path.normpath(os.path.join(addons_path, addon, pattern))):
-                    # Hack for IE, who limit 288Ko, 4095 rules, 31 sheets
-                    # http://support.microsoft.com/kb/262161/en
-                    if pattern == "static/lib/bootstrap/css/bootstrap.css":
-                        if include_remotes:
-                            r.insert(0, (None, fs2web(path[len(addons_path):])))
-                    else:
-                        r.append((path, fs2web(path[len(addons_path):])))
+                    r.append((path, fs2web(path[len(addons_path):])))
     return r
 
 def manifest_list(extension, mods=None, db=None, debug=False):
@@ -435,15 +421,6 @@ def set_cookie_and_redirect(redirect_url):
     redirect.autocorrect_location_header = False
     return redirect
 
-def login_redirect():
-    url = '/web/login?'
-    if request.debug:
-        url += 'debug&'
-    return """<html><head><script>
-        window.location = '%sredirect=' + encodeURIComponent(window.location);
-    </script></head></html>
-    """ % (url,)
-
 def load_actions_from_ir_values(key, key2, models, meta):
     Values = request.session.model('ir.values')
     actions = Values.get(key, key2, models, meta, request.context)
@@ -614,13 +591,12 @@ html_template = """<!DOCTYPE html>
 </html>
 """
 
-def render_bootstrap_template(template, values=None, debug=False, db=None, **kw):
-    if not db:
-        db = request.db
-    if request.debug:
+def render_bootstrap_template(db, template, values=None, debug=False, lazy=False, **kw):
+    if request and request.debug:
         debug = True
     if values is None:
         values = {}
+    values.update(kw)
     values['debug'] = debug
     values['current_db'] = db
     try:
@@ -636,34 +612,36 @@ def render_bootstrap_template(template, values=None, debug=False, db=None, **kw)
         values['modules'] = module_boot(db=db)
     values['modules'] = simplejson.dumps(values['modules'])
 
-    return request.render(template, values, **kw)
+    def callback(template, values):
+        registry = openerp.modules.registry.RegistryManager.get(db)
+        with registry.cursor() as cr:
+            view_obj = registry["ir.ui.view"]
+            return view_obj.render(cr, openerp.SUPERUSER_ID, template, values)
+    if lazy:
+        return LazyResponse(callback, template=template, values=values)
+    else:
+        return callback(template, values)
 
 class Home(http.Controller):
 
     @http.route('/', type='http', auth="none")
     def index(self, s_action=None, db=None, **kw):
-        return http.local_redirect('/web', query=request.params, keep_hash=True)
+        return http.local_redirect('/web', query=request.params)
 
     @http.route('/web', type='http', auth="none")
     def web_client(self, s_action=None, **kw):
         ensure_db()
 
         if request.session.uid:
-            headers = {
-                'Cache-Control': 'no-cache',
-                'Content-Type': 'text/html; charset=utf-8',
-            }
-            return render_bootstrap_template("web.webclient_bootstrap", headers=headers)
+            html = render_bootstrap_template(request.session.db, "web.webclient_bootstrap")
+            return request.make_response(html, {'Cache-Control': 'no-cache', 'Content-Type': 'text/html; charset=utf-8'})
         else:
-            return login_redirect()
+            return http.local_redirect('/web/login', query=request.params)
 
     @http.route('/web/login', type='http', auth="none")
     def web_login(self, redirect=None, **kw):
         ensure_db()
 
-        if not request.uid:
-            request.uid = openerp.SUPERUSER_ID
-
         values = request.params.copy()
         if not redirect:
             redirect = '/web?' + request.httprequest.query_string
@@ -673,7 +651,7 @@ class Home(http.Controller):
             if uid is not False:
                 return http.redirect_with_hash(redirect)
             values['error'] = "Wrong login/password"
-        return render_bootstrap_template('web.login', values)
+        return render_bootstrap_template(request.session.db, 'web.login', values, lazy=True)
 
     @http.route('/login', type='http', auth="none")
     def login(self, db, login, key, redirect="/web", **kw):
@@ -950,11 +928,10 @@ class Database(http.Controller):
             return simplejson.dumps([[],[{'error': openerp.tools.ustr(e), 'title': _('Backup Database')}]])
 
     @http.route('/web/database/restore', type='http', auth="none")
-    def restore(self, db_file, restore_pwd, new_db, mode):
+    def restore(self, db_file, restore_pwd, new_db):
         try:
-            copy = mode == 'copy'
             data = base64.b64encode(db_file.read())
-            request.session.proxy("db").restore(restore_pwd, new_db, data, copy)
+            request.session.proxy("db").restore(restore_pwd, new_db, data)
             return ''
         except openerp.exceptions.AccessDenied, e:
             raise Exception("AccessDenied")
@@ -1035,7 +1012,18 @@ class Session(http.Controller):
         :return: A key identifying the saved action.
         :rtype: integer
         """
-        return request.httpsession.save_action(the_action)
+        saved_actions = request.httpsession.get('saved_actions')
+        if not saved_actions:
+            saved_actions = {"next":1, "actions":{}}
+            request.httpsession['saved_actions'] = saved_actions
+        # we don't allow more than 10 stored actions
+        if len(saved_actions["actions"]) >= 10:
+            del saved_actions["actions"][min(saved_actions["actions"])]
+        key = saved_actions["next"]
+        saved_actions["actions"][key] = the_action
+        saved_actions["next"] = key + 1
+        request.httpsession['saved_actions'] = saved_actions
+        return key
 
     @http.route('/web/session/get_session_action', type='json', auth="user")
     def get_session_action(self, key):
@@ -1048,7 +1036,10 @@ class Session(http.Controller):
         :return: The saved action or None.
         :rtype: anything
         """
-        return request.httpsession.get_action(key)
+        saved_actions = request.httpsession.get('saved_actions')
+        if not saved_actions:
+            return None
+        return saved_actions["actions"].get(key)
 
     @http.route('/web/session/check', type='json', auth="user")
     def check(self):
@@ -1619,8 +1610,8 @@ class Export(http.Controller):
             model, map(operator.itemgetter('name'), export_fields_list))
 
         return [
-            {'name': field['name'], 'label': fields_data[field['name']]}
-            for field in export_fields_list
+            {'name': field_name, 'label': fields_data[field_name]}
+            for field_name in fields_data.keys()
         ]
 
     def fields_info(self, model, export_fields):
index a51b619..598270c 100644 (file)
@@ -52,6 +52,7 @@ TESTING = Template(u"""<!DOCTYPE html>
     <script src="/web/static/lib/qunit/qunit.js"></script>
 
     <script type="text/javascript">
+        var oe_db_info = ${db_info | n};
         // List of modules, each module is preceded by its dependencies
         var oe_all_dependencies = ${dependencies | n};
         QUnit.config.testTimeout = 5 * 60 * 1000;
@@ -133,10 +134,16 @@ class TestRunnerController(http.Controller):
             for mod, tests in itertools.izip(sorted_mods, tests)
         ]
 
+        # if all three db_info parameters are present, send them to the page
+        db_info = dict((k, v) for k, v in kwargs.iteritems()
+                       if k in ['source', 'supadmin', 'password'])
+        if len(db_info) != 3:
+            db_info = None
+
         return TESTING.render(files=files, dependencies=json.dumps(
             [name for name in sorted_mods
              if module.get_module_resource(name, 'static')
-             if manifests[name]['js']]))
+             if manifests[name]['js']]), db_info=json.dumps(db_info))
 
     def load_manifest(self, name):
         manifest = module.load_information_from_description_file(name)
@@ -157,3 +164,10 @@ class TestRunnerController(http.Controller):
                 # replace OS path separators (from join & normpath) by URI ones
                 yield path[len(root):].replace(os.path.sep, '/')
 
+    @http.route('/web/tests/set_session_value', type='json', auth="none")
+    def set_session_value(self, value):
+        request.session.some_test_value = value
+
+    @http.route('/web/tests/get_session_value', type='json', auth="none")
+    def get_session_value(self):
+        return request.session.some_test_value
index f92fdd4..d5e8602 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:01+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:08+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web
 #. openerp-web
index 9f061d5..7c8af0c 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:02+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:08+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web
 #. openerp-web
index 8d66fd1..25c1e2f 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:02+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:08+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web
 #. openerp-web
index f79c220..a40c268 100644 (file)
@@ -9,13 +9,13 @@ msgstr ""
 "Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
 "POT-Creation-Date: 2012-12-21 17:06+0000\n"
 "PO-Revision-Date: 2014-01-30 17:05+0000\n"
-"Last-Translator: Boško Stojaković <bluesoft83@gmail.com>\n"
+"Last-Translator: Bosko Stojakovic <bluesoft83@gmail.com>\n"
 "Language-Team: Bosnian <bs@li.org>\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:02+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:08+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web
 #. openerp-web
index 06889a5..a889414 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:02+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:08+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web
 #. openerp-web
index 46973b7..18a9337 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:02+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:08+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 "X-Poedit-Language: Czech\n"
 
 #. module: web
@@ -1610,7 +1610,7 @@ msgstr "Mažu databázi"
 #: code:addons/web/static/src/xml/base.xml:467
 #, python-format
 msgid "Powered by"
-msgstr "Založeno na"
+msgstr ""
 
 #. module: web
 #. openerp-web
index 495acdd..05b15a1 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:02+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:08+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web
 #. openerp-web
index f9ee094..149ca91 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:02+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:08+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web
 #. openerp-web
index d1255a8..d078092 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:05+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web
 #. openerp-web
index 1ab3070..74ec781 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:04+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:09+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web
 #. openerp-web
index 2c3918b..4f18b3b 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:04+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:09+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web
 #. openerp-web
index a1a786f..155c6ea 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:05+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:09+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web
 #. openerp-web
index 5d37ed8..ce56b09 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:05+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 "Language: es\n"
 
 #. module: web
index 774ea3d..aec2fd0 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:04+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:09+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web
 #. openerp-web
index 96b74af..16d60f1 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:05+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web
 #. openerp-web
index 8e99a25..b33f856 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:05+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web
 #. openerp-web
index 3353102..17482a5 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:05+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web
 #. openerp-web
index 6a916b1..7d1ce86 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:02+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-17 05:44+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web
 #. openerp-web
index b613aff..fa6c910 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:02+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:08+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web
 #. openerp-web
index 6350b16..3fa4a3b 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:03+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:09+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web
 #. openerp-web
index 58e91a8..455e712 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:02+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:08+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web
 #. openerp-web
@@ -853,7 +853,7 @@ msgstr "LIsää"
 #: code:addons/web/static/src/xml/base.xml:558
 #, python-format
 msgid "Toggle Form Layout Outline"
-msgstr "Vaihda lomakkeen asettelua"
+msgstr "Näytä Sijoittelu"
 
 #. module: web
 #. openerp-web
@@ -963,7 +963,7 @@ msgstr "Salasana vaihdettu"
 #: code:addons/web/static/src/js/view_list_editable.js:793
 #, python-format
 msgid "The form's data can not be discarded"
-msgstr "Lomakkeen tietoja ei voi hylätä"
+msgstr "Asiakirjan dataa ei voida hylätä"
 
 #. module: web
 #. openerp-web
index 13323c4..866478f 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:02+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:08+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web
 #. openerp-web
index 4995039..9497232 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:05+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web
 #. openerp-web
index f26c4e6..8cceab1 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:03+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:08+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web
 #. openerp-web
index 0ba9b2b..fb69c59 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:03+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:08+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web
 #. openerp-web
index 26a1c8f..8f34af9 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:03+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:08+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web
 #. openerp-web
index 3ec7a6b..428b4a3 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:03+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:08+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web
 #. openerp-web
index 73bc618..87af29c 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:04+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:09+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web
 #. openerp-web
index 22f8773..0285acb 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:03+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:08+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web
 #. openerp-web
index 65cfb2e..30e0c7d 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:03+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:08+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web
 #. openerp-web
index 068131c..f0d2cd5 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:03+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:09+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web
 #. openerp-web
index 75e354a..64e9a60 100644 (file)
@@ -14,15 +14,15 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:03+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:09+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web
 #. openerp-web
 #: code:addons/web/static/src/xml/base.xml:147
 #, python-format
 msgid "Default language:"
-msgstr "デフォルト言語:"
+msgstr "デフォルトの言語:"
 
 #. module: web
 #. openerp-web
@@ -503,7 +503,7 @@ msgstr "ログ (perm_read) のビュー"
 #: code:addons/web/static/src/js/view_form.js:1071
 #, python-format
 msgid "Set Default"
-msgstr "デフォルト値設定"
+msgstr "デフォルトに設定"
 
 #. module: web
 #. openerp-web
@@ -524,7 +524,7 @@ msgstr "数十秒前"
 #: code:addons/web/static/src/xml/base.xml:873
 #, python-format
 msgid "Condition:"
-msgstr "条件:"
+msgstr "状態:"
 
 #. module: web
 #. openerp-web
@@ -1564,7 +1564,7 @@ msgstr ""
 #: code:addons/web/static/src/xml/base.xml:899
 #, python-format
 msgid "All users"
-msgstr "全ユーザ"
+msgstr "全てのユーザ"
 
 #. module: web
 #. openerp-web
@@ -1664,7 +1664,7 @@ msgstr ""
 #: code:addons/web/static/src/js/view_form.js:1078
 #, python-format
 msgid "Save default"
-msgstr "デフォルト値保存"
+msgstr "デフォルトに保存"
 
 #. module: web
 #. openerp-web
@@ -1693,7 +1693,7 @@ msgstr "項目は空です。何も保存するものはありません。"
 #: code:addons/web/static/src/xml/base.xml:567
 #, python-format
 msgid "Manage Views"
-msgstr "ビュー管理"
+msgstr "ビューの管理"
 
 #. module: web
 #. openerp-web
@@ -1757,7 +1757,7 @@ msgstr "次の理由でインポートに失敗しました:"
 #: code:addons/web/static/src/xml/base.xml:561
 #, python-format
 msgid "JS Tests"
-msgstr "JSテスト"
+msgstr ""
 
 #. module: web
 #. openerp-web
@@ -1836,7 +1836,7 @@ msgstr "ドメイン:"
 #: code:addons/web/static/src/xml/base.xml:856
 #, python-format
 msgid "Default:"
-msgstr "デフォルト値:"
+msgstr "デフォルト:"
 
 #. module: web
 #. openerp-web
@@ -1928,7 +1928,7 @@ msgstr ""
 #: code:addons/web/static/src/xml/base.xml:559
 #, python-format
 msgid "Set Defaults"
-msgstr "デフォルト値設定"
+msgstr ""
 
 #. module: web
 #. openerp-web
@@ -2417,7 +2417,7 @@ msgstr "ID:"
 #: code:addons/web/static/src/xml/base.xml:892
 #, python-format
 msgid "Only you"
-msgstr "自分のみ"
+msgstr "あなただけ"
 
 #. module: web
 #. openerp-web
index fc1c920..cd2966b 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:02+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:08+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web
 #. openerp-web
index 8ca9fec..21a088b 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:03+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:09+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web
 #. openerp-web
index 185804a..5fafc78 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:03+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:09+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web
 #. openerp-web
index 7cc4df1..1431685 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:03+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:09+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web
 #. openerp-web
index 8ce0d5d..62d4823 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:03+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:09+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web
 #. openerp-web
index 51e740c..3f40b9e 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:03+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:09+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web
 #. openerp-web
index 6d682ee..b62a411 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:03+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:09+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web
 #. openerp-web
index 1375a92..d35b68a 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:03+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:09+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web
 #. openerp-web
index de49202..1493e5d 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:02+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:08+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web
 #. openerp-web
index f7d062e..506ac41 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:05+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web
 #. openerp-web
index 734b3cb..1148f69 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:04+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:09+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web
 #. openerp-web
index 0270262..039589d 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:04+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:09+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web
 #. openerp-web
index 4e9f441..f379e60 100644 (file)
@@ -15,8 +15,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:04+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:09+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web
 #. openerp-web
index 58c672b..72eb600 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:04+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:09+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web
 #. openerp-web
index 0acc7bb..4689690 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:04+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:09+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web
 #. openerp-web
index c722919..9503000 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:04+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:09+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web
 #. openerp-web
index 28d06e0..39da0f4 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:04+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:09+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web
 #. openerp-web
index 925ea5e..df99bfe 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:01+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:08+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web
 #. openerp-web
index 64a327e..3f5cf91 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:05+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web
 #. openerp-web
index 40b0a3b..1ae6794 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:04+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:09+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web
 #. openerp-web
index 2fc3f6a..4c00ffb 100644 (file)
@@ -14,15 +14,15 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:04+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:09+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web
 #. openerp-web
 #: code:addons/web/static/src/xml/base.xml:147
 #, python-format
 msgid "Default language:"
-msgstr "ภาษาหลัก"
+msgstr "ภาษาหลัก:"
 
 #. module: web
 #. openerp-web
index 61a1af1..b6bf3a3 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:04+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:09+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web
 #. openerp-web
index a52394b..3b850ca 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:04+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:09+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web
 #. openerp-web
index a69cd1b..bc1de8c 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:04+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:09+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web
 #. openerp-web
index 6b487c3..2b8c3e7 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:05+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web
 #. openerp-web
index fbe1c31..13cd371 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:05+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web
 #. openerp-web
index 1966940..6ac490b 100644 (file)
@@ -6,7 +6,7 @@
 .cleditorButton {float:left; width:24px; height:24px; margin:1px 0 1px 0; background: url('images/buttons.gif')}\r
 .cleditorDisabled {opacity:0.3; filter:alpha(opacity=30)}\r
 .cleditorDivider {float:left; width:1px; height:23px; margin:1px 0 1px 0; background:#CCC}\r
-.cleditorPopup {border:solid 1px #999; background-color:white; color:#333333; position:absolute; font:10pt Arial,Verdana; cursor:default; z-index:10000}\r
+.cleditorPopup {border:solid 1px #999; background-color:white; position:absolute; font:10pt Arial,Verdana; cursor:default; z-index:10000}\r
 .cleditorList div {padding:2px 4px 2px 4px}\r
 .cleditorList p,\r
 .cleditorList h1,\r
index cf98288..3de9089 100644 (file)
@@ -1,13 +1,18 @@
-/*!\r
- CLEditor WYSIWYG HTML Editor v1.4.4\r
- http://premiumsoftware.net/CLEditor\r
+/**\r
+ @preserve CLEditor WYSIWYG HTML Editor v1.3.0\r
+ http://premiumsoftware.net/cleditor\r
  requires jQuery v1.4.2 or later\r
 \r
  Copyright 2010, Chris Landowski, Premium Software, LLC\r
  Dual licensed under the MIT or GPL Version 2 licenses.\r
 */\r
 \r
-(function ($) {\r
+// ==ClosureCompiler==\r
+// @compilation_level SIMPLE_OPTIMIZATIONS\r
+// @output_file_name jquery.cleditor.min.js\r
+// ==/ClosureCompiler==\r
+\r
+(function($) {\r
 \r
   //==============\r
   // jQuery Plugin\r
@@ -17,7 +22,7 @@
 \r
     // Define the defaults used for all new cleditor instances\r
     defaultOptions: {\r
-      width:        'auto', // width not including margins, borders or padding\r
+      width:        500, // width not including margins, borders or padding\r
       height:       250, // height not including margins, borders or padding\r
       controls:     // controls to add to the toolbar\r
                     "bold italic underline strikethrough subscript superscript | font size " +\r
@@ -41,7 +46,7 @@
                     [["Paragraph", "<p>"], ["Header 1", "<h1>"], ["Header 2", "<h2>"],\r
                     ["Header 3", "<h3>"],  ["Header 4","<h4>"],  ["Header 5","<h5>"],\r
                     ["Header 6","<h6>"]],\r
-      useCSS:       true, // use CSS to style HTML when possible (not supported in ie)\r
+      useCSS:       false, // use CSS to style HTML when possible (not supported in ie)\r
       docType:      // Document type contained within the editor\r
                     '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">',\r
       docCSSFile:   // CSS file used to style the document contained within the editor\r
@@ -52,7 +57,7 @@
 \r
     // Define all usable toolbar buttons - the init string property is \r
     //   expanded during initialization back into the buttons object and \r
-    //   separate object properties are created for each button.\r
+    //   seperate object properties are created for each button.\r
     //   e.g. buttons.size.title = "Font Size"\r
     buttons: {\r
       // name,title,command,popupName (""=use name)\r
 \r
     // Loop through all matching textareas and create the editors\r
     this.each(function(idx, elem) {\r
-      if (elem.tagName.toUpperCase() === "TEXTAREA") {\r
+      if (elem.tagName == "TEXTAREA") {\r
         var data = $.data(elem, CLEDITOR);\r
         if (!data) data = new cleditor(elem, options);\r
         $result = $result.add(data);\r
 \r
   // Misc constants\r
   BACKGROUND_COLOR = "backgroundColor",\r
-  BLURRED          = "blurred",\r
   BUTTON           = "button",\r
   BUTTON_NAME      = "buttonName",\r
   CHANGE           = "change",\r
   CLICK            = "click",\r
   DISABLED         = "disabled",\r
   DIV_TAG          = "<div>",\r
-  FOCUSED          = "focused",\r
   TRANSPARENT      = "transparent",\r
   UNSELECTABLE     = "unselectable",\r
 \r
   PROMPT_CLASS     = "cleditorPrompt",  // prompt popup divs inside body\r
   MSG_CLASS        = "cleditorMsg",     // message popup div inside body\r
 \r
-  // Browser detection\r
-  ua = navigator.userAgent.toLowerCase(),\r
-  ie = /msie/.test(ua),\r
-  ie6 = /msie\s6/.test(ua),\r
-  iege11 = /(trident)(?:.*rv:([\w.]+))?/.test(ua),\r
-  webkit = /webkit/.test(ua),\r
+  // Test for ie\r
+  ie = $.browser.msie,\r
+  ie6 = /msie\s6/i.test(navigator.userAgent),\r
 \r
   // Test for iPhone/iTouch/iPad\r
-  iOS = /iphone|ipad|ipod/i.test(ua),\r
+  iOS = /iphone|ipad|ipod/i.test(navigator.userAgent),\r
 \r
   // Popups are created once as needed and shared by all editor instances\r
   popups = {},\r
     var $group = $(DIV_TAG)\r
       .addClass(GROUP_CLASS)\r
       .appendTo($toolbar);\r
-\r
-    // Initialize the group width\r
-    var groupWidth = 0;\r
     \r
     // Add the buttons to the toolbar\r
     $.each(options.controls.split(" "), function(idx, buttonName) {\r
       if (buttonName === "") return true;\r
 \r
       // Divider\r
-      if (buttonName === "|") {\r
+      if (buttonName == "|") {\r
 \r
         // Add a new divider to the group\r
         var $div = $(DIV_TAG)\r
           .addClass(DIVIDER_CLASS)\r
           .appendTo($group);\r
 \r
-        // Update the group width\r
-        $group.width(groupWidth + 1);\r
-        groupWidth = 0;\r
-\r
         // Create a new group\r
         $group = $(DIV_TAG)\r
           .addClass(GROUP_CLASS)\r
           .appendTo($group)\r
           .hover(hoverEnter, hoverLeave);\r
 \r
-        // Update the group width\r
-        groupWidth += 24;\r
-        $group.width(groupWidth + 1);\r
-\r
         // Prepare the button image\r
         var map = {};\r
         if (button.css) map = button.css;\r
 \r
     // Bind the window resize event when the width or height is auto or %\r
     if (/auto|%/.test("" + options.width + options.height))\r
-      $(window).bind('resize.cleditor', function () {\r
+      $(window).resize(function() {\r
         //Forcefully blurred iframe contentWindow, chrome, IE, safari doesn't trigger blur on window resize and due to which text disappears\r
         var contentWindow = editor.$frame[0].contentWindow;\r
         if(!$.browser.mozilla && contentWindow){\r
           refresh(editor);\r
         }\r
       });\r
+\r
     // Create the iframe and resize the controls\r
     refresh(editor);\r
 \r
       return editor;\r
     };\r
   });\r
-  \r
-  // blurred - shortcut for .bind("blurred", handler) or .trigger("blurred")\r
-  fn.blurred = function(handler) {\r
-    var $this = $(this);\r
-    return handler ? $this.bind(BLURRED, handler) : $this.trigger(BLURRED);\r
-  };\r
 \r
   // change - shortcut for .bind("change", handler) or .trigger("change")\r
-  fn.change = function change(handler) {\r
-    console.log('change test');\r
+  fn.change = function(handler) {\r
     var $this = $(this);\r
     return handler ? $this.bind(CHANGE, handler) : $this.trigger(CHANGE);\r
   };\r
 \r
-  // focused - shortcut for .bind("focused", handler) or .trigger("focused")\r
-  fn.focused = function(handler) {\r
-    var $this = $(this);\r
-    return handler ? $this.bind(FOCUSED, handler) : $this.trigger(FOCUSED);\r
-  };\r
-\r
   //===============\r
   // Event Handlers\r
   //===============\r
         popup = popups[popupName];\r
 \r
     // Check if disabled\r
-    if (editor.disabled || $(buttonDiv).attr(DISABLED) === DISABLED)\r
+    if (editor.disabled || $(buttonDiv).attr(DISABLED) == DISABLED)\r
       return;\r
 \r
     // Fire the buttonClick event\r
       return false;\r
 \r
     // Toggle source\r
-    if (buttonName === "source") {\r
+    if (buttonName == "source") {\r
 \r
       // Show the iframe\r
       if (sourceMode(editor)) {\r
         var $popup = $(popup);\r
 \r
         // URL\r
-        if (popupName === "url") {\r
+        if (popupName == "url") {\r
 \r
           // Check for selection before showing the link url popup\r
-          if (buttonName === "link" && selectedText(editor) === "") {\r
+          if (buttonName == "link" && selectedText(editor) === "") {\r
             showMessage(editor, "A selection is required when inserting a link.", buttonDiv);\r
             return false;\r
           }\r
         }\r
 \r
         // Paste as Text\r
-        else if (popupName === "pastetext") {\r
+        else if (popupName == "pastetext") {\r
 \r
           // Wire up the submit button click event handler\r
           $popup.children(":button")\r
           return false; // stop propagination to document click\r
         }\r
 \r
-        // propaginate to document click\r
+        // propaginate to documnt click\r
         return;\r
 \r
       }\r
 \r
       // Print\r
-      else if (buttonName === "print")\r
+      else if (buttonName == "print")\r
         editor.$frame[0].contentWindow.print();\r
 \r
       // All other buttons\r
         useCSS = editor.options.useCSS;\r
 \r
     // Get the command value\r
-    if (buttonName === "font")\r
+    if (buttonName == "font")\r
       // Opera returns the fontfamily wrapped in quotes\r
       value = target.style.fontFamily.replace(/"/g, "");\r
-    else if (buttonName === "size") {\r
-      if (target.tagName.toUpperCase() === "DIV")\r
+    else if (buttonName == "size") {\r
+      if (target.tagName == "DIV")\r
         target = target.children[0];\r
       value = target.innerHTML;\r
     }\r
-    else if (buttonName === "style")\r
+    else if (buttonName == "style")\r
       value = "<" + target.tagName + ">";\r
-    else if (buttonName === "color")\r
+    else if (buttonName == "color")\r
       value = hex(target.style.backgroundColor);\r
-    else if (buttonName === "highlight") {\r
+    else if (buttonName == "highlight") {\r
       value = hex(target.style.backgroundColor);\r
       if (ie) command = 'backcolor';\r
       else useCSS = true;\r
       $popup.html(popupContent);\r
 \r
     // Color\r
-    else if (popupName === "color") {\r
+    else if (popupName == "color") {\r
       var colors = options.colors.split(" ");\r
       if (colors.length < 10)\r
         $popup.width("auto");\r
     }\r
 \r
     // Font\r
-    else if (popupName === "font")\r
+    else if (popupName == "font")\r
       $.each(options.fonts.split(","), function(idx, font) {\r
         $(DIV_TAG).appendTo($popup)\r
           .css("fontFamily", font)\r
       });\r
 \r
     // Size\r
-    else if (popupName === "size")\r
+    else if (popupName == "size")\r
       $.each(options.sizes.split(","), function(idx, size) {\r
         $(DIV_TAG).appendTo($popup)\r
-          .html('<font size="' + size + '">' + size + '</font>');\r
+          .html("<font size=" + size + ">" + size + "</font>");\r
       });\r
 \r
     // Style\r
-    else if (popupName === "style")\r
+    else if (popupName == "style")\r
       $.each(options.styles, function(idx, style) {\r
         $(DIV_TAG).appendTo($popup)\r
           .html(style[1] + style[0] + style[1].replace("<", "</"));\r
       });\r
 \r
     // URL\r
-    else if (popupName === "url") {\r
-      $popup.html('Enter URL:<br /><input type="text" value="http://" size="35" /><br /><input type="button" value="Submit" />');\r
+    else if (popupName == "url") {\r
+      $popup.html('Enter URL:<br><input type=text value="http://" size=35><br><input type=button value="Submit">');\r
       popupTypeClass = PROMPT_CLASS;\r
     }\r
 \r
     // Paste as Text\r
-    else if (popupName === "pastetext") {\r
-      $popup.html('Paste your content here and click submit.<br /><textarea cols="40" rows="3"></textarea><br /><input type="button" value="Submit" />');\r
+    else if (popupName == "pastetext") {\r
+      $popup.html('Paste your content here and click submit.<br /><textarea cols=40 rows=3></textarea><br /><input type=button value=Submit>');\r
       popupTypeClass = PROMPT_CLASS;\r
     }\r
 \r
     }\r
 \r
     // Execute the command and check for error\r
-    var success = true, message;\r
-    if (ie && command.toLowerCase() === "inserthtml")\r
+    var success = true, description;\r
+    if (ie && command.toLowerCase() == "inserthtml")\r
       getRange(editor).pasteHTML(value);\r
     else {\r
       try { success = editor.doc.execCommand(command, 0, value || null); }\r
-      catch (err) { message = err.message; success = false; }\r
+      catch (err) { description = err.description; success = false; }\r
       if (!success) {\r
         if ("cutcopypaste".indexOf(command) > -1)\r
           showMessage(editor, "For security reasons, your browser does not support the " +\r
             button);\r
         else\r
           showMessage(editor,\r
-            (message ? message : "Error executing the " + command + " command."),\r
+            (description ? description : "Error executing the " + command + " command."),\r
             button);\r
       }\r
     }\r
 \r
-    // Enable the buttons and update the textarea\r
+    // Enable the buttons\r
     refreshButtons(editor);\r
-    updateTextArea(editor, true);\r
     return success;\r
 \r
   }\r
     return editor.$frame[0].contentWindow.getSelection();\r
   }\r
 \r
-  // hex - returns the hex value for the passed in color string\r
+  // Returns the hex value for the passed in string.\r
+  //   hex("rgb(255, 0, 0)"); // #FF0000\r
+  //   hex("#FF0000"); // #FF0000\r
+  //   hex("#F00"); // #FF0000\r
   function hex(s) {\r
-\r
-    // hex("rgb(255, 0, 0)") returns #FF0000\r
-    var m = /rgba?\((\d+), (\d+), (\d+)/.exec(s);\r
+    var m = /rgba?\((\d+), (\d+), (\d+)/.exec(s),\r
+      c = s.split("");\r
     if (m) {\r
-      s = (m[1] << 16 | m[2] << 8 | m[3]).toString(16);\r
+      s = ( m[1] << 16 | m[2] << 8 | m[3] ).toString(16);\r
       while (s.length < 6)\r
         s = "0" + s;\r
-      return "#" + s;\r
     }\r
-\r
-    // hex("#F00") returns #FF0000\r
-    var c = s.split("");\r
-    if (s.length === 4)\r
-      return "#" + c[1] + c[1] + c[2] + c[2] + c[3] + c[3];\r
-\r
-    // hex("#FF0000") returns #FF0000\r
-    return s;\r
-\r
+    return "#" + (s.length == 6 ? s : c[1] + c[1] + c[2] + c[2] + c[3] + c[3]);\r
   }\r
 \r
   // hidePopups - hides all popups\r
 \r
   // imagesPath - returns the path to the images folder\r
   function imagesPath() {\r
-    var href = $("link[href*=cleditor]").attr("href");\r
-    return href.replace(/^(.*\/)[^\/]+$/, '$1') + "images/";\r
+    var cssFile = "jquery.cleditor.css",\r
+        href = $("link[href$='" + cssFile +"']").attr("href");\r
+    return href.substr(0, href.length - cssFile.length) + "images/";\r
   }\r
 \r
   // imageUrl - Returns the css url string for a filemane\r
       editor.$frame.remove();\r
 \r
     // Create a new iframe\r
-    var $frame = editor.$frame = $('<iframe frameborder="0" src="javascript:true;" />')\r
+    var $frame = editor.$frame = $('<iframe frameborder="0" src="javascript:true;">')\r
       .hide()\r
       .appendTo($main);\r
 \r
 \r
     // Work around for bug in IE which causes the editor to lose\r
     // focus when clicking below the end of the document.\r
-    if (ie || iege11)\r
+    if (ie)\r
       $doc.click(function() {focus(editor);});\r
 \r
     // Load the content\r
     updateFrame(editor);\r
 \r
     // Bind the ie specific iframe event handlers\r
-    if (ie || iege11) {\r
+    if (ie) {\r
 \r
       // Save the current user selection. This code is needed since IE will\r
       // reset the selection just after the beforedeactivate event and just\r
       $doc.bind("beforedeactivate beforeactivate selectionchange keypress", function(e) {\r
         \r
         // Flag the editor as inactive\r
-        if (e.type === "beforedeactivate")\r
+        if (e.type == "beforedeactivate")\r
           editor.inactive = true;\r
-\r
-          // Get rid of the bogus selection and flag the editor as active\r
-        else if (e.type === "beforeactivate") {\r
+        \r
+        // Get rid of the bogus selection and flag the editor as active\r
+        else if (e.type == "beforeactivate") {\r
           if (!editor.inactive && editor.range && editor.range.length > 1)\r
             editor.range.shift();\r
           delete editor.inactive;\r
         }\r
 \r
-          // Save the selection when the editor is active\r
+        // Save the selection when the editor is active\r
         else if (!editor.inactive) {\r
-          if (!editor.range)\r
+          if (!editor.range) \r
             editor.range = [];\r
           editor.range.unshift(getRange(editor));\r
 \r
 \r
       });\r
 \r
-      // Restore the text range and trigger focused event when the iframe gains focus\r
+      // Restore the text range when the iframe gains focus\r
       $frame.focus(function() {\r
         restoreRange(editor);\r
-        $(editor).triggerHandler(FOCUSED);\r
-      });\r
-\r
-      // Trigger blurred event when the iframe looses focus\r
-      $frame.blur(function() {\r
-        $(editor).triggerHandler(BLURRED);\r
       });\r
 \r
     }\r
 \r
-      // Trigger focused and blurred events for all other browsers\r
-    else {\r
-      $(editor.$frame[0].contentWindow)\r
-        .focus(function () { $(editor).triggerHandler(FOCUSED); })\r
-        .blur(function () { $(editor).triggerHandler(BLURRED); });\r
-    }\r
+    // Update the textarea when the iframe loses focus\r
+    ($.browser.mozilla ? $doc : $(contentWindow)).blur(function() {\r
+      updateTextArea(editor, true);\r
+    });\r
 \r
-    // Enable the toolbar buttons and update the textarea as the user types or clicks\r
+    // Enable the toolbar buttons as the user types or clicks\r
     $doc.click(hidePopups)\r
       .bind("keyup mouseup", function() {\r
         refreshButtons(editor);\r
-        updateTextArea(editor, true);\r
       });\r
 \r
     // Show the textarea for iPhone/iTouch/iPad or\r
       $toolbar.height(hgt);\r
 \r
       // Resize the iframe\r
-      hgt = (/%/.test("" + options.height) ? $main.height() : parseInt(options.height, 10)) - hgt;\r
+      hgt = (/%/.test("" + options.height) ? $main.height() : parseInt(options.height)) - hgt;\r
       $frame.width(wid).height(hgt);\r
 \r
       // Resize the textarea. IE6 textareas have a 1px top\r
   function refreshButtons(editor) {\r
 \r
     // Webkit requires focus before queryCommandEnabled will return anything but false\r
-    if (!iOS && webkit && !editor.focused) {\r
+    if (!iOS && $.browser.webkit && !editor.focused) {\r
       editor.$frame[0].contentWindow.focus();\r
       window.focus();\r
       editor.focused = true;\r
         if (enabled === undefined)\r
           enabled = true;\r
       }\r
-      else if (((inSourceMode || iOS) && button.name !== "source") ||\r
-      (ie && (command === "undo" || command === "redo")))\r
+      else if (((inSourceMode || iOS) && button.name != "source") ||\r
+      (ie && (command == "undo" || command == "redo")))\r
         enabled = false;\r
-      else if (command && command !== "print") {\r
-        if (ie && command === "hilitecolor")\r
+      else if (command && command != "print") {\r
+        if (ie && command == "hilitecolor")\r
           command = "backcolor";\r
         // IE does not support inserthtml, so it's always enabled\r
-        if (!ie || command !== "inserthtml") {\r
+        if (!ie || command != "inserthtml") {\r
           try {enabled = queryObj.queryCommandEnabled(command);}\r
           catch (err) {enabled = false;}\r
         }\r
 \r
   // restoreRange - restores the current ie selection\r
   function restoreRange(editor) {\r
-    if (editor.range) {\r
-      if (ie)\r
-        editor.range[0].select();\r
-      else if (iege11)\r
-        getSelection(editor).addRange(editor.range[0]);\r
-    }\r
+    if (ie && editor.range)\r
+      editor.range[0].select();\r
   }\r
 \r
   // select - selects all the text in either the textarea or iframe\r
     // of potentially heavy updateFrame callbacks.\r
     if (updateFrameCallback) {\r
       var sum = checksum(code);\r
-      if (checkForChange && editor.areaChecksum === sum)\r
+      if (checkForChange && editor.areaChecksum == sum)\r
         return;\r
       editor.areaChecksum = sum;\r
     }\r
       editor.frameChecksum = checksum(html);\r
 \r
     // Update the iframe and trigger the change event\r
-    if (html !== $body.html()) {\r
+    if (html != $body.html()) {\r
       $body.html(html);\r
       $(editor).triggerHandler(CHANGE);\r
     }\r
     // of potentially heavy updateTextArea callbacks.\r
     if (updateTextAreaCallback) {\r
       var sum = checksum(html);\r
-      if (checkForChange && editor.frameChecksum === sum)\r
+      if (checkForChange && editor.frameChecksum == sum)\r
         return;\r
       editor.frameChecksum = sum;\r
     }\r
       editor.areaChecksum = checksum(code);\r
 \r
     // Update the textarea and trigger the change event\r
-    if (code !== $area.val()) {\r
+    if (code != $area.val()) {\r
       $area.val(code);\r
       $(editor).triggerHandler(CHANGE);\r
     }\r
diff --git a/addons/web/static/lib/cleditor/jquery.cleditor.min.js b/addons/web/static/lib/cleditor/jquery.cleditor.min.js
new file mode 100644 (file)
index 0000000..5afec04
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ CLEditor WYSIWYG HTML Editor v1.3.0
+ http://premiumsoftware.net/cleditor
+ requires jQuery v1.4.2 or later
+
+ Copyright 2010, Chris Landowski, Premium Software, LLC
+ Dual licensed under the MIT or GPL Version 2 licenses.
+*/
+(function(e){function aa(a){var b=this,c=a.target,d=e.data(c,x),h=s[d],f=h.popupName,i=p[f];if(!(b.disabled||e(c).attr(n)==n)){var g={editor:b,button:c,buttonName:d,popup:i,popupName:f,command:h.command,useCSS:b.options.useCSS};if(h.buttonClick&&h.buttonClick(a,g)===false)return false;if(d=="source"){if(t(b)){delete b.range;b.$area.hide();b.$frame.show();c.title=h.title}else{b.$frame.hide();b.$area.show();c.title="Show Rich Text"}setTimeout(function(){u(b)},100)}else if(!t(b))if(f){var j=e(i);if(f==
+"url"){if(d=="link"&&M(b)===""){z(b,"A selection is required when inserting a link.",c);return false}j.children(":button").unbind(q).bind(q,function(){var k=j.find(":text"),o=e.trim(k.val());o!==""&&v(b,g.command,o,null,g.button);k.val("http://");r();w(b)})}else f=="pastetext"&&j.children(":button").unbind(q).bind(q,function(){var k=j.find("textarea"),o=k.val().replace(/\n/g,"<br />");o!==""&&v(b,g.command,o,null,g.button);k.val("");r();w(b)});if(c!==e.data(i,A)){N(b,i,c);return false}return}else if(d==
+"print")b.$frame[0].contentWindow.print();else if(!v(b,g.command,g.value,g.useCSS,c))return false;w(b)}}function O(a){a=e(a.target).closest("div");a.css(H,a.data(x)?"#FFF":"#FFC")}function P(a){e(a.target).closest("div").css(H,"transparent")}function ba(a){var b=a.data.popup,c=a.target;if(!(b===p.msg||e(b).hasClass(B))){var d=e.data(b,A),h=e.data(d,x),f=s[h],i=f.command,g,j=this.options.useCSS;if(h=="font")g=c.style.fontFamily.replace(/"/g,"");else if(h=="size"){if(c.tagName=="DIV")c=c.children[0];
+g=c.innerHTML}else if(h=="style")g="<"+c.tagName+">";else if(h=="color")g=Q(c.style.backgroundColor);else if(h=="highlight"){g=Q(c.style.backgroundColor);if(l)i="backcolor";else j=true}b={editor:this,button:d,buttonName:h,popup:b,popupName:f.popupName,command:i,value:g,useCSS:j};if(!(f.popupClick&&f.popupClick(a,b)===false)){if(b.command&&!v(this,b.command,b.value,b.useCSS,d))return false;r();w(this)}}}function C(a){for(var b=1,c=0,d=0;d<a.length;++d){b=(b+a.charCodeAt(d))%65521;c=(c+b)%65521}return c<<
+16|b}function R(a,b,c,d,h){if(p[a])return p[a];var f=e(m).hide().addClass(ca).appendTo("body");if(d)f.html(d);else if(a=="color"){b=b.colors.split(" ");b.length<10&&f.width("auto");e.each(b,function(i,g){e(m).appendTo(f).css(H,"#"+g)});c=da}else if(a=="font")e.each(b.fonts.split(","),function(i,g){e(m).appendTo(f).css("fontFamily",g).html(g)});else if(a=="size")e.each(b.sizes.split(","),function(i,g){e(m).appendTo(f).html("<font size="+g+">"+g+"</font>")});else if(a=="style")e.each(b.styles,function(i,
+g){e(m).appendTo(f).html(g[1]+g[0]+g[1].replace("<","</"))});else if(a=="url"){f.html('Enter URL:<br><input type=text value="http://" size=35><br><input type=button value="Submit">');c=B}else if(a=="pastetext"){f.html("Paste your content here and click submit.<br /><textarea cols=40 rows=3></textarea><br /><input type=button value=Submit>");c=B}if(!c&&!d)c=S;f.addClass(c);l&&f.attr(I,"on").find("div,font,p,h1,h2,h3,h4,h5,h6").attr(I,"on");if(f.hasClass(S)||h===true)f.children().hover(O,P);p[a]=f[0];
+return f[0]}function T(a,b){if(b){a.$area.attr(n,n);a.disabled=true}else{a.$area.removeAttr(n);delete a.disabled}try{if(l)a.doc.body.contentEditable=!b;else a.doc.designMode=!b?"on":"off"}catch(c){}u(a)}function v(a,b,c,d,h){D(a);if(!l){if(d===undefined||d===null)d=a.options.useCSS;a.doc.execCommand("styleWithCSS",0,d.toString())}d=true;var f;if(l&&b.toLowerCase()=="inserthtml")y(a).pasteHTML(c);else{try{d=a.doc.execCommand(b,0,c||null)}catch(i){f=i.description;d=false}d||("cutcopypaste".indexOf(b)>
+-1?z(a,"For security reasons, your browser does not support the "+b+" command. Try using the keyboard shortcut or context menu instead.",h):z(a,f?f:"Error executing the "+b+" command.",h))}u(a);return d}function w(a){setTimeout(function(){t(a)?a.$area.focus():a.$frame[0].contentWindow.focus();u(a)},0)}function y(a){if(l)return J(a).createRange();return J(a).getRangeAt(0)}function J(a){if(l)return a.doc.selection;return a.$frame[0].contentWindow.getSelection()}function Q(a){var b=/rgba?\((\d+), (\d+), (\d+)/.exec(a),
+c=a.split("");if(b)for(a=(b[1]<<16|b[2]<<8|b[3]).toString(16);a.length<6;)a="0"+a;return"#"+(a.length==6?a:c[1]+c[1]+c[2]+c[2]+c[3]+c[3])}function r(){e.each(p,function(a,b){e(b).hide().unbind(q).removeData(A)})}function U(){var a=e("link[href$='jquery.cleditor.css']").attr("href");return a.substr(0,a.length-19)+"images/"}function K(a){var b=a.$main,c=a.options;a.$frame&&a.$frame.remove();var d=a.$frame=e('<iframe frameborder="0" src="javascript:true;">').hide().appendTo(b),h=d[0].contentWindow,f=
+a.doc=h.document,i=e(f);f.open();f.write(c.docType+"<html>"+(c.docCSSFile===""?"":'<head><link rel="stylesheet" type="text/css" href="'+c.docCSSFile+'" /></head>')+'<body style="'+c.bodyStyle+'"></body></html>');f.close();l&&i.click(function(){w(a)});E(a);if(l){i.bind("beforedeactivate beforeactivate selectionchange keypress",function(g){if(g.type=="beforedeactivate")a.inactive=true;else if(g.type=="beforeactivate"){!a.inactive&&a.range&&a.range.length>1&&a.range.shift();delete a.inactive}else if(!a.inactive){if(!a.range)a.range=
+[];for(a.range.unshift(y(a));a.range.length>2;)a.range.pop()}});d.focus(function(){D(a)})}(e.browser.mozilla?i:e(h)).blur(function(){V(a,true)});i.click(r).bind("keyup mouseup",function(){u(a)});L?a.$area.show():d.show();e(function(){var g=a.$toolbar,j=g.children("div:last"),k=b.width();j=j.offset().top+j.outerHeight()-g.offset().top+1;g.height(j);j=(/%/.test(""+c.height)?b.height():parseInt(c.height))-j;d.width(k).height(j);a.$area.width(k).height(ea?j-2:j);T(a,a.disabled);u(a)})}function u(a){if(!L&&
+e.browser.webkit&&!a.focused){a.$frame[0].contentWindow.focus();window.focus();a.focused=true}var b=a.doc;if(l)b=y(a);var c=t(a);e.each(a.$toolbar.find("."+W),function(d,h){var f=e(h),i=e.cleditor.buttons[e.data(h,x)],g=i.command,j=true;if(a.disabled)j=false;else if(i.getEnabled){j=i.getEnabled({editor:a,button:h,buttonName:i.name,popup:p[i.popupName],popupName:i.popupName,command:i.command,useCSS:a.options.useCSS});if(j===undefined)j=true}else if((c||L)&&i.name!="source"||l&&(g=="undo"||g=="redo"))j=
+false;else if(g&&g!="print"){if(l&&g=="hilitecolor")g="backcolor";if(!l||g!="inserthtml")try{j=b.queryCommandEnabled(g)}catch(k){j=false}}if(j){f.removeClass(X);f.removeAttr(n)}else{f.addClass(X);f.attr(n,n)}})}function D(a){l&&a.range&&a.range[0].select()}function M(a){D(a);if(l)return y(a).text;return J(a).toString()}function z(a,b,c){var d=R("msg",a.options,fa);d.innerHTML=b;N(a,d,c)}function N(a,b,c){var d,h,f=e(b);if(c){var i=e(c);d=i.offset();h=--d.left;d=d.top+i.height()}else{i=a.$toolbar;
+d=i.offset();h=Math.floor((i.width()-f.width())/2)+d.left;d=d.top+i.height()-2}r();f.css({left:h,top:d}).show();if(c){e.data(b,A,c);f.bind(q,{popup:b},e.proxy(ba,a))}setTimeout(function(){f.find(":text,textarea").eq(0).focus().select()},100)}function t(a){return a.$area.is(":visible")}function E(a,b){var c=a.$area.val(),d=a.options,h=d.updateFrame,f=e(a.doc.body);if(h){var i=C(c);if(b&&a.areaChecksum==i)return;a.areaChecksum=i}c=h?h(c):c;c=c.replace(/<(?=\/?script)/ig,"&lt;");if(d.updateTextArea)a.frameChecksum=
+C(c);if(c!=f.html()){f.html(c);e(a).triggerHandler(F)}}function V(a,b){var c=e(a.doc.body).html(),d=a.options,h=d.updateTextArea,f=a.$area;if(h){var i=C(c);if(b&&a.frameChecksum==i)return;a.frameChecksum=i}c=h?h(c):c;if(d.updateFrame)a.areaChecksum=C(c);if(c!=f.val()){f.val(c);e(a).triggerHandler(F)}}e.cleditor={defaultOptions:{width:500,height:250,controls:"bold italic underline strikethrough subscript superscript | font size style | color highlight removeformat | bullets numbering | outdent indent | alignleft center alignright justify | undo redo | rule image link unlink | cut copy paste pastetext | print source",
+colors:"FFF FCC FC9 FF9 FFC 9F9 9FF CFF CCF FCF CCC F66 F96 FF6 FF3 6F9 3FF 6FF 99F F9F BBB F00 F90 FC6 FF0 3F3 6CC 3CF 66C C6C 999 C00 F60 FC3 FC0 3C0 0CC 36F 63F C3C 666 900 C60 C93 990 090 399 33F 60C 939 333 600 930 963 660 060 366 009 339 636 000 300 630 633 330 030 033 006 309 303",fonts:"Arial,Arial Black,Comic Sans MS,Courier New,Narrow,Garamond,Georgia,Impact,Sans Serif,Serif,Tahoma,Trebuchet MS,Verdana",sizes:"1,2,3,4,5,6,7",styles:[["Paragraph","<p>"],["Header 1","<h1>"],["Header 2","<h2>"],
+["Header 3","<h3>"],["Header 4","<h4>"],["Header 5","<h5>"],["Header 6","<h6>"]],useCSS:false,docType:'<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">',docCSSFile:"",bodyStyle:"margin:4px; font:10pt Arial,Verdana; cursor:text"},buttons:{init:"bold,,|italic,,|underline,,|strikethrough,,|subscript,,|superscript,,|font,,fontname,|size,Font Size,fontsize,|style,,formatblock,|color,Font Color,forecolor,|highlight,Text Highlight Color,hilitecolor,color|removeformat,Remove Formatting,|bullets,,insertunorderedlist|numbering,,insertorderedlist|outdent,,|indent,,|alignleft,Align Text Left,justifyleft|center,,justifycenter|alignright,Align Text Right,justifyright|justify,,justifyfull|undo,,|redo,,|rule,Insert Horizontal Rule,inserthorizontalrule|image,Insert Image,insertimage,url|link,Insert Hyperlink,createlink,url|unlink,Remove Hyperlink,|cut,,|copy,,|paste,,|pastetext,Paste as Text,inserthtml,|print,,|source,Show Source"},
+imagesPath:function(){return U()}};e.fn.cleditor=function(a){var b=e([]);this.each(function(c,d){if(d.tagName=="TEXTAREA"){var h=e.data(d,Y);h||(h=new cleditor(d,a));b=b.add(h)}});return b};var H="backgroundColor",A="button",x="buttonName",F="change",Y="cleditor",q="click",n="disabled",m="<div>",I="unselectable",W="cleditorButton",X="cleditorDisabled",ca="cleditorPopup",S="cleditorList",da="cleditorColor",B="cleditorPrompt",fa="cleditorMsg",l=e.browser.msie,ea=/msie\s6/i.test(navigator.userAgent),
+L=/iphone|ipad|ipod/i.test(navigator.userAgent),p={},Z,s=e.cleditor.buttons;e.each(s.init.split("|"),function(a,b){var c=b.split(","),d=c[0];s[d]={stripIndex:a,name:d,title:c[1]===""?d.charAt(0).toUpperCase()+d.substr(1):c[1],command:c[2]===""?d:c[2],popupName:c[3]===""?d:c[3]}});delete s.init;cleditor=function(a,b){var c=this;c.options=b=e.extend({},e.cleditor.defaultOptions,b);var d=c.$area=e(a).hide().data(Y,c).blur(function(){E(c,true)}),h=c.$main=e(m).addClass("cleditorMain").width(b.width).height(b.height),
+f=c.$toolbar=e(m).addClass("cleditorToolbar").appendTo(h),i=e(m).addClass("cleditorGroup").appendTo(f);e.each(b.controls.split(" "),function(g,j){if(j==="")return true;if(j=="|"){e(m).addClass("cleditorDivider").appendTo(i);i=e(m).addClass("cleditorGroup").appendTo(f)}else{var k=s[j],o=e(m).data(x,k.name).addClass(W).attr("title",k.title).bind(q,e.proxy(aa,c)).appendTo(i).hover(O,P),G={};if(k.css)G=k.css;else if(k.image)G.backgroundImage="url("+U()+k.image+")";if(k.stripIndex)G.backgroundPosition=
+k.stripIndex*-24;o.css(G);l&&o.attr(I,"on");k.popupName&&R(k.popupName,b,k.popupClass,k.popupContent,k.popupHover)}});h.insertBefore(d).append(d);if(!Z){e(document).click(function(g){g=e(g.target);g.add(g.parents()).is("."+B)||r()});Z=true}/auto|%/.test(""+b.width+b.height)&&e(window).resize(function(){K(c)});K(c)};var $=cleditor.prototype;e.each([["clear",function(a){a.$area.val("");E(a)}],["disable",T],["execCommand",v],["focus",w],["hidePopups",r],["sourceMode",t,true],["refresh",K],["select",
+function(a){setTimeout(function(){t(a)?a.$area.select():v(a,"selectall")},0)}],["selectedHTML",function(a){D(a);a=y(a);if(l)return a.htmlText;var b=e("<layer>")[0];b.appendChild(a.cloneContents());return b.innerHTML},true],["selectedText",M,true],["showMessage",z],["updateFrame",E],["updateTextArea",V]],function(a,b){$[b[0]]=function(){for(var c=[this],d=0;d<arguments.length;d++)c.push(arguments[d]);c=b[1].apply(this,c);if(b[2])return c;return this}});$.change=function(a){var b=e(this);return a?b.bind(F,
+a):b.trigger(F)}})(jQuery);
\ No newline at end of file
index 7fa0e6f..048cff9 100644 (file)
@@ -13,7 +13,7 @@
 }
 .fa {
   display: inline-block;
-  font-family: FontAwesome !important;
+  font-family: FontAwesome;
   font-style: normal;
   font-weight: normal;
   line-height: 1;
index ca61fdc..b50115d 100644 (file)
@@ -1,6 +1,6 @@
-//     Underscore.js 1.6.0
+//     Underscore.js 1.5.2
 //     http://underscorejs.org
-//     (c) 2009-2014 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
+//     (c) 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
 //     Underscore may be freely distributed under the MIT license.
 
 (function() {
@@ -65,7 +65,7 @@
   }
 
   // Current version.
-  _.VERSION = '1.6.0';
+  _.VERSION = '1.5.2';
 
   // Collection Functions
   // --------------------
@@ -74,7 +74,7 @@
   // Handles objects with the built-in `forEach`, arrays, and raw objects.
   // Delegates to **ECMAScript 5**'s native `forEach` if available.
   var each = _.each = _.forEach = function(obj, iterator, context) {
-    if (obj == null) return obj;
+    if (obj == null) return;
     if (nativeForEach && obj.forEach === nativeForEach) {
       obj.forEach(iterator, context);
     } else if (obj.length === +obj.length) {
@@ -87,7 +87,6 @@
         if (iterator.call(context, obj[keys[i]], keys[i], obj) === breaker) return;
       }
     }
-    return obj;
   };
 
   // Return the results of applying the iterator to each element.
   };
 
   // Return the first value which passes a truth test. Aliased as `detect`.
-  _.find = _.detect = function(obj, predicate, context) {
+  _.find = _.detect = function(obj, iterator, context) {
     var result;
     any(obj, function(value, index, list) {
-      if (predicate.call(context, value, index, list)) {
+      if (iterator.call(context, value, index, list)) {
         result = value;
         return true;
       }
   // Return all the elements that pass a truth test.
   // Delegates to **ECMAScript 5**'s native `filter` if available.
   // Aliased as `select`.
-  _.filter = _.select = function(obj, predicate, context) {
+  _.filter = _.select = function(obj, iterator, context) {
     var results = [];
     if (obj == null) return results;
-    if (nativeFilter && obj.filter === nativeFilter) return obj.filter(predicate, context);
+    if (nativeFilter && obj.filter === nativeFilter) return obj.filter(iterator, context);
     each(obj, function(value, index, list) {
-      if (predicate.call(context, value, index, list)) results.push(value);
+      if (iterator.call(context, value, index, list)) results.push(value);
     });
     return results;
   };
 
   // Return all the elements for which a truth test fails.
-  _.reject = function(obj, predicate, context) {
+  _.reject = function(obj, iterator, context) {
     return _.filter(obj, function(value, index, list) {
-      return !predicate.call(context, value, index, list);
+      return !iterator.call(context, value, index, list);
     }, context);
   };
 
   // Determine whether all of the elements match a truth test.
   // Delegates to **ECMAScript 5**'s native `every` if available.
   // Aliased as `all`.
-  _.every = _.all = function(obj, predicate, context) {
-    predicate || (predicate = _.identity);
+  _.every = _.all = function(obj, iterator, context) {
+    iterator || (iterator = _.identity);
     var result = true;
     if (obj == null) return result;
-    if (nativeEvery && obj.every === nativeEvery) return obj.every(predicate, context);
+    if (nativeEvery && obj.every === nativeEvery) return obj.every(iterator, context);
     each(obj, function(value, index, list) {
-      if (!(result = result && predicate.call(context, value, index, list))) return breaker;
+      if (!(result = result && iterator.call(context, value, index, list))) return breaker;
     });
     return !!result;
   };
   // Determine if at least one element in the object matches a truth test.
   // Delegates to **ECMAScript 5**'s native `some` if available.
   // Aliased as `any`.
-  var any = _.some = _.any = function(obj, predicate, context) {
-    predicate || (predicate = _.identity);
+  var any = _.some = _.any = function(obj, iterator, context) {
+    iterator || (iterator = _.identity);
     var result = false;
     if (obj == null) return result;
-    if (nativeSome && obj.some === nativeSome) return obj.some(predicate, context);
+    if (nativeSome && obj.some === nativeSome) return obj.some(iterator, context);
     each(obj, function(value, index, list) {
-      if (result || (result = predicate.call(context, value, index, list))) return breaker;
+      if (result || (result = iterator.call(context, value, index, list))) return breaker;
     });
     return !!result;
   };
 
   // Convenience version of a common use case of `map`: fetching a property.
   _.pluck = function(obj, key) {
-    return _.map(obj, _.property(key));
+    return _.map(obj, function(value){ return value[key]; });
   };
 
   // Convenience version of a common use case of `filter`: selecting only objects
   // containing specific `key:value` pairs.
-  _.where = function(obj, attrs) {
-    return _.filter(obj, _.matches(attrs));
+  _.where = function(obj, attrs, first) {
+    if (_.isEmpty(attrs)) return first ? void 0 : [];
+    return _[first ? 'find' : 'filter'](obj, function(value) {
+      for (var key in attrs) {
+        if (attrs[key] !== value[key]) return false;
+      }
+      return true;
+    });
   };
 
   // Convenience version of a common use case of `find`: getting the first object
   // containing specific `key:value` pairs.
   _.findWhere = function(obj, attrs) {
-    return _.find(obj, _.matches(attrs));
+    return _.where(obj, attrs, true);
   };
 
   // Return the maximum element or (element-based computation).
     if (!iterator && _.isArray(obj) && obj[0] === +obj[0] && obj.length < 65535) {
       return Math.max.apply(Math, obj);
     }
-    var result = -Infinity, lastComputed = -Infinity;
+    if (!iterator && _.isEmpty(obj)) return -Infinity;
+    var result = {computed : -Infinity, value: -Infinity};
     each(obj, function(value, index, list) {
       var computed = iterator ? iterator.call(context, value, index, list) : value;
-      if (computed > lastComputed) {
-        result = value;
-        lastComputed = computed;
-      }
+      computed > result.computed && (result = {value : value, computed : computed});
     });
-    return result;
+    return result.value;
   };
 
   // Return the minimum element (or element-based computation).
     if (!iterator && _.isArray(obj) && obj[0] === +obj[0] && obj.length < 65535) {
       return Math.min.apply(Math, obj);
     }
-    var result = Infinity, lastComputed = Infinity;
+    if (!iterator && _.isEmpty(obj)) return Infinity;
+    var result = {computed : Infinity, value: Infinity};
     each(obj, function(value, index, list) {
       var computed = iterator ? iterator.call(context, value, index, list) : value;
-      if (computed < lastComputed) {
-        result = value;
-        lastComputed = computed;
-      }
+      computed < result.computed && (result = {value : value, computed : computed});
     });
-    return result;
+    return result.value;
   };
 
-  // Shuffle an array, using the modern version of the
+  // Shuffle an array, using the modern version of the 
   // [Fisher-Yates shuffle](http://en.wikipedia.org/wiki/Fisher–Yates_shuffle).
   _.shuffle = function(obj) {
     var rand;
     return shuffled;
   };
 
-  // Sample **n** random values from a collection.
-  // If **n** is not specified, returns a single random element.
+  // Sample **n** random values from an array.
+  // If **n** is not specified, returns a single random element from the array.
   // The internal `guard` argument allows it to work with `map`.
   _.sample = function(obj, n, guard) {
-    if (n == null || guard) {
-      if (obj.length !== +obj.length) obj = _.values(obj);
+    if (arguments.length < 2 || guard) {
       return obj[_.random(obj.length - 1)];
     }
     return _.shuffle(obj).slice(0, Math.max(0, n));
 
   // An internal function to generate lookup iterators.
   var lookupIterator = function(value) {
-    if (value == null) return _.identity;
-    if (_.isFunction(value)) return value;
-    return _.property(value);
+    return _.isFunction(value) ? value : function(obj){ return obj[value]; };
   };
 
   // Sort the object's values by a criterion produced by an iterator.
-  _.sortBy = function(obj, iterator, context) {
-    iterator = lookupIterator(iterator);
+  _.sortBy = function(obj, value, context) {
+    var iterator = lookupIterator(value);
     return _.pluck(_.map(obj, function(value, index, list) {
       return {
         value: value,
 
   // An internal function used for aggregate "group by" operations.
   var group = function(behavior) {
-    return function(obj, iterator, context) {
+    return function(obj, value, context) {
       var result = {};
-      iterator = lookupIterator(iterator);
+      var iterator = value == null ? _.identity : lookupIterator(value);
       each(obj, function(value, index) {
         var key = iterator.call(context, value, index, obj);
         behavior(result, key, value);
   // Groups the object's values by a criterion. Pass either a string attribute
   // to group by, or a function that returns the criterion.
   _.groupBy = group(function(result, key, value) {
-    _.has(result, key) ? result[key].push(value) : result[key] = [value];
+    (_.has(result, key) ? result[key] : (result[key] = [])).push(value);
   });
 
   // Indexes the object's values by a criterion, similar to `groupBy`, but for
   // Use a comparator function to figure out the smallest index at which
   // an object should be inserted so as to maintain order. Uses binary search.
   _.sortedIndex = function(array, obj, iterator, context) {
-    iterator = lookupIterator(iterator);
+    iterator = iterator == null ? _.identity : lookupIterator(iterator);
     var value = iterator.call(context, obj);
     var low = 0, high = array.length;
     while (low < high) {
   // allows it to work with `_.map`.
   _.first = _.head = _.take = function(array, n, guard) {
     if (array == null) return void 0;
-    if ((n == null) || guard) return array[0];
-    if (n < 0) return [];
-    return slice.call(array, 0, n);
+    return (n == null) || guard ? array[0] : slice.call(array, 0, n);
   };
 
   // Returns everything but the last entry of the array. Especially useful on
   // values in the array. The **guard** check allows it to work with `_.map`.
   _.last = function(array, n, guard) {
     if (array == null) return void 0;
-    if ((n == null) || guard) return array[array.length - 1];
-    return slice.call(array, Math.max(array.length - n, 0));
+    if ((n == null) || guard) {
+      return array[array.length - 1];
+    } else {
+      return slice.call(array, Math.max(array.length - n, 0));
+    }
   };
 
   // Returns everything but the first entry of the array. Aliased as `tail` and `drop`.
     return _.difference(array, slice.call(arguments, 1));
   };
 
-  // Split an array into two arrays: one whose elements all satisfy the given
-  // predicate, and one whose elements all do not satisfy the predicate.
-  _.partition = function(array, predicate, context) {
-    predicate = lookupIterator(predicate);
-    var pass = [], fail = [];
-    each(array, function(elem) {
-      (predicate.call(context, elem) ? pass : fail).push(elem);
-    });
-    return [pass, fail];
-  };
-
   // Produce a duplicate-free version of the array. If the array has already
   // been sorted, you have the option of using a faster algorithm.
   // Aliased as `unique`.
     var rest = slice.call(arguments, 1);
     return _.filter(_.uniq(array), function(item) {
       return _.every(rest, function(other) {
-        return _.contains(other, item);
+        return _.indexOf(other, item) >= 0;
       });
     });
   };
   // Zip together multiple lists into a single array -- elements that share
   // an index go together.
   _.zip = function() {
-    var length = _.max(_.pluck(arguments, 'length').concat(0));
+    var length = _.max(_.pluck(arguments, "length").concat(0));
     var results = new Array(length);
     for (var i = 0; i < length; i++) {
       results[i] = _.pluck(arguments, '' + i);
   };
 
   // Partially apply a function by creating a version that has had some of its
-  // arguments pre-filled, without changing its dynamic `this` context. _ acts
-  // as a placeholder, allowing any combination of arguments to be pre-filled.
+  // arguments pre-filled, without changing its dynamic `this` context.
   _.partial = function(func) {
-    var boundArgs = slice.call(arguments, 1);
+    var args = slice.call(arguments, 1);
     return function() {
-      var position = 0;
-      var args = boundArgs.slice();
-      for (var i = 0, length = args.length; i < length; i++) {
-        if (args[i] === _) args[i] = arguments[position++];
-      }
-      while (position < arguments.length) args.push(arguments[position++]);
-      return func.apply(this, args);
+      return func.apply(this, args.concat(slice.call(arguments)));
     };
   };
 
-  // Bind a number of an object's methods to that object. Remaining arguments
-  // are the method names to be bound. Useful for ensuring that all callbacks
-  // defined on an object belong to it.
+  // Bind all of an object's methods to that object. Useful for ensuring that
+  // all callbacks defined on an object belong to it.
   _.bindAll = function(obj) {
     var funcs = slice.call(arguments, 1);
-    if (funcs.length === 0) throw new Error('bindAll must be passed function names');
+    if (funcs.length === 0) throw new Error("bindAll must be passed function names");
     each(funcs, function(f) { obj[f] = _.bind(obj[f], obj); });
     return obj;
   };
     var previous = 0;
     options || (options = {});
     var later = function() {
-      previous = options.leading === false ? 0 : _.now();
+      previous = options.leading === false ? 0 : new Date;
       timeout = null;
       result = func.apply(context, args);
-      context = args = null;
     };
     return function() {
-      var now = _.now();
+      var now = new Date;
       if (!previous && options.leading === false) previous = now;
       var remaining = wait - (now - previous);
       context = this;
         timeout = null;
         previous = now;
         result = func.apply(context, args);
-        context = args = null;
       } else if (!timeout && options.trailing !== false) {
         timeout = setTimeout(later, remaining);
       }
   // leading edge, instead of the trailing.
   _.debounce = function(func, wait, immediate) {
     var timeout, args, context, timestamp, result;
-
-    var later = function() {
-      var last = _.now() - timestamp;
-      if (last < wait) {
-        timeout = setTimeout(later, wait - last);
-      } else {
-        timeout = null;
-        if (!immediate) {
-          result = func.apply(context, args);
-          context = args = null;
-        }
-      }
-    };
-
     return function() {
       context = this;
       args = arguments;
-      timestamp = _.now();
+      timestamp = new Date();
+      var later = function() {
+        var last = (new Date()) - timestamp;
+        if (last < wait) {
+          timeout = setTimeout(later, wait - last);
+        } else {
+          timeout = null;
+          if (!immediate) result = func.apply(context, args);
+        }
+      };
       var callNow = immediate && !timeout;
       if (!timeout) {
         timeout = setTimeout(later, wait);
       }
-      if (callNow) {
-        result = func.apply(context, args);
-        context = args = null;
-      }
-
+      if (callNow) result = func.apply(context, args);
       return result;
     };
   };
   // allowing you to adjust arguments, run code before and after, and
   // conditionally execute the original function.
   _.wrap = function(func, wrapper) {
-    return _.partial(wrapper, func);
+    return function() {
+      var args = [func];
+      push.apply(args, arguments);
+      return wrapper.apply(this, args);
+    };
   };
 
   // Returns a function that is the composition of a list of functions, each
 
   // Retrieve the names of an object's properties.
   // Delegates to **ECMAScript 5**'s native `Object.keys`
-  _.keys = function(obj) {
-    if (!_.isObject(obj)) return [];
-    if (nativeKeys) return nativeKeys(obj);
+  _.keys = nativeKeys || function(obj) {
+    if (obj !== Object(obj)) throw new TypeError('Invalid object');
     var keys = [];
     for (var key in obj) if (_.has(obj, key)) keys.push(key);
     return keys;
     // from different frames are.
     var aCtor = a.constructor, bCtor = b.constructor;
     if (aCtor !== bCtor && !(_.isFunction(aCtor) && (aCtor instanceof aCtor) &&
-                             _.isFunction(bCtor) && (bCtor instanceof bCtor))
-                        && ('constructor' in a && 'constructor' in b)) {
+                             _.isFunction(bCtor) && (bCtor instanceof bCtor))) {
       return false;
     }
     // Add the first object to the stack of traversed objects.
     return value;
   };
 
-  _.constant = function(value) {
-    return function () {
-      return value;
-    };
-  };
-
-  _.property = function(key) {
-    return function(obj) {
-      return obj[key];
-    };
-  };
-
-  // Returns a predicate for checking whether an object has a given set of `key:value` pairs.
-  _.matches = function(attrs) {
-    return function(obj) {
-      if (obj === attrs) return true; //avoid comparing an object to itself.
-      for (var key in attrs) {
-        if (attrs[key] !== obj[key])
-          return false;
-      }
-      return true;
-    }
-  };
-
   // Run a function **n** times.
   _.times = function(n, iterator, context) {
     var accum = Array(Math.max(0, n));
     return min + Math.floor(Math.random() * (max - min + 1));
   };
 
-  // A (possibly faster) way to get the current timestamp as an integer.
-  _.now = Date.now || function() { return new Date().getTime(); };
-
   // List of HTML entities for escaping.
   var entityMap = {
     escape: {
 
   });
 
-  // AMD registration happens at the end for compatibility with AMD loaders
-  // that may not enforce next-turn semantics on modules. Even though general
-  // practice for AMD registration is to be anonymous, underscore registers
-  // as a named module because, like jQuery, it is a base library that is
-  // popular enough to be bundled in a third party lib, but not be part of
-  // an AMD load request. Those cases could generate an error when an
-  // anonymous define() is called outside of a loader request.
-  if (typeof define === 'function' && define.amd) {
-    define('underscore', [], function() {
-      return _;
-    });
-  }
 }).call(this);
index ba88946..f4f1f6d 100644 (file)
@@ -1,5 +1,2 @@
-all: *.css
-%.css: %.sass
-       sass -t expanded --compass --unix-newlines $< $@
-watch:
-       sass -t expanded --compass --unix-newlines --watch .:.
+sass:
+       sass -t expanded --compass --unix-newlines --watch base.sass:base.css&
\ No newline at end of file
index 6a20442..6b568f8 100644 (file)
@@ -1,4 +1,4 @@
-@charset "utf-8";
+@charset "UTF-8";
 @font-face {
   font-family: "mnmliconsRegular";
   src: url("/web/static/src/font/mnmliconsv21-webfont.eot") format("eot");
 .openerp td {
   vertical-align: top;
 }
-.openerp .oe_title {
-  width: 50%;
-  float: left;
-}
-.openerp .oe_title:after {
-  content: ".";
-  display: block;
-  height: 0;
-  clear: both;
-  visibility: hidden;
-}
-.openerp .oe_form_group {
-  clear: both;
-}
 .openerp .zebra tbody tr:nth-child(odd) td {
   background-color: #f0f0fa;
   background-color: #efeff8;
 .openerp .oe_about .oe_bottom a {
   color: #eeeeee;
 }
-.openerp a.oe_form_uri:hover {
+.openerp .oe_form_uri {
+  color: #7c7bad;
+}
+.openerp .oe_form_uri:hover {
   text-decoration: underline;
 }
 .openerp .oe_application {
   border-radius: 0 3px 3px 0;
 }
 .openerp .oe_searchview .oe_searchview_facets .oe_searchview_facet .oe_facet_category, .openerp .oe_searchview .oe_searchview_facets .oe_searchview_facet .oe_facet_value {
+  height: 18px;
   padding: 0 4px;
 }
 .openerp .oe_searchview .oe_searchview_facets .oe_searchview_facet .oe_facet_category {
 }
 .openerp .oe_form > :not(.oe_form_nosheet) header .oe_button {
   margin: 3px 2px 1px;
+  float: left;
 }
 .openerp .oe_form > :not(.oe_form_nosheet) header .oe_button:first-child {
   margin-left: 6px;
 }
 .openerp .oe_form .oe_form_label_help[for] span, .openerp .oe_form .oe_form_label[for] span {
   font-size: 80%;
-  color: darkgreen;
+  color: darkGreen;
   vertical-align: top;
   position: relative;
   top: -4px;
 }
 .openerp .oe_form .oe_form_embedded_html {
   position: relative;
-  width: 100%;
-  margin: auto;
-  overflow: auto;
+  width: 600px;
+  margin-left: 130px;
+  margin-top: 32px;
+  margin-bottom: 32px;
   text-align: justify;
 }
 .openerp .oe_form .oe_form_field_html .oe_input_icon {
   font-size: 95%;
   line-height: 1.2em;
 }
+.openerp .oe_debug_view_log label {
+  display: block;
+  width: 49%;
+  text-align: right;
+  float: left;
+  font-weight: bold;
+  color: #000099;
+}
+.openerp .oe_debug_view_log span {
+  display: block;
+  width: 49%;
+  float: right;
+  color: #333333;
+}
 .openerp .navbar {
   min-height: 32px;
   margin-bottom: 0px;
   border: none;
   z-index: 1;
-  position: static;
   background-color: #414141;
   background-color: #454343;
   background-image: -webkit-gradient(linear, left top, left bottom, from(#646060), to(#262626));
   border: none;
   padding: 10px 0 3px 0;
 }
+.openerp .jqstooltip {
+  height: auto !important;
+  width: auto !important;
+}
 .openerp h5 {
   font-weight: bold;
   font-size: smaller;
   margin: 3px 3px 0 !important;
 }
 
-.jqstooltip {
-  height: auto !important;
-  width: auto !important;
-  padding: 0;
-}
-
 @-moz-document url-prefix() {
   .openerp .oe_searchview .oe_searchview_search {
     top: -1px;
index 38a47ee..5bb2bb9 100644 (file)
@@ -189,17 +189,6 @@ $sheet-padding: 16px
         vertical-align: middle
     td
         vertical-align: top
-    .oe_title
-        width: 50%
-        float: left    
-    .oe_title:after
-        content: "."
-        display: block
-        height: 0
-        clear: both
-        visibility: hidden    
-    .oe_form_group
-        clear: both
     .zebra tbody tr:nth-child(odd) td
         background-color: #f0f0fa
         @include vertical-gradient(#f0f0fa, #eeeef6)
@@ -1013,8 +1002,10 @@ $sheet-padding: 16px
                 color: #eee
     // }}}
     // ActionManager {{{
-    a.oe_form_uri:hover
-        text-decoration: underline
+    .oe_form_uri
+        color: $link-color
+        &:hover
+            text-decoration: underline
     .oe_application
         width: 100%
         height: 100%
@@ -1311,6 +1302,7 @@ $sheet-padding: 16px
                     background: $tag-bg-light
                     @include radius(0 3px 3px 0)
                 .oe_facet_category, .oe_facet_value
+                    height: 18px
                     padding: 0 4px
                 .oe_facet_category
                     color: white
@@ -1647,6 +1639,7 @@ $sheet-padding: 16px
             float: right
         .oe_button
             margin: 3px 2px 1px
+            float: left
             &:first-child
                 margin-left: 6px
 
@@ -1893,9 +1886,10 @@ $sheet-padding: 16px
                 overflow: hidden
         .oe_form_embedded_html
             position: relative
-            width: 100%
-            margin: auto
-            overflow: auto            
+            width: 600px
+            margin-left: 130px
+            margin-top: 32px
+            margin-bottom: 32px
             text-align: justify
         .oe_form_field_html .oe_input_icon
             float: right
@@ -2425,6 +2419,18 @@ $sheet-padding: 16px
     .oe_debug_view_log
         font-size: 95%
         line-height: 1.2em
+    .oe_debug_view_log label
+        display: block
+        width: 49%
+        text-align: right
+        float: left
+        font-weight: bold
+        color: #009
+    .oe_debug_view_log span
+        display: block
+        width: 49%
+        float: right
+        color: #333
     // }}}
     // Bootstrap HACKS {{{
     .navbar
@@ -2432,7 +2438,6 @@ $sheet-padding: 16px
         margin-bottom: 0px
         border: none
         z-index: 1
-        position: static
         background-color: #414141
         @include vertical-gradient(#646060, #262626)
     .navbar-default
@@ -2512,7 +2517,10 @@ $sheet-padding: 16px
         border: none
         padding: 10px 0 3px 0
 
-
+    // Customize for kanban tooltip
+    .jqstooltip
+        height: auto !important
+        width: auto !important
 
     // Customize for chatter
     h5
@@ -2523,12 +2531,7 @@ $sheet-padding: 16px
     .oe_msg_subtype_check
         margin: 3px 3px 0 !important
     // }}}
-// Customize for kanban tooltip
-.jqstooltip
-    height: auto !important
-    width: auto !important
-    padding: 0
-        
+
 @-moz-document url-prefix()
     .openerp
         .oe_searchview .oe_searchview_search
diff --git a/addons/web/static/src/img/throbber-large.gif b/addons/web/static/src/img/throbber-large.gif
deleted file mode 100644 (file)
index 453b272..0000000
Binary files a/addons/web/static/src/img/throbber-large.gif and /dev/null differ
index 8e5df84..afa761d 100644 (file)
@@ -513,7 +513,7 @@ instance.web.DatabaseManager = instance.web.Widget.extend({
         var fields = $(form).serializeArray();
         self.rpc("/web/database/create", {'fields': fields}).done(function(result) {
             if (result) {
-                instance.web.redirect('/web');
+                instance.web.redirect('/web')
             } else {
                 alert("Failed to create database");
             }
@@ -1336,16 +1336,10 @@ instance.web.WebClient = instance.web.Client.extend({
         var state = $.bbq.getState(true);
         if (_.isEmpty(state) || state.action == "login") {
             self.menu.has_been_loaded.done(function() {
-                new instance.web.Model("res.users").call("read", [self.session.uid, ["action_id"]]).done(function(data) {
-                    if(data.action_id) {
-                        self.action_manager.do_action(data.action_id[0]);
-                        self.menu.open_action(data.action_id[0]);
-                    } else {
-                        var first_menu_id = self.menu.$el.find("a:first").data("menu");
-                        if(first_menu_id)
-                            self.menu.menu_click(first_menu_id);
-                    }
-                });
+                var first_menu_id = self.menu.$el.find("a:first").data("menu");
+                if(first_menu_id) {
+                    self.menu.menu_click(first_menu_id);
+                }
             });
         } else {
             $(window).trigger('hashchange');
@@ -1489,6 +1483,24 @@ instance.web.embed = function (origin, dbname, login, key, action, options) {
     client.insertAfter(currentScript);
 };
 
+openerp.web.LoginForm = openerp.web.Widget.extend({
+    init: function ($form) {
+        this._super(/* no parent */);
+        this.setElement($form);
+        this.$el.on('submit', this.on_submit);
+        this.start();
+    },
+    start: function () {
+        if (location.hash) {
+            this.$el.attr('action', this.$el.attr('action') + location.hash);
+        }
+        return this._super();
+    },
+    on_submit: function () {
+        return true;
+    },
+});
+
 })();
 
 // vim:et fdc=0 fdl=0 foldnestmax=3 fdm=syntax:
index 517afa7..78e3001 100644 (file)
@@ -221,12 +221,11 @@ instance.web.QueryGroup = instance.web.Class.extend({
             {__context: {group_by: []}, __domain: []},
             read_group_group);
 
-        var raw_field = grouping_field && grouping_field.split(':')[0];
         var aggregates = {};
         _(fixed_group).each(function (value, key) {
             if (key.indexOf('__') === 0
-                    || key === raw_field
-                    || key === raw_field + '_count') {
+                    || key === grouping_field
+                    || key === grouping_field + '_count') {
                 return;
             }
             aggregates[key] = value || 0;
@@ -235,6 +234,7 @@ instance.web.QueryGroup = instance.web.Class.extend({
         this.model = new instance.web.Model(
             model, fixed_group.__context, fixed_group.__domain);
 
+        var raw_field = grouping_field && grouping_field.split(':')[0];
         var group_size = fixed_group[raw_field + '_count'] || fixed_group.__count || 0;
         var leaf_group = fixed_group.__context.group_by.length === 0;
 
@@ -448,29 +448,15 @@ instance.web.DataSet =  instance.web.Class.extend(instance.web.PropertiesMixin,
      * Read records.
      *
      * @param {Array} ids identifiers of the records to read
-     * @param {Array} [fields] fields to read and return, by default all fields are returned
-     * @param {Object} [options]
+     * @param {Array} fields fields to read and return, by default all fields are returned
      * @returns {$.Deferred}
      */
     read_ids: function (ids, fields, options) {
-        if (_.isEmpty(ids))
-            return $.Deferred().resolve([]);
-            
         options = options || {};
+        // TODO: reorder results to match ids list
         return this._model.call('read',
-                [ids, fields || false],
-                {context: this.get_context(options.context)})
-            .then(function (records) {
-                if (records.length <= 1) { return records; }
-                var indexes = {};
-                for (var i = 0; i < ids.length; i++) {
-                    indexes[ids[i]] = i;
-                }
-                records.sort(function (a, b) {
-                    return indexes[a.id] - indexes[b.id];
-                });
-                return records;
-        });
+            [ids, fields || false],
+            {context: this.get_context(options.context)});
     },
     /**
      * Read a slice of the records represented by this DataSet, based on its
@@ -886,8 +872,7 @@ instance.web.BufferedDataSet = instance.web.DataSetStatic.extend({
         });
         var return_records = function() {
             var records = _.map(ids, function(id) {
-                var c = _.find(self.cache, function(c) {return c.id === id;});
-                return _.isUndefined(c) ? c : _.extend({}, c.values, {"id": id});
+                return _.extend({}, _.detect(self.cache, function(c) {return c.id === id;}).values, {"id": id});
             });
             if (self.debug_mode) {
                 if (_.include(records, undefined)) {
@@ -915,10 +900,6 @@ instance.web.BufferedDataSet = instance.web.DataSetStatic.extend({
                             sign = -1;
                             field = field.slice(1);
                         }
-                        //m2o should be searched based on value[1] not based whole value(i.e. [id, value])
-                        if(_.isArray(a[field]) && a[field].length == 2 && _.isString(a[field][1])){
-                            return sign * compare(a[field][1], b[field][1]);
-                        }
                         return sign * compare(a[field], b[field]);
                     }, 0);
                 });
index 252a5a3..2725e18 100644 (file)
@@ -119,7 +119,6 @@ instance.web.DataExport = instance.web.Dialog.extend({
                 if (select_exp.val()) {
                     self.exports.unlink([parseInt(select_exp.val(), 10)]);
                     select_exp.remove();
-                    self.$el.find("#fields_list option").remove();
                     if (self.$el.find('#saved_export_list option').length <= 1) {
                         self.$el.find('#ExistsExportList').hide();
                     }
@@ -167,16 +166,18 @@ instance.web.DataExport = instance.web.Dialog.extend({
             export_fields: _(fields).map(function (field) {
                 return [0, 0, {name: field}];
             })
-        }).then(function (export_list_id) {
-            if (!export_list_id) {
+        }, function (export_list_id) {
+            if (!export_list_id.result) {
                 return;
             }
-            if (!self.$el.find("#saved_export_list").length || self.$el.find("#saved_export_list").is(":hidden")) {
+            self.$el.find("#saved_export_list").append(
+                    new Option(value, export_list_id.result));
+            if (self.$el.find("#saved_export_list").is(":hidden")) {
                 self.show_exports_list();
             }
-            self.$el.find("#saved_export_list").append( new Option(value, export_list_id) );
         });
         this.on_show_save_list();
+        this.$el.find("#fields_list option").remove();
     },
     on_click: function(id, record) {
         var self = this;
index 3c32dbe..2f6bbce 100644 (file)
@@ -205,7 +205,7 @@ instance.web.format_value = function (value, descriptor, value_if_empty) {
         case 'selection': case 'statusbar':
             // Each choice is [value, label]
             if(_.isArray(value)) {
-                 return value[1];
+                 value = value[0];
             }
             var result = _(descriptor.selection).detect(function (choice) {
                 return choice[0] === value;
index 7c04ad4..fa9bae9 100644 (file)
@@ -355,7 +355,7 @@ instance.web.SearchView = instance.web.Widget.extend(/** @lends instance.web.Sea
             }
         },
         'autocompleteopen': function () {
-            this.$el.autocomplete('widget').css('z-index', 9999);
+            this.$el.autocomplete('widget').css('z-index', 1004);
         },
     },
     /**
@@ -414,7 +414,7 @@ instance.web.SearchView = instance.web.Widget.extend(/** @lends instance.web.Sea
                 context: this.dataset.get_context(),
             });
 
-            this.alive($.when(load_view)).then(function (r) {
+            $.when(load_view).then(function (r) {
                 return self.search_view_loaded(r);
             }).fail(function () {
                 self.ready.reject.apply(null, arguments);
@@ -473,9 +473,12 @@ instance.web.SearchView = instance.web.Widget.extend(/** @lends instance.web.Sea
      * Sets up search view's view-wide auto-completion widget
      */
     setup_global_completion: function () {
+        var self = this;
+
         var autocomplete = this.$el.autocomplete({
             source: this.proxy('complete_global_search'),
             select: this.proxy('select_completion'),
+            search: function () { self.$el.autocomplete('close'); },
             focus: function (e) { e.preventDefault(); },
             html: true,
             autoFocus: true,
@@ -483,10 +486,6 @@ instance.web.SearchView = instance.web.Widget.extend(/** @lends instance.web.Sea
             delay: 250,
         }).data('autocomplete');
 
-        this.$el.on('input', function () {
-            this.$el.autocomplete('close');
-        }.bind(this));
-
         // MonkeyPatch autocomplete instance
         _.extend(autocomplete, {
             _renderItem: function (ul, item) {
@@ -677,11 +676,6 @@ instance.web.SearchView = instance.web.Widget.extend(/** @lends instance.web.Sea
      * @returns instance.web.search.Field
      */
     make_field: function (item, field, parent) {
-        // M2O combined with selection widget is pointless and broken in search views,
-        // but has been used in the past for unsupported hacks -> ignore it
-        if (field.type === "many2one" && item.attrs.widget === "selection"){
-            item.attrs.widget = undefined;
-        }
         var obj = instance.web.search.fields.get_any( [item.attrs.widget, field.type]);
         if(obj) {
             return new (obj) (item, field, parent || this);
index 1f1c718..f607b27 100644 (file)
@@ -15,37 +15,6 @@ openerp.testing = {};
         list_editable: ['list', 'form', 'data'],
     };
 
-    var initialized = [];
-    /**
-     * openerp.init is a broken-ass piece of shit, makes it impossible to
-     * progressively add modules, using it, retarded openerp_inited flag
-     * means the first tests being run get their dependencies loaded
-     * (basically just base and web), and for *every other module* the tests
-     * run without the dependencies being correctly loaded
-     */
-    function init(modules) {
-        if (!initialized.length) {
-            openerp.init(modules);
-            initialized = openerp._modules.slice();
-            return;
-        }
-        var to_initialize = _.difference(modules, initialized);
-        for (var i = 0; i < to_initialize.length; i++) {
-            var modname = to_initialize[i];
-            var fct = openerp[modname];
-            if (typeof fct === 'function') {
-                var module = openerp[modname] = {};
-                for(var k in fct) {
-                    if (!fct.hasOwnProperty(k)) { continue; }
-                    module[k] = fct[k];
-                }
-                fct(openerp, module)
-            }
-            initialized.push(modname);
-            openerp._modules.push(modname);
-        }
-    }
-
     testing.dependencies = window['oe_all_dependencies'] || [];
     testing.current_module = null;
     testing.templates = { };
@@ -196,6 +165,9 @@ openerp.testing = {};
         });
     };
 
+    var openerp_inited = false;
+
+    var db = window['oe_db_info'];
     testing.section = function (name, options, body) {
         if (_.isFunction(options)) {
             body = options;
@@ -234,10 +206,47 @@ openerp.testing = {};
             .push(env._oe.setup, env._oe.teardown)
             .push(options.setup, options.teardown);
         var opts = _.defaults({}, options, env._oe);
+        // FIXME: if this test is ignored, will still query
+        if (opts.rpc === 'rpc' && !db) {
+            QUnit.config.autostart = false;
+            db = {
+                source: null,
+                supadmin: null,
+                password: null
+            };
+            var $msg = $('<form style="margin: 0 1em 1em;">')
+                .append('<h3>A test needs to clone a database</h3>')
+                .append('<h4>Please provide the source clone information</h4>')
+                .append('     Source DB: ').append('<input name="source">').append('<br>')
+                .append('   DB Password: ').append('<input name="supadmin">').append('<br>')
+                .append('Admin Password: ').append('<input name="password">').append('<br>')
+                .append('<input type="submit" value="OK"/>')
+                .submit(function (e) {
+                    e.preventDefault();
+                    e.stopPropagation();
+                    db.source = $msg.find('input[name=source]').val();
+                    db.supadmin = $msg.find('input[name=supadmin]').val();
+                    db.password = $msg.find('input[name=password]').val();
+                    QUnit.start();
+                    $.unblockUI();
+                });
+            $.blockUI({
+                message: $msg,
+                css: {
+                    fontFamily: 'monospace',
+                    textAlign: 'left',
+                    whiteSpace: 'pre-wrap',
+                    cursor: 'default'
+                }
+            });
+        }
 
         QUnit.test(name, function () {
             var instance = openerp;
-            init(module_deps);
+            if (!openerp_inited) {
+                openerp.init(module_deps);
+                openerp_inited = true;
+            }
             instance.session = new instance.web.Session();
             instance.session.uid = 42;
             if (_.isNumber(opts.asserts)) {
@@ -267,6 +276,44 @@ openerp.testing = {};
                     instance.session.responses[spec] = handler;
                 };
                 break;
+            case 'rpc':
+                async = true;
+                (function () {
+                // Bunch of random base36 characters
+                var dbname = 'test_' + Math.random().toString(36).slice(2);
+                // Add db setup/teardown at the start of the stack
+                case_stack = case_stack.unshift(function (instance) {
+                    // FIXME hack: don't want the session to go through shitty loading process of everything
+                    instance.session.session_init = testing.noop;
+                    instance.session.load_modules = testing.noop;
+                    instance.session.session_bind();
+                    return instance.session.rpc('/web/database/duplicate', {
+                        fields: [
+                            {name: 'super_admin_pwd', value: db.supadmin},
+                            {name: 'db_original_name', value: db.source},
+                            {name: 'db_name', value: dbname}
+                        ]
+                    }).then(function (result) {
+                        if (result.error) {
+                            return $.Deferred().reject(result.error).promise();
+                        }
+                        return instance.session.session_authenticate(
+                            dbname, 'admin', db.password, true);
+                    });
+                }, function (instance) {
+                    return instance.session.rpc('/web/database/drop', {
+                            fields: [
+                                {name: 'drop_pwd', value: db.supadmin},
+                                {name: 'drop_db', value: dbname}
+                            ]
+                        }).then(function (result) {
+                        if (result.error) {
+                            return $.Deferred().reject(result.error).promise();
+                        }
+                        return result;
+                    });
+                });
+                })();
             }
 
             // Always execute tests asynchronously
index 3dc148b..4576e9d 100644 (file)
@@ -1030,9 +1030,8 @@ instance.web.FormView = instance.web.View.extend(instance.web.form.FieldManagerM
     open_defaults_dialog: function () {
         var self = this;
         var display = function (field, value) {
-            if (!value) { return value; }
             if (field instanceof instance.web.form.FieldSelection) {
-                return _(field.get('values')).find(function (option) {
+                return _(field.values).find(function (option) {
                     return option[0] === value;
                 })[1];
             } else if (field instanceof instance.web.form.FieldMany2One) {
@@ -2835,7 +2834,9 @@ instance.web.form.FieldSelection = instance.web.form.AbstractField.extend(instan
         var def;
         if (this.field.type === "many2one") {
             var model = new openerp.Model(openerp.session, this.field.relation);
-            def = model.call("name_search", ['', this.get("domain")], {"context": this.build_context()});
+            def = model.call("search", [this.get("domain")], {"context": this.build_context()}).then(function(record_ids) {
+                return model.call("name_get", [record_ids] , {"context": self.build_context()});
+            });
         } else {
             var values = _.reject(this.field.selection, function (v) { return v[0] === false && v[1] === ''; });
             def = $.when(values);
@@ -3090,7 +3091,7 @@ instance.web.form.CompletionFieldMixin = {
             // quick create
             var raw_result = _(data.result).map(function(x) {return x[1];});
             if (search_val.length > 0 && !_.include(raw_result, search_val) &&
-                ! (self.options && (self.options.no_create || self.options.no_quick_create))) {
+                ! (self.options && self.options.no_quick_create)) {
                 values.push({
                     label: _.str.sprintf(_t('Create "<strong>%s</strong>"'),
                         $('<span />').text(search_val).html()),
@@ -3101,15 +3102,13 @@ instance.web.form.CompletionFieldMixin = {
                 });
             }
             // create...
-            if (!(self.options && self.options.no_create)){
-                values.push({
-                    label: _t("Create and Edit..."),
-                    action: function() {
-                        self._search_create_popup("form", undefined, self._create_context(search_val));
-                    },
-                    classname: 'oe_m2o_dropdown_option'
-                });
-            }
+            values.push({
+                label: _t("Create and Edit..."),
+                action: function() {
+                    self._search_create_popup("form", undefined, self._create_context(search_val));
+                },
+                classname: 'oe_m2o_dropdown_option'
+            });
 
             return values;
         });
@@ -3125,8 +3124,7 @@ instance.web.form.CompletionFieldMixin = {
         if (self.options.quick_create === undefined || self.options.quick_create) {
             new instance.web.DataSet(this, this.field.relation, self.build_context())
                 .name_create(name).done(function(data) {
-                    if (!self.get('effective_readonly'))
-                        self.add_id(data[0]);
+                    self.add_id(data[0]);
                 }).fail(function(error, event) {
                     event.preventDefault();
                     slow_create();
@@ -5006,7 +5004,7 @@ instance.web.form.SelectCreatePopup = instance.web.form.AbstractFormPopup.extend
         this.searchview.on('search_data', self, function(domains, contexts, groupbys) {
             if (self.initial_ids) {
                 self.do_search(domains.concat([[["id", "in", self.initial_ids]], self.domain]),
-                    contexts.concat(self.context), groupbys);
+                    contexts, groupbys);
                 self.initial_ids = undefined;
             } else {
                 self.do_search(domains.concat([self.domain]), contexts.concat(self.context), groupbys);
@@ -5131,7 +5129,7 @@ instance.web.form.FieldReference = instance.web.form.AbstractField.extend(instan
             .on('blurred', null, function () {self.trigger('blurred');});
 
         this.m2o = new instance.web.form.FieldMany2One(fm, { attrs: {
-            name: 'Referenced Document',
+            name: 'm2o',
             modifiers: JSON.stringify({readonly: this.get('effective_readonly')}),
         }});
         this.m2o.on("change:value", this, this.data_changed);
index 7426c70..8e3923d 100644 (file)
@@ -408,9 +408,6 @@ instance.web.ListView = instance.web.View.extend( /** @lends instance.web.ListVi
         if (total) {
             var range_start = this.page * limit + 1;
             var range_stop = range_start - 1 + limit;
-            if (this.records.length) {
-                range_stop = range_start - 1 + this.records.length;
-            }
             if (range_stop > total) {
                 range_stop = total;
             }
@@ -605,17 +602,7 @@ instance.web.ListView = instance.web.View.extend( /** @lends instance.web.ListVi
             _(ids).each(function (id) {
                 self.records.remove(self.records.get(id));
             });
-            if (self.records.length === 0 && self.dataset.size() > 0) {
-                //Trigger previous manually to navigate to previous page, 
-                //If all records are deleted on current page.
-                self.$pager.find('ul li:first a').trigger('click');
-            } else if (self.dataset.size() == self.limit()) {
-                //Reload listview to update current page with next page records 
-                //because pager going to be hidden if dataset.size == limit
-                self.reload();
-            } else {
-                self.configure_pager(self.dataset);
-            }
+            self.configure_pager(self.dataset);
             self.compute_aggregates();
         });
     },
@@ -1667,12 +1654,9 @@ instance.web.ListView.Groups = instance.web.Class.extend( /** @lends instance.we
 function synchronized(fn) {
     var fn_mutex = new $.Mutex();
     return function () {
-        var obj = this;
         var args = _.toArray(arguments);
-        return fn_mutex.exec(function () {
-            if (obj.isDestroyed()) { return $.when(); }
-            return fn.apply(obj, args)
-        });
+        args.unshift(this);
+        return fn_mutex.exec(fn.bind.apply(fn, args));
     };
 }
 var DataGroup =  instance.web.Class.extend({
index c9229c3..79a7555 100644 (file)
@@ -595,7 +595,6 @@ instance.web.ViewManager =  instance.web.Widget.extend({
                     action_views_ids : views_ids
                 }, self.flags, self.flags[view.view_type] || {}, view.options || {})
             });
-            
             views_ids[view.view_type] = view.view_id;
         });
         if (this.flags.views_switcher === false) {
@@ -603,11 +602,7 @@ instance.web.ViewManager =  instance.web.Widget.extend({
         }
         // If no default view defined, switch to the first one in sequence
         var default_view = this.flags.default_view || this.views_src[0].view_type;
-  
-
-        return this.switch_mode(default_view, null, this.flags[default_view] && this.flags[default_view].options);
-      
-        
+        return this.switch_mode(default_view);
     },
     switch_mode: function(view_type, no_store, view_options) {
         var self = this;
@@ -815,11 +810,6 @@ instance.web.ViewManager =  instance.web.Widget.extend({
             contexts: [action_context].concat(contexts || []),
             group_by_seq: groupbys || []
         }).done(function (results) {
-            if (results.error) {
-                throw new Error(
-                        _.str.sprintf(_t("Failed to evaluate search criterions")+": \n%s",
-                                      JSON.stringify(results.error)));
-            }
             self.dataset._model = new instance.web.Model(
                 self.dataset.model, results.context, results.domain);
             var groupby = results.group_by.length
@@ -1264,7 +1254,7 @@ instance.web.Sidebar = instance.web.Widget.extend({
         this.dataset = dataset;
         this.model_id = model_id;
         if (args && args[0].error) {
-            this.do_warn(_t('Uploading Error'), args[0].error);
+            this.do_warn( instance.web.qweb.render('message_error_uploading'), args[0].error);
         }
         if (!model_id) {
             this.on_attachments_loaded([]);
@@ -1348,7 +1338,7 @@ instance.web.View = instance.web.Widget.extend({
                 "context": this.dataset.get_context(),
             });
         }
-        return this.alive(view_loaded_def).then(function(r) {
+        return view_loaded_def.then(function(r) {
             self.fields_view = r;
             // add css classes that reflect the (absence of) access rights
             self.$el.addClass('oe_view')
index 7ba06b6..fc9c215 100644 (file)
                 </div>
                 <table align="center" class="db_option_table">
                     <tr>
-                        <td><label for="restore_pwd">Master Password:</label></td>
-                        <td><input type="password" name="restore_pwd" class="required" autofocus="autofocus"/></td>
+                        <td><label for="restore_db">File:</label></td>
+                        <td><input type="file" name="db_file" class="required" autofocus="autofocus"/></td>
                     </tr>
                     <tr>
-                        <td><label for="restore_db">File:</label></td>
-                        <td><input type="file" name="db_file" class="required"/></td>
+                        <td><label for="restore_pwd">Master Password:</label></td>
+                        <td><input type="password" name="restore_pwd" class="required"/></td>
                     </tr>
                     <tr>
                         <td><label for="new_db">New database name:</label></td>
                         <td><input type="text" name="new_db" class="required"/></td>
                     </tr>
-                    <tr>
-                        <td><label for="mode">Mode:</label></td>
-                        <td><select name="mode" class="required">
-                            <option value="restore">Backup Restore</option>
-                            <option value="copy">Copy of an existing database</option>
-                        </select></td>
-                    </tr>
                 </table>
             </form>
             <form id="db_change_password" name="change_pwd_form" style="display: none;">
 </t>
 <t t-name="ViewManagerDebugViewLog">
     <div class="oe_debug_view_log">
-        <table class="table table-condensed table-striped">
-            <tr>
-                <th>ID:</th>
-                <td><t t-esc="perm.id"/></td>
-            </tr>
-            <tr>
-                <th>XML ID:</th>
-                <td><t t-esc="perm.xmlid or '/'"/></td>
-            </tr>
-            <tr>
-                <th>Creation User:</th>
-                <td><t t-esc="format(perm.create_uid, { 'type' : 'many2one' }, '/')"/></td>
-            </tr>
-            <tr>
-                <th>Creation Date:</th>
-                <td><t t-esc="format(perm.create_date, { 'type' : 'datetime' }, '/')"/></td>
-            </tr>
-            <tr>
-                <th>Latest Modification by:</th>
-                <td><t t-esc="format(perm.write_uid, { 'type' : 'many2one' }, '/')"/></td>
-            </tr>
-            <tr>
-                <th>Latest Modification Date:</th>
-                <td><t t-esc="format(perm.write_date, { 'type' : 'datetime' }, '/')"/></td>
-            </tr>
-        </table>
+        <label>ID:</label>
+        <span><t t-esc="perm.id"/></span>
+
+        <label>XML ID:</label>
+        <span><t t-esc="perm.xmlid"/></span>
+
+        <label>Creation User:</label>
+        <span><t t-esc="format(perm.create_uid, { 'type' : 'many2one' }, '/')"/></span>
+
+        <label>Creation Date:</label>
+        <span><t t-esc="format(perm.create_date, { 'type' : 'datetime' }, '/')"/></span>
+
+        <label>Latest Modification by:</label>
+        <span><t t-esc="format(perm.write_uid, { 'type' : 'many2one' }, '/')"/></span>
+
+        <label>Latest Modification Date:</label>
+        <span><t t-esc="format(perm.write_date, { 'type' : 'datetime' }, '/')"/></span>
     </div>
 </t>
 <t t-name="ViewPager">
index 2228709..d7a957a 100644 (file)
@@ -1,32 +1,3 @@
-openerp.testing.section('data.dataset', {
-    rpc: 'mock',
-    dependencies: ['web.data'],
-}, function (test) {
-    test('read_ids', {asserts: 2}, function (instance, _, mock) {
-        var d = new instance.web.DataSet(null, 'foo');
-        mock('foo:read', function (args) {
-            var ids = args[0];
-            deepEqual(ids, [3, 1, 2]);
-            return [
-                {id: 1, a: 'bar'},
-                {id: 2, a: 'baz'},
-                {id: 3, a: 'foo'}
-            ];
-        });
-
-        return d.read_ids([3, 1, 2]).then(function (records) {
-            deepEqual(
-                records,
-                [
-                    {id: 3, a: 'foo'},
-                    {id: 1, a: 'bar'},
-                    {id: 2, a: 'baz'}
-                ]
-            )
-        });
-    })
-});
-
 openerp.testing.section('data.model.group_by', {
     rpc: 'mock',
     dependencies: ['web.data'],
diff --git a/addons/web/static/test/jsonrpc.js b/addons/web/static/test/jsonrpc.js
new file mode 100644 (file)
index 0000000..ef0c1fb
--- /dev/null
@@ -0,0 +1,212 @@
+(function() {
+
+var ropenerp = window.openerp;
+
+var openerp = ropenerp.declare($, _, QWeb2);
+
+ropenerp.testing.section('jsonrpc', {},
+function (test) {
+    test('basic-jsonrpc', {asserts: 1}, function () {
+        var session = new openerp.Session();
+        return session.rpc("/gen_session_id", {}).then(function(result) {
+            ok(result.length > 0, "Result returned by /gen_session_id");
+        });
+    });
+    test('basic-jsonprpc', {asserts: 1}, function () {
+        var session = new openerp.Session();
+        session.origin_server = false;
+        return session.rpc("/gen_session_id", {}).then(function(result) {
+            ok(result.length > 0, "Result returned by /gen_session_id");
+        });
+    });
+    // desactivated because the phantomjs runner crash
+    /*test('basic-jsonprpc2', {asserts: 1}, function () {
+        var session = new openerp.Session();
+        session.origin_server = false;
+        return session.rpc("/gen_session_id", {}, {force2step: true}).then(function(result) {
+            ok(result.length > 0, "Result returned by /gen_session_id");
+        });
+    });*/
+    test('session-jsonrpc', {asserts: 2}, function () {
+        var session = new openerp.Session();
+        var tmp = _.uniqueId("something");
+        return session.rpc("/web/tests/set_session_value", {value: tmp}).then(function() {
+            ok(true, "set_session returned");
+            return session.rpc("/web/tests/get_session_value", {});
+        }).then(function(result) {
+            equal(result, tmp, "Got the same value from the session");
+        });
+    });
+    test('session-jsonprpc', {asserts: 2}, function () {
+        var session = new openerp.Session();
+        session.origin_server = false;
+        var tmp = _.uniqueId("something");
+        return session.rpc("/web/tests/set_session_value", {value: tmp}).then(function() {
+            ok(true, "set_session returned");
+            return session.rpc("/web/tests/get_session_value", {});
+        }).then(function(result) {
+            equal(result, tmp, "Got the same value from the session");
+        });
+    });
+    // desactivated because the phantomjs runner crash
+    /*test('session-jsonprpc2', {asserts: 2}, function () {
+        var session = new openerp.Session();
+        session.origin_server = false;
+        var tmp = _.uniqueId("something");
+        return session.rpc("/web/tests/set_session_value", {value: tmp}, {force2step: true}).then(function() {
+            ok(true, "set_session returned");
+            return session.rpc("/web/tests/get_session_value", {}, {force2step: true});
+        }).then(function(result) {
+            equal(result, tmp, "Got the same value from the session");
+        });
+    });*/
+    test('overridesession-jsonrpc', {asserts: 4}, function () {
+        var origin_session = new openerp.Session();
+        var origin_tmp = _.uniqueId("something");
+        var session = new openerp.Session(null, null, {override_session: true});
+        var tmp = _.uniqueId("something_else");
+        return session.rpc("/web/tests/set_session_value", {value: tmp}).then(function() {
+            ok(true, "set_session returned");
+            return origin_session.rpc("/web/tests/set_session_value", {value: origin_tmp});
+        }).then(function(result) {
+            ok(true, "set_session on origin returned");
+            return session.rpc("/web/tests/get_session_value", {});
+        }).then(function(result) {
+            equal(result, tmp, "Got the same value from the session");
+            notEqual(result, origin_tmp, "Values in the different sessions should be different");
+        });
+    });
+    test('overridesession-jsonprpc', {asserts: 4}, function () {
+        var origin_session = new openerp.Session();
+        var origin_tmp = _.uniqueId("something");
+        var session = new openerp.Session(null, null, {override_session: true});
+        var tmp = _.uniqueId("something_else");
+        session.origin_server = false;
+        return session.rpc("/web/tests/set_session_value", {value: tmp}).then(function() {
+            ok(true, "set_session returned");
+            return origin_session.rpc("/web/tests/set_session_value", {value: origin_tmp});
+        }).then(function(result) {
+            ok(true, "set_session on origin returned");
+            return session.rpc("/web/tests/get_session_value", {});
+        }).then(function(result) {
+            equal(result, tmp, "Got the same value from the session");
+            notEqual(result, origin_tmp, "Values in the different sessions should be different");
+        });
+    });
+    // desactivated because the phantomjs runner crash
+    /*test('overridesession-jsonprpc2', {asserts: 4}, function () {
+        var origin_session = new openerp.Session();
+        var origin_tmp = _.uniqueId("something");
+        var session = new openerp.Session(null, null, {override_session: true});
+        var tmp = _.uniqueId("something_else");
+        session.origin_server = false;
+        return session.rpc("/web/tests/set_session_value", {value: tmp}, {force2step: true}).then(function() {
+            ok(true, "set_session returned");
+            return origin_session.rpc("/web/tests/set_session_value", {value: origin_tmp});
+        }).then(function(result) {
+            ok(true, "set_session on origin returned");
+            return session.rpc("/web/tests/get_session_value", {}, {force2step: true});
+        }).then(function(result) {
+            equal(result, tmp, "Got the same value from the session");
+            notEqual(result, origin_tmp, "Values in the different sessions should be different");
+        });
+    });*/
+    test('timeout-jsonrpc', {asserts: 1}, function () {
+        var session = new openerp.Session();
+        return session.rpc("/gen_session_id", {}, {timeout: 1}).then(function() {
+            ok(false, "the request incorrectly succeeded");
+            return $.when();
+        }, function(a, e) {
+            e.preventDefault();
+            ok(true, "the request correctly failed");
+            return $.when();
+        });
+    });
+    test('timeout-jsonprpc', {asserts: 1}, function () {
+        var session = new openerp.Session();
+        session.origin_server = false;
+        return session.rpc("/gen_session_id", {}, {timeout: 1}).then(function() {
+            ok(false, "the request incorrectly succeeded");
+            return $.when();
+        }, function(a, e) {
+            e.preventDefault();
+            ok(true, "the request correctly failed");
+            return $.when();
+        });
+    });
+    // desactivated because the phantomjs runner crash
+    /*test('timeout-jsonprpc2', {asserts: 1}, function () {
+        var session = new openerp.Session();
+        session.origin_server = false;
+        return session.rpc("/gen_session_id", {}, {force2step: true, timeout: 1}).then(function() {
+            ok(false, "the request incorrectly succeeded");
+            return $.when();
+        }, function(a, e) {
+            e.preventDefault();
+            ok(true, "the request correctly failed");
+            return $.when();
+        });
+    });*/
+});
+
+var login = "admin";
+var password = "admin";
+
+ropenerp.testing.section('jsonrpc-auth', {
+    rpc: "rpc",
+},
+function (test) {
+    return;
+    test('basic-auth', {asserts: 3}, function () {
+        var db = ropenerp.session.db;
+        var session = new openerp.Session(null, null, {override_session: true});
+        equal(session.uid, undefined, "uid is expected to be undefined");
+        return session.session_authenticate(db, login, password).then(function() {
+            equal(session.uid, 1, "Admin's uid must be 1");
+            return session.rpc("/web/dataset/call_kw", {
+                model: "res.users",
+                method: "read",
+                args: [1, ["login"]],
+                kwargs: {},
+            }).then(function(result) {
+                equal(result.login, "admin", "Admin's name must be 'admin'");
+            });
+        });
+    });
+    test('share-sessions', {asserts: 6}, function () {
+        var db = ropenerp.session.db;
+        var session = new openerp.Session(null, null, {override_session: true});
+        var session2;
+        return session.session_authenticate(db, login, password).then(function() {
+            equal(session.uid, 1, "Admin's uid must be 1");
+            session2 = new openerp.Session(null, null, {session_id: session.session_id});
+            equal(session2.uid, undefined, "uid should be undefined");
+            equal(session2.override_session, true, "overwrite_session should be true");
+            console.log("session_id", session.session_id);
+            return session2.session_reload();
+        }).then(function() {
+            equal(session2.uid, session.uid);
+            equal(session2.uid, 1);
+            return session2.rpc("/web/dataset/call_kw", {
+                model: "res.users",
+                method: "read",
+                args: [1, ["login"]],
+                kwargs: {},
+            }).then(function(result) {
+                equal(result.login, "admin", "Admin's name must be 'admin'");
+            });
+        });
+    });
+    test('models', {asserts: 2}, function () {
+        var db = ropenerp.session.db;
+        var session = new openerp.Session(null, null, {override_session: true});
+        return session.session_authenticate(db, login, password).then(function() {
+            return session.model("res.users").call("search_read", {fields: ["login"], domain: [["id", "=", 1]]});
+        }).then(function(result) {
+            equal(result.length, 1, "Must have one result");
+            equal(result[0].login, "admin", "Must have admin's login");
+        });
+    });
+});
+
+})();
index 54d2e18..0abd2f3 100644 (file)
@@ -59,7 +59,7 @@ class QUnitSuite(unittest.TestSuite):
                 'timeout': self.timeout,
                 'inject': os.path.join(ROOT, 'qunit-phantomjs-bridge.js')
             })
-        ], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
+        ], stdout=subprocess.PIPE)
 
         try:
             while True:
@@ -75,12 +75,7 @@ class QUnitSuite(unittest.TestSuite):
                 phantom.terminate()
 
     def process(self, line, result):
-        try:
-            args = json.loads(line)
-        except ValueError: # phantomjs stderr
-            if 'CoreText' not in line:
-                print line
-            return False
+        args = json.loads(line)
         event_name = args[0]
 
         if event_name == 'qunit.done':
@@ -113,8 +108,6 @@ class QUnitSuite(unittest.TestSuite):
             self._test.failed = True
             result.addFailure(
                 self._test, self.failure_to_str(*args[2:]))
-        elif event_name == 'console':
-            print args[1]
 
         return False
 
index 0bab1de..2228794 100644 (file)
@@ -1,24 +1,27 @@
-import urllib
 import urlparse
 from openerp import sql_db, tools
 from qunitsuite.suite import QUnitSuite
 
 class WebSuite(QUnitSuite):
-    def __init__(self, module):
+    def __init__(self):
         url = urlparse.urlunsplit([
             'http',
             'localhost:{port}'.format(port=tools.config['xmlrpc_port']),
             '/web/tests',
-            urllib.urlencode({
-                'mod': module,
-                'source': tools.config['db_name'],
-                'supadmin': tools.config['admin_passwd'],
-                'password': 'admin',
-            }),
+            'mod=*&source={db}&supadmin={supadmin}&password={password}'.format(
+                db=tools.config['db_name'],
+                # al: i dont understand why both are needed, db_password is the
+                # password for postgres and should not appear here of that i'm
+                # sure
+                #
+                # But runbot provides it with this wrong key so i let it here
+                # until it's fixed
+                supadmin=tools.config['db_password'] or 'admin',
+                password=tools.config['admin_passwd'] or 'admin'),
             ''
         ])
         super(WebSuite, self).__init__(url, 50000)
 
 def load_tests(loader, standard_tests, _):
-    standard_tests.addTest(WebSuite('web'))
+    standard_tests.addTest(WebSuite())
     return standard_tests
index 8164ddb..b8f7749 100644 (file)
                 {% endif %}
             </div>
 
+            <hr/>
             {% if debug %}
                 <input type="hidden" name="debug" value=""/>
             {% endif %}
-
-            <noscript>
-                <hr/>
-                <input type="submit" value="Continue" class="btn btn-primary pull-right"/>
-            </noscript>
+            <input type="submit" value="Continue" class="btn btn-primary pull-right"/>
 
             <div class="oe_single_form_footer">
                 <a class="oe_login_manage_db" href="/web/database/manager{% if debug %}?debug{% endif %}">Manage Databases</a> |
index 46bae5f..0e08f74 100644 (file)
 
         <template id="web.login_layout" name="Login Layout">
             <t t-call="web.layout">
-                <t t-set="head">
-                    <link href="/web/static/src/css/base.css" rel="stylesheet"/>
-                    <link href="/web/static/lib/bootstrap/css/bootstrap.css" rel="stylesheet"/>
-                </t>
                 <t t-set="body_classname" t-value="'oe_single_form'"/>
                 <div class="oe_single_form_container modal-content">
                     <div class="oe_single_form_logo">
                     </div>
                     <hr/>
                     <t t-raw="0"/>
-
-                    <div class="oe_single_form_footer" t-if="not disable_footer">
-                        <t t-if="not disable_database_manager">
-                            <a class="oe_login_manage_db" t-attf-href="/web/database/manager{{ '?debug' if debug else '' }}">Manage Databases</a>
-                            <span class="oe_footer_seperator"> | </span>
-                        </t>
-                        <a href="http://www.openerp.com" target="_blank">Powered by <span>OpenERP</span></a>
-                    </div>
                 </div>
             </t>
         </template>
 
         <template id="web.login" name="Login">
             <t t-call="web.login_layout">
-                <form class="oe_login_form" role="form" t-attf-action="/web/login{{ '?debug' if debug else '' }}" method="post" onsubmit="this.action = this.action + location.hash">
+                <t t-set="head">
+                    <t t-foreach="css" t-as="css_file">
+                        <link rel="stylesheet" t-att-href="css_file"/>
+                    </t>
+                    <t t-foreach="js" t-as="js_file">
+                        <script type="text/javascript" t-att-src="js_file"></script>
+                    </t>
+                    <script type="text/javascript">
+                        $(function() {
+                            var s = new openerp.init(<t t-raw="modules"/>);
+                            var login_form = new openerp.web.LoginForm($('.oe_login_form'));
+                        });
+                    </script>
+                </t>
+
+                <form class="oe_login_form" role="form" t-attf-action="/web/login{{ '?debug' if debug else '' }}" method="post">
 
                     <t t-call="web.database_select"/>
 
 
                     <div class="form-group field-password">
                         <label for="password" class="control-label">Password</label>
-                        <input type="password" name="password" id="password" class="form-control" required="required" t-att-autofocus="'autofocus' if login else None"/>
+                        <input type="password" name="password" id="password" class="form-control" required="required"/>
                     </div>
 
                     <p class="alert alert-danger" t-if="error">
                     </div>
 
                 </form>
+                <div class="oe_single_form_footer" t-if="not disable_footer">
+                    <t t-if="not disable_database_manager">
+                        <a class="oe_login_manage_db" t-attf-href="/web/database/manager{{ '?debug' if debug else '' }}">Manage Databases</a>
+                        <span class="oe_footer_seperator"> | </span>
+                    </t>
+                    <a href="http://www.openerp.com" target="_blank">Powered by <span>OpenERP</span></a>
+                </div>
+
             </t>
         </template>
 
index dbd949f..43ccd56 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:05+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_calendar
 #. openerp-web
index a058327..53519ff 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:05+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_calendar
 #. openerp-web
index 02793de..acf75d0 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:05+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_calendar
 #. openerp-web
index 5bf6a67..33fdb03 100644 (file)
@@ -9,13 +9,13 @@ msgstr ""
 "Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
 "POT-Creation-Date: 2012-12-21 17:06+0000\n"
 "PO-Revision-Date: 2014-01-30 17:05+0000\n"
-"Last-Translator: Boško Stojaković <bluesoft83@gmail.com>\n"
+"Last-Translator: Bosko Stojakovic <bluesoft83@gmail.com>\n"
 "Language-Team: Bosnian <bs@li.org>\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:05+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_calendar
 #. openerp-web
index 29f9791..2ef69ac 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:05+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_calendar
 #. openerp-web
index 9f36676..19b586b 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:05+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 "X-Poedit-Language: Czech\n"
 
 #. module: web_calendar
index e04e69b..9771ca6 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:05+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_calendar
 #. openerp-web
index fbb9223..3c64306 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:05+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_calendar
 #. openerp-web
index d4b8352..3910a35 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:05+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_calendar
 #. openerp-web
index d84dc0d..5d7ee46 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:05+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_calendar
 #. openerp-web
index c198423..6732754 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:05+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_calendar
 #. openerp-web
index 4de337d..f54e46c 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:05+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_calendar
 #. openerp-web
index b58a1d0..1e20c89 100644 (file)
@@ -15,8 +15,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:05+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 "Language: es\n"
 
 #. module: web_calendar
index 27f63fa..4c5f2ab 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:05+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_calendar
 #. openerp-web
index a3b553a..d21d419 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_calendar
 #. openerp-web
index 3f6c670..c382ee6 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_calendar
 #. openerp-web
index 485a424..21cb749 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_calendar
 #. openerp-web
index 56a8d1c..aededcf 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:05+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_calendar
 #. openerp-web
index 2675ee5..9d6dc1f 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:05+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_calendar
 #. openerp-web
index 11c084f..b85b9c5 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:05+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_calendar
 #. openerp-web
index 677cceb..6ce8929 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:05+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_calendar
 #. openerp-web
index ce99491..5f14925 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:05+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_calendar
 #. openerp-web
index 322832d..b09944f 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:05+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_calendar
 #. openerp-web
index fe6a1d1..785d5fe 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:05+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_calendar
 #. openerp-web
index 0a1109e..0194935 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:05+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_calendar
 #. openerp-web
index 386442f..8c8bb25 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:05+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_calendar
 #. openerp-web
index 59fcca8..50bdcd0 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:05+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_calendar
 #. openerp-web
index 277b8ff..a9a77b8 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:05+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_calendar
 #. openerp-web
index 01fd241..3beb16b 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:05+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_calendar
 #. openerp-web
index a020fa6..df5af71 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:05+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_calendar
 #. openerp-web
index d6b15de..245163a 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:05+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_calendar
 #. openerp-web
index bb13411..2016cf3 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:05+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_calendar
 #. openerp-web
index 17d8e63..7a73a43 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:05+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_calendar
 #. openerp-web
index 2a6ca23..4defcdb 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:05+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_calendar
 #. openerp-web
index 53972ab..efa0435 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:05+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_calendar
 #. openerp-web
index a2021e8..75bb676 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:05+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_calendar
 #. openerp-web
index fb362e3..c9a73a6 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:05+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_calendar
 #. openerp-web
index 6879208..73e3bf6 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:05+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_calendar
 #. openerp-web
index 05c8b9c..0b687aa 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:05+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_calendar
 #. openerp-web
index 5f559d1..2fce0f0 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:05+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_calendar
 #. openerp-web
index 69204d4..b33d42b 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:05+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_calendar
 #. openerp-web
index 7330717..5fffa8e 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:05+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_calendar
 #. openerp-web
index c008cd4..74b49d9 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:05+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_calendar
 #. openerp-web
index a883a55..21fb67f 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:05+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_calendar
 #. openerp-web
index 1c4bd9b..95e52e7 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:05+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_calendar
 #. openerp-web
index a46c726..8caa395 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:05+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_calendar
 #. openerp-web
index ad3e1dd..c9a4c5b 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_calendar
 #. openerp-web
index 2004988..d593b98 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:05+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_calendar
 #. openerp-web
index 5b011a4..baffdd6 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:05+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_calendar
 #. openerp-web
index fbbb944..4c00db6 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:05+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_calendar
 #. openerp-web
index 79710f7..00a2a6f 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:05+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_calendar
 #. openerp-web
index 461b5be..6f1ccd5 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:05+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_calendar
 #. openerp-web
index af27ad9..007fbc5 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:05+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_calendar
 #. openerp-web
index 4c5473a..b283f8b 100644 (file)
@@ -2,62 +2,44 @@
  * OpenERP web_calendar
  *---------------------------------------------------------*/
 
-_.str.toBoolElse = function (str, elseValues, trueValues, falseValues) {
-    var ret = _.str.toBool(str, trueValues, falseValues);
-    if (_.isUndefined(ret)) {
-        return elseValues;
-    }
-    return ret;
+_.str.toBoolElse = function(str, elseValues, trueValues, falseValues) {
+      var ret = _.str.toBool(str, trueValues, falseValues);
+      if (_.isUndefined(ret)) {
+        return elseValues
+      }
+      return ret
 };
 
 openerp.web_calendar = function(instance) {
 
     var _t = instance.web._t,
-        _lt = instance.web._lt,
-        QWeb = instance.web.qweb;
+        _lt = instance.web._lt;
+    var QWeb = instance.web.qweb;
 
     function get_class(name) {
         return new instance.web.Registry({'tmp' : name}).get_object("tmp");
     }
 
-    function get_fc_defaultOptions() {
-        shortTimeformat = Date.CultureInfo.formatPatterns.shortTime;
-        return {
-            weekNumberTitle: _t("W"),
-            allDayText: _t("All day"),
-            buttonText : {
-                today:    _t("Today"),
-                month:    _t("Month"),
-                week:     _t("Week"),
-                day:      _t("Day")
-            },
-            monthNames: Date.CultureInfo.monthNames,
-            monthNamesShort: Date.CultureInfo.abbreviatedMonthNames,
-            dayNames: Date.CultureInfo.dayNames,
-            dayNamesShort: Date.CultureInfo.abbreviatedDayNames,
-            firstDay: Date.CultureInfo.firstDayOfWeek,
-            weekNumbers: true,
-            axisFormat : shortTimeformat.replace(/:mm/,'(:mm)'),
-            timeFormat : {
-               // for agendaWeek and agendaDay               
-               agenda: shortTimeformat + '{ - ' + shortTimeformat + '}', // 5:00 - 6:30
-                // for all other views
-                '': shortTimeformat.replace(/:mm/,'(:mm)')  // 7pm
-            },
-            weekMode : 'liquid',
-            aspectRatio: 1.8,
-            snapMinutes: 15,
-        };
-    }
+    var fc_defaultOptions = {
+        monthNames: Date.CultureInfo.monthNames,
+        monthNamesShort: Date.CultureInfo.abbreviatedMonthNames,
+        dayNames: Date.CultureInfo.dayNames,
+        dayNamesShort: Date.CultureInfo.abbreviatedDayNames,
+
+        weekNumberTitle: _t("W"),
+        allDayText: _t("all-day"),
+
+        firstDay: Date.CultureInfo.firstDayOfWeek,
+    };
 
     function is_virtual_id(id) {
-        return typeof id === "string" && id.indexOf('-') >= 0;
+        return typeof id == "string" && id.indexOf('-') >= 0;
     }
 
     function isNullOrUndef(value) {
-        return _.isUndefined(value) || _.isNull(value);
+        return _.isUndefined(value) || _.isNull(value)
     }
-
+    
     instance.web.views.add('calendar', 'instance.web_calendar.CalendarView');
 
     instance.web_calendar.CalendarView = instance.web.View.extend({
@@ -78,27 +60,24 @@ openerp.web_calendar = function(instance) {
             this.range_start = null;
             this.range_stop = null;
             this.selected_filters = [];
+                        
         },
 
         set_default_options: function(options) {
             this._super(options);
             _.defaults(this.options, {
-                confirm_on_delete: true
+                confirm_on_delete: true,
             });
         },
 
         destroy: function() {
             this.$calendar.fullCalendar('destroy');
-            if (this.$small_calendar) {
-                this.$small_calendar.datepicker('destroy');
-            }
+            this.$small_calendar.datepicker('destroy');
             this._super.apply(this, arguments);
         },
 
         view_loading: function (fv) {
-            /* xml view calendar options */
-            var attrs = fv.arch.attrs,
-                self = this;
+            var self = this;
             this.fields_view = fv;
             this.$calendar = this.$el.find(".oe_calendar_widget");
 
@@ -117,6 +96,9 @@ openerp.web_calendar = function(instance) {
                 self.do_switch_view('form');
             });
 
+            /* xml view calendar options */
+            var attrs = fv.arch.attrs;
+
             if (!attrs.date_start) {
                 throw new Error(_t("Calendar view has not defined 'date_start' attribute."));
             }
@@ -130,47 +112,42 @@ openerp.web_calendar = function(instance) {
             this.date_start = attrs.date_start;     // Field name of starting date field
             this.date_delay = attrs.date_delay;     // duration
             this.date_stop = attrs.date_stop;
-            this.all_day = attrs.all_day;
+            this.all_day = attrs.all_day; 
+            this.attendee_people = attrs.attendee;  
             this.how_display_event = '';
-            this.attendee_people = attrs.attendee;
-
+           
             if (!isNullOrUndef(attrs.quick_create_instance)) {
-                self.quick_create_instance = 'instance.' + attrs.quick_create_instance;
+                self.quick_create_instance = 'instance.' + attrs.quick_create_instance;                
             }
-
+                
             //if quick_add = False, we don't allow quick_add
             //if quick_add = not specified in view, we use the default quick_create_instance
             //if quick_add = is NOT False and IS specified in view, we this one for quick_create_instance'   
-
-            this.quick_add_pop = (isNullOrUndef(attrs.quick_add) || _.str.toBoolElse(attrs.quick_add, true));
+            
+            this.quick_add_pop = (isNullOrUndef(attrs.quick_add) || _.str.toBoolElse(attrs.quick_add,true) );            
             if (this.quick_add_pop && !isNullOrUndef(attrs.quick_add)) {
-                self.quick_create_instance = 'instance.' + attrs.quick_add;
+                self.quick_create_instance = 'instance.' + attrs.quick_add;                
             }
             // The display format which will be used to display the event where fields are between "[" and "]"
             if (!isNullOrUndef(attrs.display)) {
                 this.how_display_event = attrs.display; // String with [FIELD]
             }
-
+            
             // If this field is set ot true, we don't open the event in form view, but in a popup with the view_id passed by this parameter
-            if (isNullOrUndef(attrs.event_open_popup) || !_.str.toBoolElse(attrs.event_open_popup, true)) {
-                this.open_popup_action = false;
-            } else {
+            if (isNullOrUndef(attrs.event_open_popup) || !_.str.toBoolElse(attrs.event_open_popup,true)) {
+                this.open_popup_action = false; 
+            }
+            else {
                 this.open_popup_action = attrs.event_open_popup;
             }
-            // If this field is set to true, we will use the calendar_friends model as filter and not the color field.
-            this.useContacts = (!isNullOrUndef(attrs.use_contacts) && _.str.toBool(attrs.use_contacts)) && (!isNullOrUndef(self.options.$sidebar));
+            
+            // If this field is set to true, we will use de calendar_friends model as filter and not the color field.
+            this.useContacts = (!isNullOrUndef(attrs.use_contacts) && _.str.toBool(attrs.use_contacts)); 
 
             // If this field is set ot true, we don't add itself as an attendee when we use attendee_people to add each attendee icon on an event
             // The color is the color of the attendee, so don't need to show again that it will be present
-            this.colorIsAttendee = (!(isNullOrUndef(attrs.color_is_attendee) || !_.str.toBoolElse(attrs.color_is_attendee, true))) && (!isNullOrUndef(self.options.$sidebar));
-
-            // if we have not sidebar, (eg: Dashboard), we don't use the filter "coworkers"
-            if (isNullOrUndef(self.options.$sidebar)) {
-                this.useContacts = false;
-                this.colorIsAttendee = false;
-                this.attendee_people = undefined;
-            }
-
+            this.colorIsAttendee = (!(isNullOrUndef(attrs.color_is_attendee) || !_.str.toBoolElse(attrs.color_is_attendee,true))); 
+                
 /*
             Will be more logic to do it in futur, but see below to stay Retro-compatible
             
@@ -187,36 +164,38 @@ openerp.web_calendar = function(instance) {
             }            
 */
             if (isNullOrUndef(attrs.avatar_model)) {
-                this.avatar_model = null;
-            } else {
+                this.avatar_model = null; 
+            }
+            else {
                 this.avatar_model = attrs.avatar_model;
             }
-
+           
             if (isNullOrUndef(attrs.avatar_title)) {
-                this.avatar_title = this.avatar_model;
-            } else {
+                this.avatar_title = this.avatar_model; 
+            }
+            else {
                 this.avatar_title = attrs.avatar_title;
             }
+                    
             this.color_field = attrs.color;
-
+        
             if (this.color_field && this.selected_filters.length === 0) {
                 var default_filter;
                 if ((default_filter = this.dataset.context['calendar_default_' + this.color_field])) {
                     this.selected_filters.push(default_filter + '');
                 }
             }
-
             this.fields = fv.fields;
 
             for (var fld = 0; fld < fv.arch.children.length; fld++) {
                 this.info_fields.push(fv.arch.children[fld].attrs.name);
             }
-
+            
             return (new instance.web.Model(this.dataset.model))
                 .call("check_access_rights", ["create", false])
                 .then(function (create_right) {
                     self.create_right = create_right;
-                    self.init_calendar().then(function() {
+                    self.init_calendar().then(function() {    
                         self.trigger('calendar_view_loaded', fv);
                         self.ready.resolve();
                     });
@@ -226,7 +205,7 @@ openerp.web_calendar = function(instance) {
         get_fc_init_options: function () {
             //Documentation here : http://arshaw.com/fullcalendar/docs/
             var self = this;
-            return  $.extend({}, get_fc_defaultOptions(), {
+            return $.extend({}, fc_defaultOptions, {
                 
                 defaultView: (this.mode == "month")?"month":
                     (this.mode == "week"?"agendaWeek":
@@ -252,15 +231,15 @@ openerp.web_calendar = function(instance) {
                     self.proxy('update_record')(event._id, data);
                 },
                 eventRender: function (event, element, view) {
-                    element.find('.fc-event-title').html(event.title);
+                    element.find('.fc-event-title').html(event.title);                    
                 },
-                eventAfterRender: function (event, element, view) {
+                eventAfterRender: function (event, element, view) {                    
                     if ((view.name !== 'month') && (((event.end-event.start)/60000)<=30)) {
                         //if duration is too small, we see the html code of img
                         var current_title = $(element.find('.fc-event-time')).text();
-                        var new_title = current_title.substr(0,current_title.indexOf("<img")>0?current_title.indexOf("<img"):current_title.length);
+                        var new_title = current_title.substr(0,current_title.indexOf("<img")>0?current_title.indexOf("<img"):current_title.length)
                         element.find('.fc-event-time').html(new_title);
-                    }
+                    }                    
                 },
                 eventClick: function (event) { self.open_event(event._id,event.title); },
                 select: function (start_date, end_date, all_day, _js_event, _view) {
@@ -269,13 +248,39 @@ openerp.web_calendar = function(instance) {
                         end: end_date,
                         allDay: all_day,
                     });
+
                     self.open_quick_create(data_template);
 
                 },
+                drop: function(start_date, all_day) {
+                    if (this.classList.contains("ui-dialog")) {
+                        return; //don't look click event on calendar if popup hover !
+                    }
+                    var data_template = self.get_event_data({
+                        start: start_date,
+                        allDay: all_day,
+                    });
+                    var stored_data = $(this).data('eventDefaults');
 
+                    data_template = $.extend({}, stored_data, data_template);
+                    self.open_quick_create(data_template);
+                },
                 unselectAuto: false,
 
+                // Options
 
+                weekNumbers: true,
+                snapMinutes: 15,
+                timeFormat : {
+                
+                           // for agendaWeek and agendaDay
+                            agenda: 'h:mm{ - h:mm}', // 5:00 - 6:30
+
+                            // for all other views
+                            '': 'h(:mm)tt'            // 7pm
+                        },
+                weekMode : 'liquid',
+                aspectRatio: 1.8,
             });
         },
 
@@ -289,56 +294,44 @@ openerp.web_calendar = function(instance) {
                         context.$calendar.fullCalendar('changeView','agendaDay');
                     }
                 }
-                else if (curView.name != "agendaDay" || (curView.name == "agendaDay" && curDate.compareTo(curView.start)===0)) {
+                else if (curView.name != "agendaDay" || (curView.name == "agendaDay" && curDate.compareTo(curView.start)==0)) {
                         context.$calendar.fullCalendar('changeView','agendaWeek');
                 }
                 context.$calendar.fullCalendar('gotoDate', obj.currentYear , obj.currentMonth, obj.currentDay);
-            };
+            }
         },
 
         init_calendar: function() {
             var self = this;
              
             if (!this.sidebar && this.options.$sidebar) {
-                translate = get_fc_defaultOptions();
                 this.sidebar = new instance.web_calendar.Sidebar(this);
                 this.sidebar.appendTo(this.$el.find('.oe_calendar_sidebar_container'));
 
                 this.$small_calendar = self.$el.find(".oe_calendar_mini");
-                this.$small_calendar.datepicker({ 
-                    onSelect: self.calendarMiniChanged(self),
-                    dayNamesMin : translate.dayNamesShort,
-                    monthNames: translate.monthNamesShort,
-                    firstDay: translate.firstDay,
-                });
-
+                this.$small_calendar.datepicker({ onSelect: self.calendarMiniChanged(self) });
             
                 if (this.useContacts) {
-                    //Get my Partner ID
-                    
                     new instance.web.Model("res.users").query(["partner_id"]).filter([["id", "=",this.dataset.context.uid]]).first()
                         .done(
-                            function(result) {
+                            function(result) { 
                                 var sidebar_items = {};
                                 var filter_value = result.partner_id[0];
                                 var filter_item = {
-                                    value: filter_value,
-                                    label: result.partner_id[1] + _lt(" [Me]"),
-                                    color: self.get_color(filter_value),
-                                    avatar_model: self.avatar_model,
-                                    is_checked: true
-                                };
-
+                                        value: filter_value,
+                                        label: result.partner_id[1] + _lt(" [Me]"),
+                                        color: self.get_color(filter_value),
+                                        avatar_model: self.avatar_model
+                                    };
                                 sidebar_items[filter_value] = filter_item ;
                                 filter_item = {
                                         value: -1,
-                                        label: _lt("Everybody's calendars"),
+                                        label: _lt("All calendars"),
                                         color: self.get_color(-1),
-                                        avatar_model: self.avatar_model,
-                                        is_checked: false
+                                        avatar_model: self.avatar_model
                                     };
                                 sidebar_items[-1] = filter_item ;
-                                //Get my coworkers/contacts
+
                                 new instance.web.Model("calendar.contacts").query(["partner_id"]).filter([["user_id", "=",self.dataset.context.uid]]).all().then(function(result) {
                                     _.each(result, function(item) {
                                         filter_value = item.partner_id[0];
@@ -346,28 +339,25 @@ openerp.web_calendar = function(instance) {
                                             value: filter_value,
                                             label: item.partner_id[1],
                                             color: self.get_color(filter_value),
-                                            avatar_model: self.avatar_model,
-                                            is_checked: true
+                                            avatar_model: self.avatar_model
                                         };
                                         sidebar_items[filter_value] = filter_item ;
                                     });
-
-                                    self.all_filters = sidebar_items;
-                                    self.now_filter_ids = $.map(self.all_filters, function(o) { return o.value; });
                                     
-                                    self.sidebar.filter.events_loaded(self.all_filters);
-                                    self.sidebar.filter.set_filters();
-                                                                        
+                                    self.allFilters = sidebar_items;
+                                    self.sidebar.filter.events_loaded(sidebar_items);
                                     self.sidebar.filter.addUpdateButton();
-                                }).done(function () {
-                                    self.$calendar.fullCalendar('refetchEvents');
+                                }).done(function () { 
+                                    self.$calendar.fullCalendar('refetchEvents');            
                                 });
                             }
-                         );
-                }
-                this.extraSideBar();                
+                         );               
+                };
+                this.extraSideBar();
+                
             }
             self.$calendar.fullCalendar(self.get_fc_init_options());
+
             
             return $.when();
         },
@@ -390,7 +380,7 @@ openerp.web_calendar = function(instance) {
                         delete this.quick;
                         this.$calendar.fullCalendar('unselect');
                     });
-            this.quick.replace(this.$el.find('.oe_calendar_qc_placeholder'));
+            this.quick.replace($(".oe_calendar_qc_placeholder"));
             this.quick.focus();
             
         },
@@ -496,19 +486,16 @@ openerp.web_calendar = function(instance) {
         event_data_transform: function(evt) {
             var self = this;
 
-            var date_delay = evt[this.date_delay] || 1.0,
+            var date_start = instance.web.auto_str_to_date(evt[this.date_start]),
+                date_stop = this.date_stop ? instance.web.auto_str_to_date(evt[this.date_stop]) : null,
+                date_delay = evt[this.date_delay] || 1.0,
                 all_day = this.all_day ? evt[this.all_day] : false,
                 res_computed_text = '',
                 the_title = '',
-                attendees = [];
+                attendees = [];                
 
-            if (!all_day) {
-                date_start = instance.web.auto_str_to_date(evt[this.date_start]);
-                date_stop = this.date_stop ? instance.web.auto_str_to_date(evt[this.date_stop]) : null;
-            }
-            else {
-                date_start = instance.web.auto_str_to_date(evt[this.date_start].split(' ')[0],'date');
-                date_stop = this.date_stop ? instance.web.auto_str_to_date(evt[this.date_stop].split(' ')[0],'date').addMinutes(-1) : null;
+            if (this.date_stop && this.fields[this.date_stop].type == 'date') {
+                date_stop.addDay(1);
             }
 
             if (this.info_fields) {
@@ -543,7 +530,7 @@ openerp.web_calendar = function(instance) {
                         temp_ret[fieldname] = value;
                     }
                     res_computed_text = res_computed_text.replace("["+fieldname+"]",temp_ret[fieldname]);
-                });
+                });                
 
                 
                 if (res_computed_text.length) {
@@ -551,8 +538,8 @@ openerp.web_calendar = function(instance) {
                 }
                 else {
                     var res_text= [];
-                    _.each(temp_ret, function(val,key) { res_text.push(val); });
-                    the_title = res_text.join(', ');
+                    _.each(temp_ret, function(val,key) { res_text.push(val)} );
+                    the_title = res_text.join(', ');                    
                 }
                 the_title = _.escape(the_title);
                 
@@ -564,59 +551,66 @@ openerp.web_calendar = function(instance) {
                     var attendee_showed = 0;
                     var attendee_other = '';
 
-                    _.each(temp_ret[this.attendee_people],
-                        function (the_attendee_people) {
+                    _.each(temp_ret[this.attendee_people], 
+                        function (the_attendee_people) { 
                             attendees.push(the_attendee_people);
                             attendee_showed += 1;
-                            if (attendee_showed<= MAX_ATTENDEES) {
-                                if (self.avatar_model !== null) {
-                                       the_title_avatar += '<img title="' + self.all_attendees[the_attendee_people] + '" class="attendee_head"  \
-                                                            src="/web/binary/image?model=' + self.avatar_model + '&field=image_small&id=' + the_attendee_people + '"></img>';
+                            if (attendee_showed<= MAX_ATTENDEES) {                            
+                                if (self.avatar_model != null) {
+                                       the_title_avatar += '<img title="' + self.all_attendees[the_attendee_people] + '" class="attendee_head" src="/web/binary/image?model=' + self.avatar_model + '&field=image_small&id=' + the_attendee_people + '"></img>';                                
                                 }
                                 else {
                                     if (!self.colorIsAttendee || the_attendee_people != temp_ret[self.color_field]) {
-                                            tempColor = (self.all_filters[the_attendee_people] !== undefined) 
-                                                        ? self.all_filters[the_attendee_people].color
-                                                        : self.all_filters[-1].color;
-                                        the_title_avatar += '<i class="fa fa-user attendee_head color_'+tempColor+'" title="' + self.all_attendees[the_attendee_people] + '" ></i>';
+                                            tempColor = (self.all_filters[the_attendee_people] != undefined) 
+                                                                ? self.all_filters[the_attendee_people].color
+                                                                : self.all_filters[-1].color;
+                                            
+                                        the_title_avatar += '<i class="fa fa-user attendee_head color_'+tempColor+'" title="' + self.all_attendees[the_attendee_people] + '" ></i>' 
                                     }//else don't add myself
                                 }
                             }
                             else {
                                 attendee_other += self.all_attendees[the_attendee_people] +", ";
-                            }
+                            }                                    
                         }
                     );
                     if (attendee_other.length>2) {
-                        the_title_avatar += '<span class="attendee_head" title="' + attendee_other.slice(0, -2) + '">+</span>';
+                        the_title_avatar += '<span class="attendee_head" title="' + attendee_other.slice(0, -2) + '">+</span>';                    
                     }
                     the_title = the_title_avatar + the_title;
-                }
+                }                
             }
             
             if (!date_stop && date_delay) {
                 date_stop = date_start.clone().addHours(date_delay);
             }
+            if (this.fields[this.date_start].type != "date" && all_day) {
+                date_stop.addDays(-1);
+            }
             var r = {
                 'start': date_start.toString('yyyy-MM-dd HH:mm:ss'),
                 'end': date_stop.toString('yyyy-MM-dd HH:mm:ss'),
-                'title': the_title,
+                'title': the_title, //res_text.join(', '),
                 'allDay': (this.fields[this.date_start].type == 'date' || (this.all_day && evt[this.all_day]) || false),
                 'id': evt.id,
                 'attendees':attendees
             };
-            if (!self.useContacts || self.all_filters[evt[this.color_field]] !== undefined) {
+            
+
+            if (!self.useContacts || self.all_filters[evt[this.color_field]] != undefined) {
                 if (this.color_field && evt[this.color_field]) {
                     var color_key = evt[this.color_field];
                     if (typeof color_key === "object") {
                         color_key = color_key[0];
                     }
-                    r.className = 'cal_opacity calendar_color_'+ this.get_color(color_key);
+                    r.className = 'cal_opacity calendar_color_'+ this.get_color(color_key);                                
                 }
             }
             else  { // if form all, get color -1
+
                   r.className = 'cal_opacity calendar_color_'+ self.all_filters[-1].color;
             }
+            
             return r;
         },
         
@@ -628,7 +622,8 @@ openerp.web_calendar = function(instance) {
             // Normalize event_end without changing fullcalendars event.
             var data = {
                 name: event.title
-            };            
+            };
+            
             
             var event_end = event.end;
             //Bug when we move an all_day event from week or day view, we don't have a dateend or duration...            
@@ -638,50 +633,46 @@ openerp.web_calendar = function(instance) {
 
             if (event.allDay) {
                 // Sometimes fullcalendar doesn't give any event.end.
-                if (event_end == null || _.isUndefined(event_end)) {
+                if (event_end === null || _.isUndefined(event_end)) {
                     event_end = new Date(event.start);
                 }
                 if (this.all_day) {
-                    event_end = (new Date(event_end.getTime())).addDays(1);
-                    date_start_day = new Date(event.start.getFullYear(),event.start.getMonth(),event.start.getDate(),12);
-                    date_stop_day = new Date(event_end.getFullYear(),event_end.getMonth(),event_end.getDate(),12);
+                    event_end = (new Date(event_end.getTime())).addDays(1); 
+                    date_start_day = new Date(Date.UTC(event.start.getFullYear(),event.start.getMonth(),event.start.getDate()))
+                    date_stop_day = new Date(Date.UTC(event_end.getFullYear(),event_end.getMonth(),event_end.getDate()))            
                 }
                 else {
-                    date_start_day = new Date(event.start.getFullYear(),event.start.getMonth(),event.start.getDate(),7);
-                    date_stop_day = new Date(event_end.getFullYear(),event_end.getMonth(),event_end.getDate(),19);
-                }
+                    date_start_day = new Date(Date.UTC(event.start.getFullYear(),event.start.getMonth(),event.start.getDate(),7))
+                    date_stop_day = new Date(Date.UTC(event_end.getFullYear(),event_end.getMonth(),event_end.getDate(),19))            
+                }                                
                 data[this.date_start] = instance.web.parse_value(date_start_day, this.fields[this.date_start]);
                 if (this.date_stop) {
                     data[this.date_stop] = instance.web.parse_value(date_stop_day, this.fields[this.date_stop]);
                 }
-                diff_seconds = Math.round((date_stop_day.getTime() - date_start_day.getTime()) / 1000);
                                 
             }
             else {
+                
                 data[this.date_start] = instance.web.parse_value(event.start, this.fields[this.date_start]);
                 if (this.date_stop) {
                     data[this.date_stop] = instance.web.parse_value(event_end, this.fields[this.date_stop]);
-                }
-                diff_seconds = Math.round((event_end.getTime() - event.start.getTime()) / 1000);
+                }            
+
             }
 
+
             if (this.all_day) {
-                data[this.all_day] = event.allDay;
+                data[this.all_day] = event.allDay;                
             }
 
             if (this.date_delay) {
-                
+                var diff_seconds = Math.round((event_end.getTime() - event.start.getTime()) / 1000);
                 data[this.date_delay] = diff_seconds / 3600;
             }
             return data;
         },
-
         do_search: function(domain, context, _group_by) {
             var self = this;
-           if (! self.all_filters) {            
-                self.all_filters = {}                
-           }
-
             if (! _.isUndefined(this.event_source)) {
                 this.$calendar.fullCalendar('removeEventSource', this.event_source);
             }
@@ -693,84 +684,82 @@ openerp.web_calendar = function(instance) {
                         domain: self.get_range_domain(domain, start, end),
                         context: context,
                     }).done(function(events) {
-
                         if (self.event_source !== current_event_source) {
                             console.log("Consecutive ``do_search`` called. Cancelling.");
                             return;
                         }
+                        // We should make sure that *2many used in title of event have their extended form [ID, NAME]...
+                        
+                        events = $.map(events, function (e) {
+                            
+                            if (self.attendee_people != undefined) { //If we filter on contacts...
+                                if (_.intersection(self.selected_filters,e[self.attendee_people]).length || (self.selected_filters.indexOf(-1) > -1)) {
+                                    return e;
+                                }
+                                else {
+                                    return null;
+                                }   
+                            }
+                            else { //We adds all events 
+                                return e;
+                            }                            
+                            return null;                            
+                        });
                         
-                        if (!self.useContacts) {  // If we use all peoples displayed in the current month as filter in sidebars
-                                                        
+                        if (!self.useContacts) {  // If we use all peoples as filter in sidebars
+                            var now_filters = {};
                             var filter_value;
                             var filter_item;
                             
-                            self.now_filter_ids = [];
-
                             _.each(events, function (e) {
                                 filter_value = e[self.color_field][0];
-                                if (!self.all_filters[e[self.color_field][0]]) {
-                                    filter_item = {
-                                        value: filter_value,
-                                        label: e[self.color_field][1],
-                                        color: self.get_color(filter_value),
-                                        avatar_model: self.avatar_model,
-                                        is_checked: true
-                                    };
-                                    self.all_filters[e[self.color_field][0]] = filter_item;
-                                }
-                                if (! _.contains(self.now_filter_ids, filter_value)) {
-                                    self.now_filter_ids.push(filter_value);
+                                filter_item = {
+                                    value: filter_value,
+                                    label: e[self.color_field][1],
+                                    color: self.get_color(filter_value),
+                                    avatar_model: self.avatar_model
+                                };
+                                if (!now_filters[e[self.color_field][0]]) {
+                                    now_filters[e[self.color_field][0]] = filter_item;
                                 }
                             });
-
-                            if (self.sidebar) {
-                                self.sidebar.filter.events_loaded();
-                                self.sidebar.filter.set_filters();
-                                
-                                events = $.map(events, function (e) {
-                                    if (_.contains(self.now_filter_ids,e[self.color_field][0]) &&  self.all_filters[e[self.color_field][0]].is_checked) {
-                                        return e;
-                                    }
-                                    return null;
-                                });
-                            }
+                            
+                            self.allFilters = now_filters;
+                            self.sidebar.filter.events_loaded(now_filters);                            
+                            
                             return self.perform_necessary_name_gets(events).then(callback);
                         }
-                        else { //WE USE CONTACT
-                            if (self.attendee_people !== undefined) {
-                                //if we don't filter on 'Everybody's Calendar
-                                if (!self.all_filters[-1] || !self.all_filters[-1].is_checked) {
-                                    var checked_filter = $.map(self.all_filters, function(o) { if (o.is_checked) { return o.value; }});
-                                    // If we filter on contacts... we keep only events from coworkers
-                                    events = $.map(events, function (e) {
-                                        if (_.intersection(checked_filter,e[self.attendee_people]).length) {
-                                            return e;
-                                        }
-                                        return null;
-                                    });
-                                }
-                            }
-
-                            var all_attendees = $.map(events, function (e) { return e[self.attendee_people]; });
+                        else {
+                            var all_attendees = [];
+                            
+                            _.each(events, function (e) {
+                                all_attendees.push(e[self.attendee_people]);                                
+                            });
+                            
+                            self.all_attendees = {}
+                            
                             all_attendees = _.chain(all_attendees).flatten().uniq().value();
-
-                            self.all_attendees = {};
-                            if (self.avatar_title !== null) {
-                                new instance.web.Model(self.avatar_title).query(["name"]).filter([["id", "in", all_attendees]]).all().then(function(result) {
+                            
+                            if (self.avatar_title != null) {
+                                new instance.web.Model(self.avatar_title).query(["name"]).filter([["id", "in",all_attendees]]).all().then(function(result) {
                                     _.each(result, function(item) {
                                         self.all_attendees[item.id] = item.name;
                                     });
-                                }).done(function() {
+                                }).done(function() { 
                                     return self.perform_necessary_name_gets(events).then(callback);
                                 });
-                            }
+                            }                                                        
                             else {
                                 _.each(all_attendees,function(item){
                                         self.all_attendees[item] = '';
                                 });
                                 return self.perform_necessary_name_gets(events).then(callback);
+                                
                             }
+                            
                         }
+                        
+
                     });
                 },
                 eventDataTransform: function (event) {
@@ -785,27 +774,13 @@ openerp.web_calendar = function(instance) {
          */
         get_range_domain: function(domain, start, end) {
             var format = instance.web.date_to_str;
-            
-            extend_domain = [[this.date_start, '>=', format(start.clone())],
-                     [this.date_start, '<=', format(end.clone())]];
-
-            if (this.date_stop) {
-                //add at start 
-                extend_domain.splice(0,0,'|','|','&');
-                //add at end 
-                extend_domain.push(
-                                '&',
-                                [this.date_start, '<=', format(start.clone())],
-                                [this.date_stop, '>=', format(start.clone())],
-                                '&',
-                                [this.date_start, '<=', format(end.clone())],
-                                [this.date_stop, '>=', format(start.clone())]
-                );
-                //final -> (A & B) | (C & D) | (E & F) ->  | | & A B & C D & E F
-            }
-            return new instance.web.CompoundDomain(domain, extend_domain);
+            return new instance.web.CompoundDomain(
+                domain,
+                [[this.date_start, '>=', format(start.clone())],
+                 [this.date_start, '<=', format(end.clone())]]);
         },
 
+
         /**
          * Updates record identified by ``id`` with values in object ``data``
          */
@@ -828,22 +803,26 @@ openerp.web_calendar = function(instance) {
             }
             return false;
         },
-        open_event: function(id, title) {
+        open_event: function(id,title) {
             var self = this;
-            if (! this.open_popup_action) {
+            if (! this.open_popup_action) { 
                 var index = this.dataset.get_id_index(id);
                 this.dataset.index = index;
                 this.do_switch_view('form', null, { mode: "edit" });
-            }
+            }            
             else {
+
+                var self = this;
+
                 var pop = new instance.web.form.FormOpenPopup(this);
+                console.log(this.open_popup_action, +this.open_popup_action);
                 pop.show_element(this.dataset.model, id, this.dataset.get_context(), {
                     title: _.str.sprintf(_t("View: %s"),title),
                     view_id: +this.open_popup_action,
                     res_id: id,
                     target: 'new',
                     readonly:true
-                });
+                });              
 
                var form_controller = pop.view_form;
                form_controller.on("load_record", self, function(){
@@ -851,25 +830,33 @@ openerp.web_calendar = function(instance) {
                     button_edit = _.str.sprintf("<button class='oe_button oe_bold editme oe_highlight'><span> %s </span></button>",_t("Edit Event"));
                     
                     
-                    pop.$el.closest(".ui-dialog").find(".ui-dialog-buttonpane").prepend(button_delete);
-                    pop.$el.closest(".ui-dialog").find(".ui-dialog-buttonpane").prepend(button_edit);
+                    pop.$el.closest(".ui-dialog").find(".ui-dialog-buttonpane").prepend(button_delete)
+                    pop.$el.closest(".ui-dialog").find(".ui-dialog-buttonpane").prepend(button_edit)
                     
                     $('.delme').click(
-                        function() {
-                            $('.oe_form_button_cancel').trigger('click');
-                            self.remove_event(id);
+                        function() { 
+                            $('.oe_form_button_cancel').trigger('click'); 
+                            self.remove_event(id); 
                         }
                     );
                     $('.editme').click(
-                        function() {
-                            $('.oe_form_button_cancel').trigger('click');
-                            self.dataset.index = self.dataset.get_id_index(id);
+                        function() { 
+                            $('.oe_form_button_cancel').trigger('click'); 
+
+                            var index = self.dataset.get_id_index(id);
+                            self.dataset.index = index;
                             self.do_switch_view('form', null, { mode: "edit" });
+
                         }
                     );
+                    
+                    
                });
-            }
-            return false;
+                 
+            }   
+            
+            return false;         
+            
         },
 
         do_show: function() {
@@ -913,10 +900,6 @@ openerp.web_calendar = function(instance) {
         slow_created: function () {
             // refresh all view, because maybe some recurrents item
             var self = this;
-            if (self.sidebar) {
-                // force filter refresh
-                self.sidebar.filter.is_loaded = false;
-            }
             self.$calendar.fullCalendar('refetchEvents');
         },
 
@@ -950,7 +933,7 @@ openerp.web_calendar = function(instance) {
         template: 'CalendarView.quick_create',
         
         init: function(parent, dataset, buttons, options, data_template) {
-            this._super(parent);
+            this._super(parent);            
             this.dataset = dataset;
             this._buttons = buttons || false;
             this.options = options;
@@ -961,7 +944,7 @@ openerp.web_calendar = function(instance) {
         get_title: function () {
             var parent = this.getParent();
             if (_.isUndefined(parent)) {
-                return _t("Create");
+                return _t("Create")
             }
             var title = (_.isUndefined(parent.field_widget)) ?
                     (parent.string || parent.name) :
@@ -982,7 +965,7 @@ openerp.web_calendar = function(instance) {
                 if(event.keyCode == 13){
                     self.$input.off('keyup', enterHandler);
                     if (!self.quick_add()){
-                        self.$input.on('keyup', enterHandler);
+                        self.$input.on('keyup', enterHandler);                    
                     }
                 }
             });
@@ -991,13 +974,14 @@ openerp.web_calendar = function(instance) {
             submit.click(function clickHandler() {
                 submit.off('click', clickHandler);
                 if (!self.quick_add()){
-                   submit.on('click', clickHandler);                }
+                   submit.on('click', clickHandler);                    
+                }
                 self.focus();
             });
             this.$el.find(".oe_calendar_quick_create_edit").click(function () {
                 self.slow_add();
                 self.focus();
-            });
+            });            
             this.$el.find(".oe_calendar_quick_create_close").click(function (ev) {
                 ev.preventDefault();
                 self.trigger('close');
@@ -1013,6 +997,7 @@ openerp.web_calendar = function(instance) {
             });
             
             self.$el.on('dialogclose', self, function() {
+                console.log("dialogclose");
                 self.trigger('close');
             });
 
@@ -1026,10 +1011,10 @@ openerp.web_calendar = function(instance) {
          */
         quick_add: function() {
             var val = this.$input.val();
-            if (/^\s*$/.test(val)) {
-                return false;
+            if (/^\s*$/.test(val)) { 
+                return false; 
             }
-            return this.quick_create({'name': val}).always(function() { return true; });
+            return this.quick_create({'name': val}).always(function() { return true });
         },
         
         slow_add: function() {
@@ -1068,19 +1053,21 @@ openerp.web_calendar = function(instance) {
             return infos;
         },
         slow_create: function(data) {
-            //if all day, we could reset time to display 00:00:00
-            
             var self = this;
             var def = $.Deferred();
             var defaults = {};
-
             _.each($.extend({}, this.data_template, data), function(val, field_name) {
                 defaults['default_' + field_name] = val;
             });
-                        
+            
+            if (defaults['default_allday'] && (defaults['default_date_deadline'] || defaults['default_duration'])) {
+                delete defaults['default_date_deadline'];
+                delete defaults['default_duration'];
+            }
+
             var pop_infos = self.get_form_popup_infos();
             var pop = new instance.web.form.FormOpenPopup(this);
-            var context = new instance.web.CompoundContext(this.dataset.context, defaults);
+            var context = new instance.web.CompoundContext(this.dataset.context, defaults)
             pop.show_element(this.dataset.model, null, this.dataset.get_context(defaults), {
                 title: this.get_title(),
                 disable_multiple_selection: true,
@@ -1155,6 +1142,7 @@ openerp.web_calendar = function(instance) {
                 if (this.$calendar.width() !== 0) { // visible
                     return this._super();
                 }
+
                 // find all parents tabs.
                 var def = $.Deferred();
                 var self = this;
@@ -1166,7 +1154,10 @@ openerp.web_calendar = function(instance) {
                 });
                 return def;
             },
+
+
         });
+
     }
 
     instance.web_calendar.BufferedDataSet = instance.web.BufferedDataSet.extend({
@@ -1319,10 +1310,13 @@ openerp.web_calendar = function(instance) {
             $.async_when().done(function () {
                 self.calendar_view.appendTo(self.$el);
             });
+            
+            
             return loaded;
         },
 
         render_value: function() {
+            console.log("In render value");
             var self = this;
             this.dataset.set_ids(this.get("value"));
             this.is_loaded = this.is_loaded.then(function() {
@@ -1332,7 +1326,7 @@ openerp.web_calendar = function(instance) {
 
         open_popup: function(type, unused) {
             if (type !== "form") { return; }
-            if (this.dataset.index == null) {
+            if (this.dataset.index === null) {
                 if (typeof this.open_popup_add === "function") {
                     this.open_popup_add();
                 }
@@ -1342,11 +1336,9 @@ openerp.web_calendar = function(instance) {
                 }
             }
         },
-
         open_popup_add: function() {
             throw new Error("Not Implemented");
         },
-
         open_popup_edit: function() {
             var id = this.dataset.ids[this.dataset.index];
             var self = this;
@@ -1368,7 +1360,7 @@ openerp.web_calendar = function(instance) {
                 },
 
                 alternative_form_view: this.field.views ? this.field.views.form : undefined,
-                parent_view: this.view,
+                parent_view: this.view, //XXXvlab: to check ! this.view is likely undefined
                 child_name: this.name,
                 readonly: this.get("effective_readonly")
             });
@@ -1390,39 +1382,41 @@ openerp.web_calendar = function(instance) {
         },
         init: function(parent, view) {
             this._super(parent);
-            this.view = view;
-        },
-        set_filters: function() {
-            var self = this;
-            _.forEach(self.view.all_filters, function(o) {
-                if (_.contains(self.view.now_filter_ids, o.value)) {
-                    self.$('div.oe_calendar_responsible input[value=' + o.value + ']').prop('checked',o.is_checked);
-                }
-            });
+            this.view = view;            
         },
         events_loaded: function(filters) {
             var self = this;
-            if (filters == null) {
-                filters = [];
-                _.forEach(self.view.all_filters, function(o) {
-                    if (_.contains(self.view.now_filter_ids, o.value)) {
-                        filters.push(o);
-                    }
-                });
-            }            
+            self.selected_filters = [];
+            self.view.all_filters = filters;
             this.$el.html(QWeb.render('CalendarView.sidebar.responsible', { filters: filters }));
+            this.filter_click(null);                        
         },
         filter_click: function(e) {
-            var self = this;            
-            self.view.all_filters[parseInt(e.target.value)].is_checked = e.target.checked;
-            self.view.$calendar.fullCalendar('refetchEvents');
+            var self = this,
+            responsibles = [];
+            self.view.selected_filters = [];
+            this.$('div.oe_calendar_responsible input:checked').each(function() {
+                responsibles.push($(this).val());
+                
+                if (e==null && parseInt($(this).val())<0) {
+                    $(this).prop('checked',false);
+                    return;
+                }                    
+                self.view.selected_filters.push(parseInt($(this).val()));
+            });
+            
+            if (e !== null) { //First intialize 
+                self.view.$calendar.fullCalendar('refetchEvents');  
+            }
+
+            
         },
         addUpdateButton: function() {
             var self=this;
             this.$('div.oe_calendar_all_responsibles').append(QWeb.render('CalendarView.sidebar.button_add_contact'));
-            this.$(".add_contacts_link_btn").on('click', function() {
-                self.rpc("/web/action/load", {
-                    action_id: "calendar.action_calendar_contacts"
+            this.$(".add_contacts_link_btn").on('click', function() {  
+                self.rpc("/web/action/load", { 
+                    action_id: "calendar.action_calendar_contacts" 
                 }).then( function(result) { return self.do_action(result); });
             });
             
@@ -1430,3 +1424,4 @@ openerp.web_calendar = function(instance) {
     });
 
 };
+
index f518098..4a05be9 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_diagram
 #. openerp-web
index a298416..b5176bf 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_diagram
 #. openerp-web
index 9e565fc..2877f53 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_diagram
 #. openerp-web
index e42e1cb..da3e035 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_diagram
 #. openerp-web
index 0d23759..3c94601 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_diagram
 #. openerp-web
index e0832aa..9e65244 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 "X-Poedit-Language: Czech\n"
 
 #. module: web_diagram
index 822c1da..7f34920 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_diagram
 #. openerp-web
index ade55de..734202e 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_diagram
 #. openerp-web
index 4d93da0..01a04a2 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_diagram
 #. openerp-web
index a77d753..1bfb82d 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_diagram
 #. openerp-web
index 42b60d4..8d845b6 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_diagram
 #. openerp-web
index 79afb06..a10737b 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_diagram
 #. openerp-web
index cdecbdc..d7a496b 100644 (file)
@@ -15,8 +15,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 "Language: es\n"
 
 #. module: web_diagram
index c900b5f..3e1a478 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_diagram
 #. openerp-web
index 1d45982..982bb48 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_diagram
 #. openerp-web
index 9f631eb..4a8cc56 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_diagram
 #. openerp-web
index 344818e..b35e3ed 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_diagram
 #. openerp-web
index 91e82ff..bf28061 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_diagram
 #. openerp-web
index 3026dcd..d959c91 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_diagram
 #. openerp-web
index 634c345..594766e 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_diagram
 #. openerp-web
index fc1dd64..8baf621 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_diagram
 #. openerp-web
index 39a1f1b..3b14644 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_diagram
 #. openerp-web
index a755ce3..8f1de5e 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_diagram
 #. openerp-web
index 4a4bdbc..ca733ce 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_diagram
 #. openerp-web
index 53b9883..00a9a57 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_diagram
 #. openerp-web
index ac76dc9..4931ff0 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_diagram
 #. openerp-web
index f1906c5..e288965 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_diagram
 #. openerp-web
index 58677f4..4130628 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_diagram
 #. openerp-web
index 234846c..04b3a4c 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_diagram
 #. openerp-web
index 47c7ab1..ae3567c 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_diagram
 #. openerp-web
index 5eeeb28..90b583d 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_diagram
 #. openerp-web
index 9168e6d..b91a710 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_diagram
 #. openerp-web
index 3e89e4a..9a872bd 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_diagram
 #. openerp-web
index 13f99f8..bf074c0 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_diagram
 #. openerp-web
index 8c14f16..0ce4b20 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_diagram
 #. openerp-web
index e27215a..d1295c7 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_diagram
 #. openerp-web
index 4b0d845..5acb445 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_diagram
 #. openerp-web
index e2a5ffd..c287bfe 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_diagram
 #. openerp-web
index 598dfda..71d089e 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_diagram
 #. openerp-web
index 76e4c91..5487322 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_diagram
 #. openerp-web
index 7f687bc..dcc8b60 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_diagram
 #. openerp-web
index 880ad51..196e768 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_diagram
 #. openerp-web
index fd608ff..ce755be 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_diagram
 #. openerp-web
index d4fd843..f29a9be 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_diagram
 #. openerp-web
index a365394..adf0011 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_diagram
 #. openerp-web
index eff432a..e201fe5 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_diagram
 #. openerp-web
index 71ee6bf..d746dbb 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_diagram
 #. openerp-web
index 695715d..bf72ac6 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_diagram
 #. openerp-web
index 540d255..8d297cc 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_diagram
 #. openerp-web
index 7a5a7ff..d5e2825 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_gantt
 #. openerp-web
index 119c35b..c8411a2 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_gantt
 #. openerp-web
index 093960e..32ddc9e 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_gantt
 #. openerp-web
index 3e129f7..4c3a612 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_gantt
 #. openerp-web
index bdf4e80..6731fe3 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_gantt
 #. openerp-web
index 8b83cca..1a191db 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 "X-Poedit-Language: Czech\n"
 
 #. module: web_gantt
index f961d3c..2fcb4f2 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_gantt
 #. openerp-web
index aea0f55..92a6aaf 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_gantt
 #. openerp-web
index 47d0a52..17b3c2d 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_gantt
 #. openerp-web
index 2fbe52d..f81ecf2 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_gantt
 #. openerp-web
index 1f7a99e..2f88821 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_gantt
 #. openerp-web
index 9bc637f..8e6cf13 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_gantt
 #. openerp-web
index 4674b91..94b443f 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_gantt
 #. openerp-web
index 5800870..374c9a6 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_gantt
 #. openerp-web
index 3737dc9..30e4132 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_gantt
 #. openerp-web
index 13cd1dd..ba7ca4e 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_gantt
 #. openerp-web
index d4b2a5c..f48df0c 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_gantt
 #. openerp-web
index 5708a09..df39b92 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_gantt
 #. openerp-web
index 25e4296..99776e0 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_gantt
 #. openerp-web
index 9b3e810..b64d86a 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_gantt
 #. openerp-web
index f3e3a17..921fe6f 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_gantt
 #. openerp-web
index f0d6b5b..366ff63 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_gantt
 #. openerp-web
index f415a52..88d1fe5 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_gantt
 #. openerp-web
index 3bd136a..9b064c5 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_gantt
 #. openerp-web
index 9ff6bb3..1a14c02 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_gantt
 #. openerp-web
index ba54149..3cea99e 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_gantt
 #. openerp-web
index 1dfd09b..61bcd0e 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_gantt
 #. openerp-web
index 42eacc4..2ad8277 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_gantt
 #. openerp-web
index d1f3101..19c5ae6 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_gantt
 #. openerp-web
index 0c36d23..7a18907 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_gantt
 #. openerp-web
index 34f187d..2501c02 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_gantt
 #. openerp-web
index 27ee629..5970f0c 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_gantt
 #. openerp-web
index b021cf3..41a5119 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_gantt
 #. openerp-web
index 643d2c6..8eda0b8 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_gantt
 #. openerp-web
index 5d3d398..68841ea 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_gantt
 #. openerp-web
index 6b6c5b6..9150a54 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_gantt
 #. openerp-web
index f87ae76..bd8ffc7 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_gantt
 #. openerp-web
index 427c523..13c00f8 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_gantt
 #. openerp-web
index 3ad6c8a..8ae5df3 100644 (file)
@@ -15,8 +15,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_gantt
 #. openerp-web
index 358e32d..6bfca9a 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_gantt
 #. openerp-web
index f730151..c6478e4 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_gantt
 #. openerp-web
index e0e5a57..375838c 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_gantt
 #. openerp-web
index 86c5219..fdf98c6 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_gantt
 #. openerp-web
index 9cb29e6..b13efb0 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_gantt
 #. openerp-web
index 2104dd9..8774a63 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_gantt
 #. openerp-web
index cc78b39..e8bf234 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_gantt
 #. openerp-web
index e361d77..3c75a89 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_gantt
 #. openerp-web
index 7cb2eec..0a4fde3 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_gantt
 #. openerp-web
index efe2051..c8c2645 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_graph
 #. openerp-web
index de5de09..a627be1 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_graph
 #. openerp-web
index d05a91b..1530ea2 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_graph
 #. openerp-web
index 356dd6c..0d5d7b9 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_graph
 #. openerp-web
index e1d5af1..4fb6156 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_graph
 #. openerp-web
index ef6895e..cd5eb0a 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_graph
 #. openerp-web
index d401a27..d9b3e35 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_graph
 #. openerp-web
index 6cbeba9..35ad229 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_graph
 #. openerp-web
index 695f15b..2686db8 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_graph
 #. openerp-web
index d874233..928d77c 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_graph
 #. openerp-web
index 3cb73d1..cfcadaa 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_graph
 #. openerp-web
index 214d299..827c7e8 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_graph
 #. openerp-web
index 3eaa8b7..dd25c59 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_graph
 #. openerp-web
index 36a2b86..32ac181 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_graph
 #. openerp-web
index fa5d6bd..50a364a 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_graph
 #. openerp-web
index d0c2321..b5191aa 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_graph
 #. openerp-web
index 9ff87f7..aaf7ae9 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_graph
 #. openerp-web
index 06b2a71..7897915 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_graph
 #. openerp-web
index 47ec843..eabf51d 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_graph
 #. openerp-web
index 56acb73..253009c 100644 (file)
@@ -15,8 +15,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_graph
 #. openerp-web
index c8212c8..c9c4e02 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_graph
 #. openerp-web
index 75f5861..d53d041 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_graph
 #. openerp-web
index c1d4fd9..5531faa 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_graph
 #. openerp-web
index 8771ca2..66072f6 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_graph
 #. openerp-web
index 711e0fa..d743913 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_graph
 #. openerp-web
index 9dfdb85..1bf0825 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_graph
 #. openerp-web
index c3671ec..7223f21 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_graph
 #. openerp-web
index 8f3e8a0..d18bc84 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_graph
 #. openerp-web
index a4953ac..1bc772c 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_graph
 #. openerp-web
index 8486ff0..cfc8fbe 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_graph
 #. openerp-web
index 2f37a47..390c8d4 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_graph
 #. openerp-web
index 30ab0b0..cd61fe2 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_graph
 #. openerp-web
index e736d22..c238c35 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_graph
 #. openerp-web
index 321f28a..0cd558c 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_graph
 #. openerp-web
index f3e3063..6041c13 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_graph
 #. openerp-web
index 4ee999e..f7bcdf6 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_graph
 #. openerp-web
index 0034b9b..ab01ef2 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_graph
 #. openerp-web
index 376bb8f..3751983 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_graph
 #. openerp-web
index 9f4572e..f0ea122 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_graph
 #. openerp-web
index 63d04e9..a1a7c93 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_graph
 #. openerp-web
index 108dfef..4d5e27c 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_graph
 #. openerp-web
index 74f796a..04608f3 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_graph
 #. openerp-web
index 6c374ae..1ce2678 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_graph
 #. openerp-web
index 76be580..5297f36 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_graph
 #. openerp-web
index f978cef..b17e264 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_graph
 #. openerp-web
index d43ca8a..eee0f2e 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_graph
 #. openerp-web
index 61c623f..345c906 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:10+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_graph
 #. openerp-web
index 978d2ae..24fef7d 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_graph
 #. openerp-web
index 1949028..b7d8259 100644 (file)
@@ -1,11 +1,3 @@
-.graph_pivot_mode {
-    position:initial;
-}
-
-.graph_chart_mode {
-    position:relative;
-}
-
 .graph_main_content td {
     font-size: 12px;
     margin: 45px;
index 25a1f93..c29c78e 100644 (file)
@@ -77,12 +77,8 @@ instance.web_graph.GraphView = instance.web.View.extend({
     },
 
     do_search: function (domain, context, group_by) {
-        if (this.ignore_do_search) {
-            this.ignore_do_search = false;
-            return;
-        }
         var self = this,
-            groupbys = this.get_groupbys_from_searchview(),
+            groupbys = this.get_groupbys_dos(),
             col_group_by = groupbys.col_group_by;
 
         if (!this.graph_widget) {
@@ -90,7 +86,7 @@ instance.web_graph.GraphView = instance.web.View.extend({
                 this.widget_config.row_groupby = group_by;
             }
             if (col_group_by.length) {
-                this.widget_config.col_groupby = col_group_by;
+                this.widget_config.col_groupby = group_by;
             }
             this.graph_widget = new openerp.web_graph.Graph(this, this.model, domain, this.widget_config);
             this.graph_widget.appendTo(this.$el);
@@ -111,7 +107,7 @@ instance.web_graph.GraphView = instance.web.View.extend({
             searchdata = this.search_view.build_search_data();
 
         _.each(searchdata.groupbys, function (data) {
-            data = (_.isString(data)) ? py.eval(data) : data;
+            data = (_isString(data)) ? py.eval(data) : data;
             result.group_by = result.group_by.concat(data.group_by);
             if (data.col_group_by) {
                 result.col_group_by = result.col_group_by.concat(data.col_group_by);
@@ -140,52 +136,30 @@ instance.web_graph.GraphView = instance.web.View.extend({
 
     // add groupby to the search view
     register_groupby: function(row_groupby, col_groupby) {
-        var query = this.search_view.query,
-            groupbys = this.get_groupbys_from_searchview(),
-            search_row_groupby = groupbys.group_by,
-            search_col_groupby = groupbys.col_group_by,
-            row_gb_changed = !_.isEqual(_.pluck(row_groupby, 'field'), search_row_groupby),
-            col_gb_changed = !_.isEqual(_.pluck(col_groupby, 'field'), search_col_groupby);
+        var query = this.search_view.query;
 
         if (!_.has(this.search_view, '_s_groupby')) { return; }
 
-        if (!row_gb_changed && !col_gb_changed) {
-            return;
-        }
-
-        if (row_gb_changed && col_gb_changed) {
-            // when two changes to the search view will be done, the method do_search
-            // will be called twice, once with the correct groupby and incorrect col_groupby,
-            // and once with correct informations. This flag is necessary to prevent the 
-            // incorrect informations to propagate and trigger useless queries
-            this.ignore_do_search = true;
-        }
-
-        if (row_gb_changed) {
-            // add row groupbys
-            var row_facet = this.make_row_groupby_facets(row_groupby),
-                row_search_facet = query.findWhere({category:'GroupBy'});
+        // add row groupbys
+        var row_facet = this.make_row_groupby_facets(row_groupby),
+            row_search_facet = query.findWhere({category:'GroupBy'});
 
-            if (row_search_facet) {
-                row_search_facet.values.reset(row_facet.values);
-            } else {
-                if (row_groupby.length) {
-                    query.add(row_facet);
-                }
+        if (row_search_facet) {
+            row_search_facet.values.reset(row_facet.values);
+        } else {
+            if (row_groupby.length) {
+                query.add(row_facet);
             }
         }
-
-        if (col_gb_changed) {
-            // add col groupbys
-            var col_facet = this.make_col_groupby_facets(col_groupby),
-                col_search_facet = query.findWhere({category:'ColGroupBy'});
-
-            if (col_search_facet) {
-                col_search_facet.values.reset(col_facet.values);
-            } else {
-                if (col_groupby.length) {
-                    query.add(col_facet);
-                }
+         // add col groupbys
+        var col_facet = this.make_col_groupby_facets(col_groupby),
+            col_search_facet = query.findWhere({category:'ColGroupBy'});
+
+        if (col_search_facet) {
+            col_search_facet.values.reset(col_facet.values);
+        } else {
+            if (col_groupby.length) {
+                query.add(col_facet);
             }
         }
     },
index 3f6acdf..51baaba 100644 (file)
@@ -38,9 +38,6 @@ openerp.web_graph.Graph = openerp.web.Widget.extend({
 
         if (this.mode !== 'pivot') {
             this.$('.graph_heatmap label').addClass('disabled');
-            this.$('.graph_main_content').addClass('graph_chart_mode');
-        } else {
-            this.$('.graph_main_content').addClass('graph_pivot_mode');
         }
 
         openerp.session.rpc('/web_graph/check_xlwt').then(function (result) {
@@ -157,13 +154,6 @@ openerp.web_graph.Graph = openerp.web.Widget.extend({
             return;
         }
 
-        if (!dom_changed && col_reduced && row_reduced) {
-            this.pivot.fold_with_depth(this.pivot.rows, row_gbs.length);
-            this.pivot.fold_with_depth(this.pivot.cols, col_gbs.length);
-            this.display_data();
-            return;
-        }
-
         if (dom_changed || row_gb_changed || col_gb_changed) {
             this.pivot.set(domain, row_gbs, col_gbs).then(this.proxy('display_data'));
         }
@@ -174,10 +164,8 @@ openerp.web_graph.Graph = openerp.web.Widget.extend({
 
         if (mode === 'pivot') {
             this.$('.graph_heatmap label').removeClass('disabled');
-            this.$('.graph_main_content').removeClass('graph_chart_mode').addClass('graph_pivot_mode');
         } else {
             this.$('.graph_heatmap label').addClass('disabled');
-            this.$('.graph_main_content').removeClass('graph_pivot_mode').addClass('graph_chart_mode');
         }
         this.display_data();
     },
@@ -275,6 +263,9 @@ openerp.web_graph.Graph = openerp.web.Widget.extend({
             case 'swap_axis':
                 this.swap_axis();
                 break;
+            case 'expand_all':
+                this.pivot.expand_all().then(this.proxy('display_data'));
+                break;
             case 'update_values':
                 this.pivot.update_data().then(this.proxy('display_data'));
                 break;
@@ -304,30 +295,25 @@ openerp.web_graph.Graph = openerp.web.Widget.extend({
 
         if (header.expanded) {
             this.fold(header);
-            return;
-        } 
-        if (header.path.length < header.root.groupby.length) {
-            this.expand(id);
-            return;
-        } 
-        if (!this.important_fields.length) {
-            return;
-        }
+        } else {
+            if (header.path.length < header.root.groupby.length) {
+                this.expand(id);
+            } else {
+                if (!this.important_fields.length) {
+                    return;
+                }
 
-        var fields = _.map(this.important_fields, function (field) {
-                return {id: field.field, value: field.string, type:self.fields[field.field.split(':')[0]].type};
-        });
-        if (this.dropdown) {
-            this.dropdown.remove();
+                var fields = _.map(this.important_fields, function (field) {
+                        return {id: field.field, value: field.string, type:self.fields[field.field.split(':')[0]].type};
+                });
+                this.dropdown = $(QWeb.render('field_selection', {fields:fields, header_id:id}));
+                $(event.target).after(this.dropdown);
+                this.dropdown.css({position:'absolute',
+                                   left:event.pageX,
+                                   top:event.pageY});
+                this.$('.field-selection').next('.dropdown-menu').toggle();
+            }
         }
-        this.dropdown = $(QWeb.render('field_selection', {fields:fields, header_id:id}));
-        $(event.target).after(this.dropdown);
-        this.dropdown.css({position:'absolute',
-                           left:event.pageX,
-                           top:event.pageY});
-        this.$('.field-selection').next('.dropdown-menu').toggle();
-        
-        
     },
 
     field_selection: function (event) {
index 4522fd2..81804e5 100644 (file)
@@ -35,6 +35,9 @@
             <label class="btn btn-default" data-choice="swap_axis" title="Swap Axis">
                 <span class="fa fa-expand"></span>
             </label>
+            <label class="btn btn-default" data-choice="expand_all" title="Expand All">
+                <span class="fa fa-arrows-alt"></span>
+            </label>
             <label class="btn btn-default" data-choice="update_values" title="Reload Data">
                 <span class="fa fa-refresh"></span>
             </label>
index f337bc0..7afa6f4 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_kanban
 #. openerp-web
index 4f4a00e..d57416d 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_kanban
 #. openerp-web
index 6491f12..0002d61 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_kanban
 #. openerp-web
index 3918b82..b0547ac 100644 (file)
@@ -9,13 +9,13 @@ msgstr ""
 "Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
 "POT-Creation-Date: 2012-12-21 17:06+0000\n"
 "PO-Revision-Date: 2014-01-30 17:06+0000\n"
-"Last-Translator: Boško Stojaković <bluesoft83@gmail.com>\n"
+"Last-Translator: Bosko Stojakovic <bluesoft83@gmail.com>\n"
 "Language-Team: Bosnian <bs@li.org>\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_kanban
 #. openerp-web
index df3b2b4..828f1b0 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_kanban
 #. openerp-web
index 1781c83..814849f 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 "X-Poedit-Language: Czech\n"
 
 #. module: web_kanban
index f35d1cb..2d999e1 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_kanban
 #. openerp-web
index fd8a74b..c350b16 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_kanban
 #. openerp-web
index cec220f..7ef5b7f 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_kanban
 #. openerp-web
index be1dc80..0d82d30 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_kanban
 #. openerp-web
index 29c6e7c..5f95a92 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_kanban
 #. openerp-web
index a5b3998..a6d981a 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_kanban
 #. openerp-web
index 25df2cb..552a71b 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_kanban
 #. openerp-web
index cd6843b..9301ff3 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_kanban
 #. openerp-web
index 3e2149e..8441b48 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_kanban
 #. openerp-web
index fe9d014..031fc9c 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_kanban
 #. openerp-web
index 8dcfb41..572bf61 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_kanban
 #. openerp-web
index 6eaa2bd..4cce265 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_kanban
 #. openerp-web
index 5fd09e9..3c54ba5 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_kanban
 #. openerp-web
index 8b91972..329212d 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_kanban
 #. openerp-web
index e05bef7..9476a96 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_kanban
 #. openerp-web
index e6e15f0..2cd9e34 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_kanban
 #. openerp-web
index edb7179..47bcde2 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_kanban
 #. openerp-web
index 29795dc..e981990 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_kanban
 #. openerp-web
index 5705fce..7ef59a4 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_kanban
 #. openerp-web
index ac46ca8..2b01b41 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_kanban
 #. openerp-web
index fbc2b6a..377259e 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_kanban
 #. openerp-web
index 4e066bc..63c552b 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_kanban
 #. openerp-web
index 62e41d3..c5d469a 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_kanban
 #. openerp-web
index 53eb527..5271c6c 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_kanban
 #. openerp-web
index 36a6500..379f40a 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_kanban
 #. openerp-web
index d8f1ea4..0ab63dc 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_kanban
 #. openerp-web
index 679f3e6..9b92f8a 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_kanban
 #. openerp-web
index 9b252a1..cd9a232 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_kanban
 #. openerp-web
index 054065c..8c80f93 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_kanban
 #. openerp-web
index 22d4552..2020960 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_kanban
 #. openerp-web
index 53a09c3..6729982 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_kanban
 #. openerp-web
index f9eacc2..d3ef97f 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_kanban
 #. openerp-web
index 583d902..6944b10 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_kanban
 #. openerp-web
index 7a2d72b..388fcc1 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_kanban
 #. openerp-web
index 0e1e001..e7cc314 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_kanban
 #. openerp-web
index 97bfd11..dd9e2aa 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_kanban
 #. openerp-web
index f2cb3ac..3ff26ea 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_kanban
 #. openerp-web
index e9d1d65..a9a8637 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_kanban
 #. openerp-web
index b5ea15a..8b974d0 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_kanban
 #. openerp-web
index fbf668e..e6e802f 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_kanban
 #. openerp-web
index 3436804..291dfe9 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_kanban
 #. openerp-web
index f779186..619b7fd 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_kanban
 #. openerp-web
index 07e462f..0ca10ba 100644 (file)
@@ -1,5 +1,7 @@
 
-openerp.testing.section('basic section', function (test) {
+// niv: I desactivate these until the testing framework has been adapted to better use
+// the new way to declare JavaScript modules
+/*openerp.testing.section('basic section', function (test) {
     test('my first test', function () {
         ok(true, "this test has run");
     });
@@ -85,4 +87,19 @@ openerp.testing.section('basic section', function (test) {
             deepEqual(dbm.db_list, ['foo', 'bar', 'baz']);
         });
     });
-});
+
+//    test('actual RPC', {rpc: 'rpc', asserts: 4}, function (instance) {
+//        var Model = new instance.web.Model('web_tests_demo.model');
+//        return Model.call('create', [{name: "Bob"}])
+//            .then(function (id) {
+//                return Model.call('read', [[id]]);
+//            }).then(function (records) {
+//                strictEqual(records.length, 1);
+//                var record = records[0];
+//                strictEqual(record.name, "Bob");
+//                strictEqual(record.thing, false);
+//                // default value
+//                strictEqual(record.other, 'bob');
+//            });
+//    });
+});*/
diff --git a/addons/web_tests_demo/tests/__init__.py b/addons/web_tests_demo/tests/__init__.py
deleted file mode 100644 (file)
index 1db9e39..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-# -*- coding: utf-8 -*-
-import test_js
diff --git a/addons/web_tests_demo/tests/test_js.py b/addons/web_tests_demo/tests/test_js.py
deleted file mode 100644 (file)
index fb97176..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-# -*- coding: utf-8 -*-
-from openerp.addons.web.tests.test_js import WebSuite
-
-def load_tests(loader, standard_tests, _):
-    standard_tests.addTest(WebSuite('web_tests_demo'))
-    return standard_tests
index fa2d683..b57aed9 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_view_editor
 #. openerp-web
index b9e47b4..5cf343f 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_view_editor
 #. openerp-web
index 9899698..fdaa75a 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_view_editor
 #. openerp-web
index 882ef8a..6477e92 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_view_editor
 #. openerp-web
index 337a5a6..b56aa36 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_view_editor
 #. openerp-web
index 8c77fa8..bc75227 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_view_editor
 #. openerp-web
index 2a27146..c592fdc 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_view_editor
 #. openerp-web
index a7835ad..fc35a01 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_view_editor
 #. openerp-web
index 1f0737c..aaed154 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_view_editor
 #. openerp-web
index 9b7a241..4695d50 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_view_editor
 #. openerp-web
index 4e219f9..d05f463 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_view_editor
 #. openerp-web
index f6fc91b..3cfbeea 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_view_editor
 #. openerp-web
index 2a909d3..acfea2b 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_view_editor
 #. openerp-web
index 26ce983..08b636c 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_view_editor
 #. openerp-web
index cbe3af7..5ee467b 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_view_editor
 #. openerp-web
index 027ddbd..b4c9012 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_view_editor
 #. openerp-web
index f1a5dbe..c72601c 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_view_editor
 #. openerp-web
index 5355849..2827721 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_view_editor
 #. openerp-web
index 35304df..7822685 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_view_editor
 #. openerp-web
index b87577a..eb463e0 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_view_editor
 #. openerp-web
index e012b5e..155039d 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_view_editor
 #. openerp-web
index 79a78dd..cf00e2a 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_view_editor
 #. openerp-web
index 50992a6..fd4a241 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_view_editor
 #. openerp-web
index 07cdaef..37276ab 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_view_editor
 #. openerp-web
index 1a9f99f..2a15b04 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_view_editor
 #. openerp-web
index 43e5d11..6a3e0fe 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_view_editor
 #. openerp-web
index c098de4..05317b4 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_view_editor
 #. openerp-web
index 76bda2c..454e0f2 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_view_editor
 #. openerp-web
index aa54ae7..136c1da 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_view_editor
 #. openerp-web
index 414757a..cc39830 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_view_editor
 #. openerp-web
index 87777be..69ce6cc 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_view_editor
 #. openerp-web
index 45f82fe..d151b80 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_view_editor
 #. openerp-web
index 2116698..7c8e114 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_view_editor
 #. openerp-web
index d95e8db..d281769 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_view_editor
 #. openerp-web
index 2a93fc1..9a1e5cb 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_view_editor
 #. openerp-web
index b1f3aa8..55e3102 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_view_editor
 #. openerp-web
index edfec33..6d8c4ff 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-15 07:06+0000\n"
-"X-Generator: Launchpad (build 16963)\n"
+"X-Launchpad-Export-Date: 2014-02-13 06:11+0000\n"
+"X-Generator: Launchpad (build 16916)\n"
 
 #. module: web_view_editor
 #. openerp-web
index 69e9a30..a790668 100644 (file)
@@ -15,7 +15,7 @@ instance.web.ViewManagerAction.include({
                 }
                 evt.currentTarget.selectedIndex = 0;
         }else{
-            return this._super.apply(this,arguments);
+            return this._super.apply(this,arguments); 
         }
     }
 });
@@ -73,10 +73,12 @@ instance.web_view_editor.ViewEditor =   instance.web.Widget.extend({
         $.when(this.action_manager.do_action(action)).done(function() {
             var viewmanager = self.action_manager.inner_widget;
             var controller = viewmanager.views[viewmanager.active_view].controller;
-            $(controller.groups).bind({
-                'selected': function (e, ids, records, deselected) {
+            controller.on('view_loaded', self, function(){
+                $(controller.groups).bind({
+                    'selected': function(e, ids, records) {
                         self.main_view_id = ids[0];
-                }
+                    }
+                });
             });
         });
     },
@@ -230,11 +232,10 @@ instance.web_view_editor.ViewEditor =   instance.web.Widget.extend({
         return main_object;
     },
     parse_xml: function(arch, view_id) {
-        //First element of att_list must be element tagname.
         main_object = {
             'level': 0,
             'id': this.xml_element_id +=1,
-            'att_list': ["view"],
+            'att_list': [],
             'name': _.str.sprintf("<view view_id = %s>", view_id),
             'child_id': []
         };
@@ -534,22 +535,15 @@ instance.web_view_editor.ViewEditor =   instance.web.Widget.extend({
         var field_dataset = new instance.web.DataSetSearch(this, this.model, null, null);
         parent_tr = self.get_object_by_id(parseInt($(parent_tr).attr('id').replace(/[^0-9]+/g, '')), this.one_object['main_object'], [])[0].att_list[0];
         _.each([tr, parent_tr],function(element) {
-            var value = _.has(_CHILDREN, element) ? element : _.str.include(html_tag, element)?"html_tag":false;
+            var value = _.has(_CHILDREN, element) ? element : _.str.include(html_tag, element)?"html_tag":false; 
             property_to_check.push(value);
         });
         field_dataset.call( 'fields_get', []).done(function(result) {
             var fields = _.keys(result);
             fields.push(" "),fields.sort();
-            self.on_add_node(property_to_check, fields, self.inject_position(parent_tr,tr));
+            self.on_add_node(property_to_check, fields);
         });
     },
-    inject_position : function(parent_tag,current_tag){
-        if(parent_tag == "view")
-            return ['Inside'];
-        if(current_tag == "field")
-            return ['After','Before'];
-        return ['After','Before','Inside'];
-    },
     do_node_edit: function(side) {
         var self = this;
         var result = self.get_object_by_id(this.one_object.clicked_tr_id, this.one_object['main_object'], []);
@@ -643,12 +637,12 @@ instance.web_view_editor.ViewEditor =   instance.web.Widget.extend({
             var children = _.filter(xml_arch.childNodes[0].childNodes, function (child) {
                 return child.nodeType == 1;
             });
-            var inherited_view = _.detect(children, function(xml_child) {
+            arch.arch = _.detect(children, function(xml_child) {
                 var temp_obj = self.create_View_Node(xml_child),
                     insert = _.intersection(_.flatten(temp_obj.att_list),_.uniq(check_list));
                 if (insert.length == _.uniq(check_list).length ) {return xml_child;}
             });
-            xml_arch = QWeb.load_xml(instance.web.xml_to_str(inherited_view));
+            xml_arch = QWeb.load_xml(arch.arch);
         }
         return self.do_save_xml(xml_arch.documentElement, obj[0].child_id[0],obj[0].child_id, move_direct, update_values,arch);
     },
@@ -947,11 +941,11 @@ instance.web_view_editor.ViewEditor =   instance.web.Widget.extend({
             });
         return def.promise();
     },
-    on_add_node: function(properties, fields, position){
+    on_add_node: function(properties, fields){
         var self = this;
         var  render_list = [{'name': 'node_type','selection': _.keys(_CHILDREN).sort(), 'value': 'field', 'string': 'Node Type','type': 'selection'},
                             {'name': 'field_value','selection': fields, 'value': false, 'string': '','type': 'selection'},
-                            {'name': 'position','selection': position, 'value': false, 'string': 'Position','type': 'selection'}];
+                            {'name': 'position','selection': ['After','Before','Inside'], 'value': false, 'string': 'Position','type': 'selection'}];
         this.add_widget = [];
         this.add_node_dialog = new instance.web.Dialog(this,{
             title: _t("Properties"),
@@ -1192,7 +1186,7 @@ var _CHILDREN = {
 //e.g.:xyz 'td' : ['field']
 };
 // Generic html_tag list and can be added html tag in future. It's support above _CHILDREN dict's *html_tag* by default.
-// For specific child node one has to define tag above and specify children tag in list. Like above xyz example.
+// For specific child node one has to define tag above and specify children tag in list. Like above xyz example. 
 var html_tag = ['div','h1','h2','h3','h4','h5','h6','td','tr'];
 
 var _ICONS = ['','STOCK_ABOUT', 'STOCK_ADD', 'STOCK_APPLY', 'STOCK_BOLD',
index 4a3f34d..90f43dd 100644 (file)
@@ -40,8 +40,6 @@ conf['addons_path'] = '../../addons/trunk,../../web/trunk/addons'
 #----------------------------------------------------------
 application = openerp.service.wsgi_server.application
 
-openerp.service.server.load_server_wide_modules()
-
 #----------------------------------------------------------
 # Gunicorn
 #----------------------------------------------------------
index 237e3a2..26b39de 100644 (file)
@@ -24,6 +24,7 @@ import workflow
 import module
 import res
 import report
+import test
 import tests
 
 # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
index 57ce6b3..3c3c290 100644 (file)
@@ -57,7 +57,6 @@ The kernel of OpenERP, needed for all installation.
         'ir/ir_values_view.xml',
         'ir/osv_memory_autovacuum.xml',
         'ir/ir_model_report.xml',
-        'ir/ir_logging_view.xml',
         'workflow/workflow_view.xml',
         'module/module_view.xml',
         'module/module_data.xml',
index 6b28e22..1ba79c7 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-20 05:30+0000\n"
-"X-Generator: Launchpad (build 16967)\n"
+"X-Launchpad-Export-Date: 2014-02-22 06:21+0000\n"
+"X-Generator: Launchpad (build 16926)\n"
 
 #. module: base
 #: model:ir.module.module,description:base.module_account_check_writing
index 248585c..bd878c8 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-20 05:30+0000\n"
-"X-Generator: Launchpad (build 16967)\n"
+"X-Launchpad-Export-Date: 2014-02-22 06:22+0000\n"
+"X-Generator: Launchpad (build 16926)\n"
 
 #. module: base
 #: model:ir.module.module,description:base.module_account_check_writing
index dce06ee..4ace71b 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-20 05:31+0000\n"
-"X-Generator: Launchpad (build 16967)\n"
+"X-Launchpad-Export-Date: 2014-02-22 06:22+0000\n"
+"X-Generator: Launchpad (build 16926)\n"
 
 #. module: base
 #: model:ir.module.module,description:base.module_account_check_writing
index 15a0ba0..f2b1d19 100644 (file)
@@ -13,8 +13,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-20 05:31+0000\n"
-"X-Generator: Launchpad (build 16967)\n"
+"X-Launchpad-Export-Date: 2014-02-22 06:22+0000\n"
+"X-Generator: Launchpad (build 16926)\n"
 
 #. module: base
 #: model:ir.module.module,description:base.module_account_check_writing
index 87b6fde..fb924a7 100644 (file)
@@ -13,8 +13,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-20 05:32+0000\n"
-"X-Generator: Launchpad (build 16967)\n"
+"X-Launchpad-Export-Date: 2014-02-22 06:23+0000\n"
+"X-Generator: Launchpad (build 16926)\n"
 
 #. module: base
 #: model:ir.module.module,description:base.module_account_check_writing
index 18d9cb2..dcf88ca 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-20 05:32+0000\n"
-"X-Generator: Launchpad (build 16967)\n"
+"X-Launchpad-Export-Date: 2014-02-22 06:23+0000\n"
+"X-Generator: Launchpad (build 16926)\n"
 
 #. module: base
 #: model:ir.module.module,description:base.module_account_check_writing
index 64560df..8bed195 100644 (file)
@@ -13,8 +13,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-20 05:32+0000\n"
-"X-Generator: Launchpad (build 16967)\n"
+"X-Launchpad-Export-Date: 2014-02-22 06:23+0000\n"
+"X-Generator: Launchpad (build 16926)\n"
 
 #. module: base
 #: model:ir.module.module,description:base.module_account_check_writing
index 5e9a509..f2ebada 100644 (file)
@@ -13,8 +13,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-20 05:32+0000\n"
-"X-Generator: Launchpad (build 16967)\n"
+"X-Launchpad-Export-Date: 2014-02-22 06:23+0000\n"
+"X-Generator: Launchpad (build 16926)\n"
 
 #. module: base
 #: model:ir.module.module,description:base.module_account_check_writing
index d5f8a06..b5287f5 100644 (file)
@@ -13,8 +13,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-20 05:33+0000\n"
-"X-Generator: Launchpad (build 16967)\n"
+"X-Launchpad-Export-Date: 2014-02-22 06:24+0000\n"
+"X-Generator: Launchpad (build 16926)\n"
 "X-Poedit-Language: Czech\n"
 
 #. module: base
@@ -64,7 +64,7 @@ msgstr "Zobrazení architektury"
 #. module: base
 #: model:ir.module.module,summary:base.module_sale_stock
 msgid "Quotation, Sale Orders, Delivery & Invoicing Control"
-msgstr "Nabídky, zakázky, řízení dodávek a fakturace"
+msgstr "Nabídky, zakázky, řízení dopravy a fakturace"
 
 #. module: base
 #: selection:ir.sequence,implementation:0
@@ -87,7 +87,8 @@ msgid ""
 "Helps you manage your projects and tasks by tracking them, generating "
 "plannings, etc..."
 msgstr ""
-"Pomůže vám řídit projekty a úkoly jejich sledováním, generováním plánů, aj."
+"Pomůže vám spravovat projekty a úkoly jejich sledováním, generováním plánů, "
+"apod."
 
 #. module: base
 #: model:ir.module.module,summary:base.module_point_of_sale
@@ -157,7 +158,7 @@ msgstr ""
 #. module: base
 #: help:res.partner,employee:0
 msgid "Check this box if this contact is an Employee."
-msgstr "Zaškrtněte toto pole, pokud je kontakt zaměstnancem."
+msgstr "Zaškrtněte toto pole, pokud je kontakt zaměstnanec."
 
 #. module: base
 #: help:ir.model.fields,domain:0
@@ -11055,7 +11056,7 @@ msgstr "Úkoly"
 #. module: base
 #: model:ir.module.module,shortdesc:base.module_product_visible_discount
 msgid "Prices Visible Discounts"
-msgstr "Zobrazení slevy u ceny"
+msgstr ""
 
 #. module: base
 #: field:ir.attachment,datas:0
index 14414ec..c689667 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-20 05:33+0000\n"
-"X-Generator: Launchpad (build 16967)\n"
+"X-Launchpad-Export-Date: 2014-02-22 06:24+0000\n"
+"X-Generator: Launchpad (build 16926)\n"
 
 #. module: base
 #: model:ir.module.module,description:base.module_account_check_writing
index 1e0a1c5..b7edb65 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-20 05:35+0000\n"
-"X-Generator: Launchpad (build 16967)\n"
+"X-Launchpad-Export-Date: 2014-02-22 06:26+0000\n"
+"X-Generator: Launchpad (build 16926)\n"
 
 #. module: base
 #: model:ir.module.module,description:base.module_account_check_writing
index 2428ce6..4e3ca23 100644 (file)
@@ -12,8 +12,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-20 05:35+0000\n"
-"X-Generator: Launchpad (build 16967)\n"
+"X-Launchpad-Export-Date: 2014-02-22 06:26+0000\n"
+"X-Generator: Launchpad (build 16926)\n"
 "X-Poedit-Country: GREECE\n"
 "X-Poedit-Language: Greek\n"
 "X-Poedit-SourceCharset: utf-8\n"
index 3ac3d49..2d994f9 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-20 05:44+0000\n"
-"X-Generator: Launchpad (build 16967)\n"
+"X-Launchpad-Export-Date: 2014-02-22 06:36+0000\n"
+"X-Generator: Launchpad (build 16926)\n"
 
 #. module: base
 #: model:ir.module.module,description:base.module_account_check_writing
index 3289f1a..1742dcd 100644 (file)
@@ -13,8 +13,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-20 05:41+0000\n"
-"X-Generator: Launchpad (build 16967)\n"
+"X-Launchpad-Export-Date: 2014-02-22 06:33+0000\n"
+"X-Generator: Launchpad (build 16926)\n"
 
 #. module: base
 #: model:ir.module.module,description:base.module_account_check_writing
index ff156da..566df65 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-20 05:43+0000\n"
-"X-Generator: Launchpad (build 16967)\n"
+"X-Launchpad-Export-Date: 2014-02-22 06:35+0000\n"
+"X-Generator: Launchpad (build 16926)\n"
 
 #. module: base
 #: model:ir.module.module,description:base.module_account_check_writing
index 4d8aa3b..31a6b94 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-20 05:45+0000\n"
-"X-Generator: Launchpad (build 16967)\n"
+"X-Launchpad-Export-Date: 2014-02-22 06:37+0000\n"
+"X-Generator: Launchpad (build 16926)\n"
 
 #. module: base
 #: model:ir.module.module,description:base.module_account_check_writing
index e5fb10c..f9fcdca 100644 (file)
@@ -13,8 +13,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-20 05:44+0000\n"
-"X-Generator: Launchpad (build 16967)\n"
+"X-Launchpad-Export-Date: 2014-02-22 06:36+0000\n"
+"X-Generator: Launchpad (build 16926)\n"
 
 #. module: base
 #: model:ir.module.module,description:base.module_account_check_writing
index ff0e905..11a0d4a 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-20 05:45+0000\n"
-"X-Generator: Launchpad (build 16967)\n"
+"X-Launchpad-Export-Date: 2014-02-22 06:37+0000\n"
+"X-Generator: Launchpad (build 16926)\n"
 "Language: \n"
 
 #. module: base
index c95ba0f..ea34722 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-20 05:44+0000\n"
-"X-Generator: Launchpad (build 16967)\n"
+"X-Launchpad-Export-Date: 2014-02-22 06:36+0000\n"
+"X-Generator: Launchpad (build 16926)\n"
 
 #. module: base
 #: model:ir.module.module,description:base.module_account_check_writing
index 6126d7c..186faa9 100644 (file)
@@ -13,8 +13,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-20 05:46+0000\n"
-"X-Generator: Launchpad (build 16967)\n"
+"X-Launchpad-Export-Date: 2014-02-22 06:38+0000\n"
+"X-Generator: Launchpad (build 16926)\n"
 
 #. module: base
 #: model:ir.module.module,description:base.module_account_check_writing
index 332d738..d89de25 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-20 05:46+0000\n"
-"X-Generator: Launchpad (build 16967)\n"
+"X-Launchpad-Export-Date: 2014-02-22 06:38+0000\n"
+"X-Generator: Launchpad (build 16926)\n"
 
 #. module: base
 #: model:ir.module.module,description:base.module_account_check_writing
index cbdab27..a6f2ee6 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-20 05:46+0000\n"
-"X-Generator: Launchpad (build 16967)\n"
+"X-Launchpad-Export-Date: 2014-02-22 06:38+0000\n"
+"X-Generator: Launchpad (build 16926)\n"
 
 #. module: base
 #: model:ir.module.module,description:base.module_account_check_writing
index 15260ad..d7e9041 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-20 05:43+0000\n"
-"X-Generator: Launchpad (build 16967)\n"
+"X-Launchpad-Export-Date: 2014-02-22 06:35+0000\n"
+"X-Generator: Launchpad (build 16926)\n"
 
 #. module: base
 #: model:ir.module.module,description:base.module_account_check_writing
index 1192725..4c01f79 100644 (file)
@@ -13,8 +13,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-20 05:33+0000\n"
-"X-Generator: Launchpad (build 16967)\n"
+"X-Launchpad-Export-Date: 2014-02-22 06:24+0000\n"
+"X-Generator: Launchpad (build 16926)\n"
 
 #. module: base
 #: model:ir.module.module,description:base.module_account_check_writing
index 6fabc95..0be7283 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-20 05:31+0000\n"
-"X-Generator: Launchpad (build 16967)\n"
+"X-Launchpad-Export-Date: 2014-02-22 06:23+0000\n"
+"X-Generator: Launchpad (build 16926)\n"
 
 #. module: base
 #: model:ir.module.module,description:base.module_account_check_writing
index 1b0e025..8e74b17 100644 (file)
@@ -9,8 +9,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-20 05:39+0000\n"
-"X-Generator: Launchpad (build 16967)\n"
+"X-Launchpad-Export-Date: 2014-02-22 06:30+0000\n"
+"X-Generator: Launchpad (build 16926)\n"
 "X-Poedit-Country: IRAN, ISLAMIC REPUBLIC OF\n"
 "X-Poedit-Language: Persian\n"
 
index af0a0e5..71f3a31 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-20 05:47+0000\n"
-"X-Generator: Launchpad (build 16967)\n"
+"X-Launchpad-Export-Date: 2014-02-22 06:38+0000\n"
+"X-Generator: Launchpad (build 16926)\n"
 
 #. module: base
 #: model:ir.module.module,description:base.module_account_check_writing
index 5646cff..baf4110 100644 (file)
@@ -13,8 +13,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-20 05:34+0000\n"
-"X-Generator: Launchpad (build 16967)\n"
+"X-Launchpad-Export-Date: 2014-02-22 06:25+0000\n"
+"X-Generator: Launchpad (build 16926)\n"
 
 #. module: base
 #: model:ir.module.module,description:base.module_account_check_writing
@@ -405,13 +405,6 @@ msgid ""
 "invoices from picking, OpenERP is able to add and compute the shipping "
 "line.\n"
 msgstr ""
-"\n"
-"Sallii toimitustapojen lisäämisen myyntitilauksille ja keräilyyn. \n"
-"==============================================================\n"
-"\n"
-"Voit määritellä oman huolitsijan ja toimitustaulukon hinnoille. Kun laskut "
-"luodaan \n"
-"keräilyssä, OpenERP lisää lähetysrivit ja laskee nille hinnat.\n"
 
 #. module: base
 #: code:addons/base/ir/ir_filters.py:80
@@ -557,7 +550,7 @@ msgstr ""
 #. module: base
 #: view:workflow.transition:0
 msgid "Workflow Transition"
-msgstr "Työnkulun eteneminen"
+msgstr ""
 
 #. module: base
 #: model:res.country,name:base.gf
@@ -606,20 +599,6 @@ msgid ""
 "* Use emails to automatically confirm and send acknowledgements for any "
 "event registration\n"
 msgstr ""
-"\n"
-"Tapahtumien organisointi ja hallinta.\n"
-"====================================\n"
-"\n"
-"Tapahtumamoduuli mahdollistaa tehokkaan tapahtumien organisoinnin ja niihin "
-"liittyvien \n"
-"töiden hallinnan: suunnittelun, rekisteröintien seurannan, osallistumisen "
-"jne. \n"
-"\n"
-"Pääominaisuudet\n"
-"------------\n"
-"* Hallitse tapahtumia ja rekisteröintejä\n"
-"* Käytä sähköpostia automatisoimaan vahvistuksia ja lähettämään kuittaus "
-"jokaisesta rekisteröitymisestä.\n"
 
 #. module: base
 #: selection:base.language.install,lang:0
@@ -1637,11 +1616,6 @@ msgid ""
 "=============\n"
 "    "
 msgstr ""
-"\n"
-"Tämä moduuli lisää palautevalikon ja toimii jos Palauteportaali on "
-"asennettu. \n"
-"=======================================================================\n"
-"    "
 
 #. module: base
 #: model:ir.actions.act_window,help:base.action_res_partner_bank_account_form
@@ -1841,7 +1815,7 @@ msgstr ""
 #. module: base
 #: model:ir.module.module,shortdesc:base.module_portal_project_issue
 msgid "Portal Issue"
-msgstr "Portaaliongelma"
+msgstr "Porttaaliongelma"
 
 #. module: base
 #: model:ir.ui.menu,name:base.menu_tools
@@ -1976,7 +1950,7 @@ msgstr "Alankomaat"
 #. module: base
 #: model:ir.module.module,shortdesc:base.module_portal_event
 msgid "Portal Event"
-msgstr "Portaalitapahtuma"
+msgstr "Porttaalitapahtuma"
 
 #. module: base
 #: selection:ir.translation,state:0
@@ -6190,7 +6164,7 @@ msgstr "Ryhmän nimi ei voi alkaa \"-\""
 #: view:ir.module.module:0
 #: model:ir.ui.menu,name:base.module_mi
 msgid "Apps"
-msgstr "Sovelluskauppa"
+msgstr "Sovellukset"
 
 #. module: base
 #: view:ir.ui.view_sc:0
@@ -7752,7 +7726,7 @@ msgstr "Tämä ikkuna"
 #. module: base
 #: model:ir.module.module,shortdesc:base.module_portal_anonymous
 msgid "Anonymous portal"
-msgstr "Anonyymiportaali"
+msgstr "Yleinen porttaali"
 
 #. module: base
 #: field:base.language.export,format:0
@@ -7810,7 +7784,7 @@ msgstr "Salasana"
 #. module: base
 #: model:ir.module.module,shortdesc:base.module_portal_claim
 msgid "Portal Claim"
-msgstr "Palauteportaali"
+msgstr "Reklmaatioporttaali"
 
 #. module: base
 #: model:ir.module.module,shortdesc:base.module_l10n_pe
@@ -7863,7 +7837,7 @@ msgstr "RML sisäinen ylätunniste"
 #. module: base
 #: field:ir.actions.act_window,search_view_id:0
 msgid "Search View Ref."
-msgstr "Hae näytettävä referenssi"
+msgstr "Hae näytettävä viite"
 
 #. module: base
 #: help:res.users,partner_id:0
@@ -8055,7 +8029,7 @@ msgstr "Liike- ja analyyttinen kirjanpito"
 #. module: base
 #: model:ir.module.module,shortdesc:base.module_portal_project
 msgid "Portal Project"
-msgstr "Portaaliprojekti"
+msgstr "Porttaaliprojekti"
 
 #. module: base
 #: model:res.country,name:base.cc
@@ -8564,7 +8538,7 @@ msgstr "Hongkong"
 #. module: base
 #: model:ir.module.module,shortdesc:base.module_portal_sale
 msgid "Portal Sale"
-msgstr "Myyntiportaali"
+msgstr "Myyntiporttaali"
 
 #. module: base
 #: field:ir.default,ref_id:0
@@ -8688,7 +8662,7 @@ msgstr "Alavalikot"
 #. module: base
 #: report:ir.module.reference:0
 msgid "Introspection report on objects"
-msgstr "Moduulin tekninen opas"
+msgstr "Introspektioraportti objekteista"
 
 #. module: base
 #: model:ir.module.module,shortdesc:base.module_web_analytics
@@ -8840,7 +8814,7 @@ msgstr ""
 #. module: base
 #: model:ir.ui.menu,name:base.menu_view_base_module_update
 msgid "Update Modules List"
-msgstr "Päivitä moduulilista"
+msgstr "Päivitä lista moduuleista"
 
 #. module: base
 #: code:addons/base/module/module.py:359
@@ -10047,7 +10021,7 @@ msgstr "Kenttien kuvaukset"
 #. module: base
 #: model:ir.module.module,shortdesc:base.module_analytic_contract_hr_expense
 msgid "Contracts Management: hr_expense link"
-msgstr "Sopimushallinat:  hr_expense link"
+msgstr "Sopimushallint:  hr_expense link"
 
 #. module: base
 #: view:ir.attachment:0
@@ -10309,7 +10283,7 @@ msgstr "Väliyksikkö"
 #. module: base
 #: model:ir.module.module,shortdesc:base.module_portal_stock
 msgid "Portal Stock"
-msgstr "Portaalivarasto"
+msgstr "Porttaalivarasto"
 
 #. module: base
 #: field:workflow.activity,kind:0
@@ -10377,7 +10351,7 @@ msgstr "Kohdetietueen ID tietokannassa"
 #. module: base
 #: model:ir.module.module,shortdesc:base.module_account_analytic_analysis
 msgid "Contracts Management"
-msgstr "Sopimushallinta"
+msgstr "Sopimustenhallinta"
 
 #. module: base
 #: selection:base.language.install,lang:0
@@ -10481,7 +10455,7 @@ msgstr "Moniyritys"
 #: model:ir.module.category,name:base.module_category_portal
 #: model:ir.module.module,shortdesc:base.module_portal
 msgid "Portal"
-msgstr "Portaali"
+msgstr "Porttaali"
 
 #. module: base
 #: selection:ir.translation,state:0
@@ -10682,7 +10656,7 @@ msgstr "Tehtävät"
 #. module: base
 #: model:ir.module.module,shortdesc:base.module_portal_hr_employees
 msgid "Portal HR employees"
-msgstr "Henkilöstöhallinnon työntekijäportaali"
+msgstr "Henkilöstöhallinnon työntekijäporttaali"
 
 #. module: base
 #: selection:base.language.install,lang:0
@@ -12163,7 +12137,7 @@ msgstr "Menetelmälle välitettävät argumentit, esim. (uid,...)."
 #. module: base
 #: report:ir.module.reference:0
 msgid "Reference Guide"
-msgstr "Tekninen opas"
+msgstr "Referenssiopaste"
 
 #. module: base
 #: model:ir.model,name:base.model_res_partner
@@ -12621,7 +12595,7 @@ msgstr "Malediivit"
 #. module: base
 #: model:ir.module.module,shortdesc:base.module_portal_crm
 msgid "Portal CRM"
-msgstr "CRM-portaali"
+msgstr "CRM-porttaali"
 
 #. module: base
 #: model:ir.ui.menu,name:base.next_id_4
@@ -14904,7 +14878,7 @@ msgstr "Bulgaria / български език"
 #. module: base
 #: model:ir.ui.menu,name:base.menu_aftersale
 msgid "After-Sale Services"
-msgstr "Asiakaspalvelut"
+msgstr "Jälkimarkkinapalvelut"
 
 #. module: base
 #: field:base.language.import,code:0
@@ -15649,7 +15623,7 @@ msgstr ""
 #: model:ir.actions.act_window,name:base.open_module_tree
 #: model:ir.ui.menu,name:base.menu_module_tree
 msgid "Installed Modules"
-msgstr "Asenna moduulit"
+msgstr "Asennetut moduulit"
 
 #. module: base
 #: code:addons/base/res/res_users.py:170
index a7cb0c9..5c779ab 100644 (file)
@@ -13,8 +13,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-20 05:34+0000\n"
-"X-Generator: Launchpad (build 16967)\n"
+"X-Launchpad-Export-Date: 2014-02-22 06:25+0000\n"
+"X-Generator: Launchpad (build 16926)\n"
 
 #. module: base
 #: model:ir.module.module,description:base.module_account_check_writing
index c132e85..73af473 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-20 05:44+0000\n"
-"X-Generator: Launchpad (build 16967)\n"
+"X-Launchpad-Export-Date: 2014-02-22 06:36+0000\n"
+"X-Generator: Launchpad (build 16926)\n"
 
 #. module: base
 #: model:ir.module.module,description:base.module_account_check_writing
@@ -29,7 +29,7 @@ msgstr ""
 #. module: base
 #: model:res.country,name:base.sh
 msgid "Saint Helena"
-msgstr "Sainte Hélène"
+msgstr ""
 
 #. module: base
 #: view:ir.actions.report.xml:0
@@ -39,7 +39,7 @@ msgstr ""
 #. module: base
 #: selection:ir.property,type:0
 msgid "DateTime"
-msgstr "Date et heure"
+msgstr ""
 
 #. module: base
 #: code:addons/fields.py:652
@@ -68,7 +68,7 @@ msgstr ""
 #. module: base
 #: selection:base.language.install,lang:0
 msgid "Hungarian / Magyar"
-msgstr "Hongrois / Magyar"
+msgstr ""
 
 #. module: base
 #: selection:base.language.install,lang:0
@@ -81,8 +81,6 @@ msgid ""
 "Helps you manage your projects and tasks by tracking them, generating "
 "plannings, etc..."
 msgstr ""
-"Vous aide à gérer vos projets et tâches, en assurant leur suivi, en générant "
-"des planifications, etc."
 
 #. module: base
 #: model:ir.module.module,summary:base.module_point_of_sale
@@ -223,7 +221,7 @@ msgstr ""
 #. module: base
 #: model:res.country,name:base.sz
 msgid "Swaziland"
-msgstr "Swaziland"
+msgstr ""
 
 #. module: base
 #: code:addons/orm.py:4485
@@ -354,7 +352,7 @@ msgstr ""
 #. module: base
 #: model:ir.module.category,name:base.module_category_customer_relationship_management
 msgid "Customer Relationship Management"
-msgstr "Gestion de la relation client (CRM)"
+msgstr ""
 
 #. module: base
 #: model:ir.module.module,description:base.module_delivery
@@ -391,14 +389,14 @@ msgstr ""
 #. module: base
 #: field:res.partner,credit_limit:0
 msgid "Credit Limit"
-msgstr "Limite de crédit"
+msgstr ""
 
 #. module: base
 #: field:ir.model.constraint,date_update:0
 #: field:ir.model.data,date_update:0
 #: field:ir.model.relation,date_update:0
 msgid "Update Date"
-msgstr "Mettre à jour la date"
+msgstr ""
 
 #. module: base
 #: model:ir.module.module,shortdesc:base.module_base_action_rule
@@ -409,12 +407,12 @@ msgstr ""
 #: view:ir.attachment:0
 #: field:ir.attachment,create_uid:0
 msgid "Owner"
-msgstr "Propriétaire"
+msgstr ""
 
 #. module: base
 #: view:ir.actions.act_window:0
 msgid "Source Object"
-msgstr "Objet source"
+msgstr ""
 
 #. module: base
 #: model:res.partner.bank.type,format_layout:base.bank_normal
@@ -436,7 +434,7 @@ msgstr ""
 #: field:ir.model.access,group_id:0
 #: view:res.groups:0
 msgid "Group"
-msgstr "Groupe"
+msgstr ""
 
 #. module: base
 #: constraint:res.lang:0
@@ -444,9 +442,6 @@ msgid ""
 "Invalid date/time format directive specified. Please refer to the list of "
 "allowed directives, displayed when you edit a language."
 msgstr ""
-"Vous avez spécifié une directive de format date/temps non valide. Veuillez "
-"vous référer à la liste des directives autorisées, qui s'affiche lorsque "
-"vous modifiez une langue."
 
 #. module: base
 #: code:addons/orm.py:4153
@@ -560,19 +555,6 @@ msgid ""
 "* Use emails to automatically confirm and send acknowledgements for any "
 "event registration\n"
 msgstr ""
-"\n"
-"Gestion et organisation d'événements\n"
-"====================================\n"
-"\n"
-"Le module 'Événement' vous permet d'organiser efficacement des événements et "
-"toutes les tâches liées : planification, suivi des inscriptions, des "
-"présences, etc.\n"
-"\n"
-"Fonctionnalités clés\n"
-"--------------------\n"
-"* Gestion des événements et des inscriptions\n"
-"* Utilisation d'e-mails pour automatiquement confirmer et envoyer des "
-"accusés de réception pour chaque inscription à un événement\n"
 
 #. module: base
 #: selection:base.language.install,lang:0
@@ -585,8 +567,6 @@ msgid ""
 "If you check this, then the second time the user prints with same attachment "
 "name, it returns the previous report."
 msgstr ""
-"Si vous cochez ceci, alors la seconde fois que l'utilisateur imprimera avec "
-"le même nom de pièce jointe, cela retournera le rapport stocké"
 
 #. module: base
 #: model:ir.module.module,description:base.module_mrp_byproduct
@@ -617,7 +597,7 @@ msgstr ""
 #. module: base
 #: model:ir.module.module,shortdesc:base.module_hr_timesheet_invoice
 msgid "Invoice on Timesheets"
-msgstr "Facture sur les feuilles de temps"
+msgstr ""
 
 #. module: base
 #: view:base.module.upgrade:0
@@ -633,12 +613,12 @@ msgstr ""
 #. module: base
 #: field:res.country,name:0
 msgid "Country Name"
-msgstr "Nom du pays"
+msgstr ""
 
 #. module: base
 #: model:res.country,name:base.co
 msgid "Colombia"
-msgstr "Colombie"
+msgstr ""
 
 #. module: base
 #: model:res.partner.title,name:base.res_partner_title_mister
@@ -660,7 +640,7 @@ msgstr ""
 #. module: base
 #: view:res.partner:0
 msgid "Sales & Purchases"
-msgstr "Achats et ventes"
+msgstr ""
 
 #. module: base
 #: view:ir.translation:0
@@ -741,33 +721,6 @@ msgid ""
 "module named account_voucher.\n"
 "    "
 msgstr ""
-"\n"
-"Comptabilité et gestion financière\n"
-"==================================\n"
-"\n"
-"Le module de comptabilité et de finance couvre :\n"
-"------------------------------------------------\n"
-"    * Comptabilité générale\n"
-"    * Comptabilité de coût / comptabilité analytique\n"
-"    * Comptabilité de tiers\n"
-"    * Gestion des taxes\n"
-"    * Budgets\n"
-"    * Factures clients et fournisseurs\n"
-"    * Relevés bancaires\n"
-"    * Réconciliations par partenaire\n"
-"\n"
-"Il créé également un tableau de bord pour les comptables qui inclut :\n"
-"---------------------------------------------------------------------\n"
-"    * Une liste des factures clients à approuver\n"
-"    * L'analyse de la société\n"
-"    * Un graphe de la trésorerie\n"
-"\n"
-"Les processus tels que le maintien de la comptabilité générale se fait par "
-"le biais des revues financières définies (les lignes d'écriture à regrouper "
-"le sont à travers un journal)\n"
-"pour un exercice donné et pour la préparation des reçus il ya un module "
-"nommé account_voucher.\n"
-"    "
 
 #. module: base
 #: view:ir.model:0
@@ -810,7 +763,7 @@ msgstr ""
 #. module: base
 #: model:res.country,name:base.jo
 msgid "Jordan"
-msgstr "Jordanie"
+msgstr ""
 
 #. module: base
 #: model:ir.module.module,shortdesc:base.module_l10n_hr
@@ -835,7 +788,7 @@ msgstr ""
 #. module: base
 #: sql_constraint:res.company:0
 msgid "The company name must be unique !"
-msgstr "Le nom de la société doit être unique !"
+msgstr ""
 
 #. module: base
 #: model:ir.ui.menu,name:base.menu_base_action_rule_admin
@@ -867,10 +820,6 @@ msgid ""
 "invoice, then `object.invoice_address_id.mobile` is the field which gives "
 "the correct mobile number"
 msgstr ""
-"Fournit les champs qui seront utilisés pour récupérer le numéro du "
-"cellulaire. Exemple: vous sélectionnez une facture, alors, "
-"`object.invoice_address_id.mobile` est le champ qui représente le numéro du "
-"cellulaire correct."
 
 #. module: base
 #: view:ir.mail_server:0
@@ -891,7 +840,7 @@ msgstr ""
 #: field:base.language.export,name:0
 #: field:ir.attachment,datas_fname:0
 msgid "File Name"
-msgstr "Nom du fichier"
+msgstr ""
 
 #. module: base
 #: model:res.country,name:base.rs
@@ -942,33 +891,6 @@ msgid ""
 "also possible in order to automatically create a meeting when a holiday "
 "request is accepted by setting up a type of meeting in Leave Type.\n"
 msgstr ""
-"\n"
-"Gère les absences et les demandes de congés\n"
-"===========================================\n"
-"\n"
-"Cette application contrôle la programmation des congés de votre société. Il "
-"permet aux employés de faire des demandes de congés. Ensuite, les managers "
-"peuvent examiner les demandes et les approuver ou les rejeter. De cette "
-"façon, vous pouvez contrôler la planification de l'ensemble des congés de "
-"votre entreprise ou de votre département.\n"
-"\n"
-"Vous pouvez configurer plusieurs sortes d'absences (maladie, congés payés, "
-"congés sans soldes…) et allouer rapidement ces absences à un employé ou un "
-"département en utilisant les demandes de congés. Un employé peut aussi faire "
-"une demande de congés pour plus de jours en ajoutant une allocation. Cela va "
-"augmenter le total des jours disponibles pour ce type de congés (si la "
-"demande est acceptée).\n"
-"\n"
-"Vous pouvez suivre les absences de différentes façons grâce aux rapports "
-"suivants : \n"
-"\n"
-"* Résumé des absences\n"
-"* Absences par département\n"
-"* Analyse des absences\n"
-"\n"
-"Une synchronisation avec les agendas internes (Réunions du module CRM) est "
-"aussi possible dans le but de créer automatiquement une réunion quand une "
-"demande de congés est accepté en ajoutant une type de réunion Absence.\n"
 
 #. module: base
 #: selection:base.language.install,lang:0
@@ -978,7 +900,7 @@ msgstr ""
 #. module: base
 #: model:ir.ui.menu,name:base.menu_crm_config_opportunity
 msgid "Opportunities"
-msgstr "Opportunités"
+msgstr ""
 
 #. module: base
 #: model:ir.model,name:base.model_base_language_export
@@ -988,7 +910,7 @@ msgstr ""
 #. module: base
 #: model:res.country,name:base.pg
 msgid "Papua New Guinea"
-msgstr "Papouasie-Nouvelle-Guinée"
+msgstr ""
 
 #. module: base
 #: help:ir.actions.report.xml,report_type:0
@@ -1019,7 +941,7 @@ msgstr ""
 #. module: base
 #: model:res.country,name:base.zw
 msgid "Zimbabwe"
-msgstr "Zimbabwe"
+msgstr ""
 
 #. module: base
 #: help:ir.model.constraint,type:0
@@ -1035,7 +957,7 @@ msgstr ""
 #. module: base
 #: model:res.country,name:base.es
 msgid "Spain"
-msgstr "Espagne"
+msgstr ""
 
 #. module: base
 #: help:ir.actions.act_window,domain:0
@@ -1056,17 +978,17 @@ msgstr ""
 #. module: base
 #: field:res.partner,mobile:0
 msgid "Mobile"
-msgstr "Cellulaire"
+msgstr ""
 
 #. module: base
 #: model:res.country,name:base.om
 msgid "Oman"
-msgstr "Oman"
+msgstr ""
 
 #. module: base
 #: model:ir.module.module,shortdesc:base.module_mrp
 msgid "MRP"
-msgstr "MRP - PBM"
+msgstr ""
 
 #. module: base
 #: model:ir.module.module,description:base.module_hr_attendance
@@ -1104,12 +1026,12 @@ msgstr ""
 #: model:ir.actions.act_window,name:base.act_menu_create
 #: view:wizard.ir.model.menu.create:0
 msgid "Create Menu"
-msgstr "Créer un menu"
+msgstr ""
 
 #. module: base
 #: model:res.country,name:base.in
 msgid "India"
-msgstr "Inde"
+msgstr ""
 
 #. module: base
 #: model:ir.actions.act_window,name:base.res_request_link-act
@@ -1125,7 +1047,7 @@ msgstr ""
 #. module: base
 #: model:ir.module.module,shortdesc:base.module_fleet
 msgid "Fleet Management"
-msgstr "Gestion de flotte"
+msgstr ""
 
 #. module: base
 #: help:ir.server.object.lines,value:0
@@ -1185,36 +1107,6 @@ msgid ""
 "* Planned Revenue by Stage and User (graph)\n"
 "* Opportunities by Stage (graph)\n"
 msgstr ""
-"\n"
-"Le module OpenERP de gestion de la relation client (CRM)\n"
-"=============================================\n"
-"\n"
-"Cette application permet aux utilisateurs de gérer efficacement et "
-"intelligemment leurs pistes, opportunités, réunions et appels "
-"téléphoniques.\n"
-"\n"
-"Elle gère les tâches clés comme la communication, l'identification, les "
-"assignations, les résolutions et les notifications.\n"
-"\n"
-"OpenERP assure que toutes les demandes sont suivis par les utilisateurs, les "
-"clients et les fournisseurs. Il permet d'envoyer automatiquement des "
-"rappels, d'escalader des requêtes, de lancer des actions spécifiques et de "
-"nombreuses autres selon les règles de l'entreprise.\n"
-"\n"
-"Le grand avantage de ce système est que les utilisateurs n'ont rien à faire "
-"de spécial. Le module CRM dispose d'une passerelle de courriel permettant de "
-"synchroniser les courriels reçus et OpenERP. De cette façon, les "
-"utilisateurs peuvent simplement envoyer des courriels au système de suivi "
-"des demandes.\n"
-"\n"
-"OpenERP s'occupera de remercier les utilisateurs de leur message, de diriger "
-"cette demande à l'équipe appropriée et de s'assurer que toute les "
-"communications futures seront rangées à la bonne place.\n"
-"\n"
-"\n"
-"Le tableau bord de cette application inclus:\n"
-"* les revenus prévus par étape de vente et par utilisateur (graphique);\n"
-"* les opportunités par étape de vente (graphique).\n"
 
 #. module: base
 #: selection:base.language.export,format:0
@@ -1349,17 +1241,17 @@ msgstr ""
 #: selection:ir.actions.server,state:0
 #: selection:workflow.activity,kind:0
 msgid "Dummy"
-msgstr "Factice"
+msgstr ""
 
 #. module: base
 #: constraint:ir.ui.view:0
 msgid "Invalid XML for View Architecture!"
-msgstr "XML invalide pour l'architecture de la vue"
+msgstr ""
 
 #. module: base
 #: model:res.country,name:base.ky
 msgid "Cayman Islands"
-msgstr "Îles Caïmans"
+msgstr ""
 
 #. module: base
 #: view:ir.rule:0
@@ -1395,7 +1287,7 @@ msgstr ""
 #. module: base
 #: selection:ir.property,type:0
 msgid "Char"
-msgstr "Caractère"
+msgstr ""
 
 #. module: base
 #: field:ir.module.category,visible:0
@@ -1473,9 +1365,6 @@ msgid ""
 "decimal number [00,53]. All days in a new year preceding the first Monday "
 "are considered to be in week 0."
 msgstr ""
-"%W - Numéro de semaine dans l'année (lundi est le premier jour de la "
-"semaine) en nombre décimal [00,53]. Tous les jours de la nouvelle année "
-"précédant le premier lundi sont considérés faisant partie de la semaine 0."
 
 #. module: base
 #: code:addons/base/module/wizard/base_language_install.py:53
@@ -1501,13 +1390,13 @@ msgstr ""
 #. module: base
 #: field:ir.actions.act_url,url:0
 msgid "Action URL"
-msgstr "URL de l'action"
+msgstr ""
 
 #. module: base
 #: field:base.module.import,module_name:0
 #: field:ir.module.module,shortdesc:0
 msgid "Module Name"
-msgstr "Nom du module"
+msgstr ""
 
 #. module: base
 #: model:res.country,name:base.mh
@@ -1534,7 +1423,7 @@ msgstr ""
 #: view:ir.ui.view:0
 #: selection:ir.ui.view,type:0
 msgid "Search"
-msgstr "Recherche"
+msgstr ""
 
 #. module: base
 #: code:addons/osv.py:154
@@ -1562,12 +1451,12 @@ msgstr ""
 #: code:addons/base/res/res_users.py:131
 #, python-format
 msgid "Operation Canceled"
-msgstr "Opération annulée"
+msgstr ""
 
 #. module: base
 #: model:ir.module.module,shortdesc:base.module_document
 msgid "Document Management System"
-msgstr "Système de gestion des documents"
+msgstr ""
 
 #. module: base
 #: model:ir.module.module,shortdesc:base.module_crm_claim
@@ -1610,7 +1499,7 @@ msgstr ""
 #: model:ir.module.category,name:base.module_category_purchase_management
 #: model:ir.ui.menu,name:base.menu_purchase_root
 msgid "Purchases"
-msgstr "Achats"
+msgstr ""
 
 #. module: base
 #: model:res.country,name:base.md
@@ -1635,12 +1524,12 @@ msgstr ""
 #. module: base
 #: view:ir.module.module:0
 msgid "Features"
-msgstr "Fonctionnalités"
+msgstr ""
 
 #. module: base
 #: view:ir.attachment:0
 msgid "Data"
-msgstr "Données"
+msgstr ""
 
 #. module: base
 #: model:ir.module.module,description:base.module_portal_claim
@@ -1708,7 +1597,7 @@ msgstr ""
 #: model:ir.module.category,name:base.module_category_social_network
 #: model:ir.module.module,shortdesc:base.module_mail
 msgid "Social Network"
-msgstr "Réseau social"
+msgstr ""
 
 #. module: base
 #: view:res.lang:0
@@ -12982,7 +12871,7 @@ msgstr ""
 #. module: base
 #: model:res.country,name:base.ao
 msgid "Angola"
-msgstr "Angola"
+msgstr ""
 
 #. module: base
 #: model:res.country,name:base.tf
index 68ab1d3..deab7d8 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-20 05:35+0000\n"
-"X-Generator: Launchpad (build 16967)\n"
+"X-Launchpad-Export-Date: 2014-02-22 06:26+0000\n"
+"X-Generator: Launchpad (build 16926)\n"
 
 #. module: base
 #: model:ir.module.module,description:base.module_account_check_writing
index cf0edaa..c12e821 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-20 05:35+0000\n"
-"X-Generator: Launchpad (build 16967)\n"
+"X-Launchpad-Export-Date: 2014-02-22 06:26+0000\n"
+"X-Generator: Launchpad (build 16926)\n"
 
 #. module: base
 #: model:ir.module.module,description:base.module_account_check_writing
index 70d012d..3b59cc7 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-20 05:35+0000\n"
-"X-Generator: Launchpad (build 16967)\n"
+"X-Launchpad-Export-Date: 2014-02-22 06:26+0000\n"
+"X-Generator: Launchpad (build 16926)\n"
 
 #. module: base
 #: model:ir.module.module,description:base.module_account_check_writing
index e790f6b..854c144 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-20 05:36+0000\n"
-"X-Generator: Launchpad (build 16967)\n"
+"X-Launchpad-Export-Date: 2014-02-22 06:27+0000\n"
+"X-Generator: Launchpad (build 16926)\n"
 
 #. module: base
 #: model:ir.module.module,description:base.module_account_check_writing
index 4462727..5879a1a 100644 (file)
@@ -13,8 +13,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-20 05:40+0000\n"
-"X-Generator: Launchpad (build 16967)\n"
+"X-Launchpad-Export-Date: 2014-02-22 06:32+0000\n"
+"X-Generator: Launchpad (build 16926)\n"
 "Language: hr\n"
 
 #. module: base
index b812e7e..a2b2b32 100644 (file)
@@ -13,8 +13,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-20 05:36+0000\n"
-"X-Generator: Launchpad (build 16967)\n"
+"X-Launchpad-Export-Date: 2014-02-22 06:27+0000\n"
+"X-Generator: Launchpad (build 16926)\n"
 
 #. module: base
 #: model:ir.module.module,description:base.module_account_check_writing
index 6275f58..6a2b22d 100644 (file)
@@ -9,8 +9,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-20 05:31+0000\n"
-"X-Generator: Launchpad (build 16967)\n"
+"X-Launchpad-Export-Date: 2014-02-22 06:22+0000\n"
+"X-Generator: Launchpad (build 16926)\n"
 
 #. module: base
 #: model:ir.module.module,description:base.module_account_check_writing
index f69a0ae..92763eb 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-20 05:36+0000\n"
-"X-Generator: Launchpad (build 16967)\n"
+"X-Launchpad-Export-Date: 2014-02-22 06:27+0000\n"
+"X-Generator: Launchpad (build 16926)\n"
 
 #. module: base
 #: model:ir.module.module,description:base.module_account_check_writing
@@ -211,15 +211,6 @@ msgid ""
 "revenue\n"
 "reports."
 msgstr ""
-"\n"
-"Bentuk tagihan anda dari entri Expenses, Timesheet.\n"
-"========================================================\n"
-"\n"
-"Modul untuk menerbitkan tagihan berbasis biaya (sdm, biaya, dsb).\n"
-"\n"
-"Anda dapat mendefinisikan daftar harga pada akun analitik, membuat laporan "
-"anggaran \n"
-"penghasilan."
 
 #. module: base
 #: code:addons/base/ir/ir_sequence.py:134
@@ -308,12 +299,6 @@ msgid ""
 "\n"
 "    "
 msgstr ""
-"\n"
-"Lokalisasi skema akunting dan pajak Chili.\n"
-"==============================================\n"
-"Plan contable chileno e impuestos de acuerdo a disposiciones vigentes\n"
-"\n"
-"    "
 
 #. module: base
 #: model:ir.module.module,shortdesc:base.module_sale
@@ -413,15 +398,6 @@ msgid ""
 "invoices from picking, OpenERP is able to add and compute the shipping "
 "line.\n"
 msgstr ""
-"\n"
-"Mengizinkan anda untuk menambahkan metode deliveri pada order penjualan dan "
-"pengambilan.\n"
-"==============================================================\n"
-"\n"
-"Anda dapat menentukan carrier sendiri dan metode antar untuk harga tersebut. "
-"Saat membuat\n"
-"tagihan dari pengantaran, OpenERP dapat menambah dan menghitung biaya "
-"pengiriman.\n"
 
 #. module: base
 #: code:addons/base/ir/ir_filters.py:80
index ee314ba..693c2c8 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-20 05:36+0000\n"
-"X-Generator: Launchpad (build 16967)\n"
+"X-Launchpad-Export-Date: 2014-02-22 06:27+0000\n"
+"X-Generator: Launchpad (build 16926)\n"
 
 #. module: base
 #: model:ir.module.module,description:base.module_account_check_writing
index d76609a..f99d805 100644 (file)
@@ -13,8 +13,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-20 05:36+0000\n"
-"X-Generator: Launchpad (build 16967)\n"
+"X-Launchpad-Export-Date: 2014-02-22 06:28+0000\n"
+"X-Generator: Launchpad (build 16926)\n"
 
 #. module: base
 #: model:ir.module.module,description:base.module_account_check_writing
index 03850c5..7acfaa7 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-20 05:37+0000\n"
-"X-Generator: Launchpad (build 16967)\n"
+"X-Launchpad-Export-Date: 2014-02-22 06:28+0000\n"
+"X-Generator: Launchpad (build 16926)\n"
 
 #. module: base
 #: model:ir.module.module,description:base.module_account_check_writing
@@ -411,7 +411,7 @@ msgstr "与信限度"
 #: field:ir.model.data,date_update:0
 #: field:ir.model.relation,date_update:0
 msgid "Update Date"
-msgstr "更新日"
+msgstr "日付の更新"
 
 #. module: base
 #: model:ir.module.module,shortdesc:base.module_base_action_rule
@@ -3262,7 +3262,7 @@ msgstr "アルメニア"
 #. module: base
 #: model:ir.module.module,summary:base.module_hr_evaluation
 msgid "Periodical Evaluations, Appraisals, Surveys"
-msgstr "定期評価、査定、調査"
+msgstr ""
 
 #. module: base
 #: model:ir.actions.act_window,name:base.ir_property_form
@@ -4582,7 +4582,7 @@ msgstr "スペイン語(ホンジュラス)/ Español (HN)"
 #. module: base
 #: view:ir.sequence.type:0
 msgid "Sequence Type"
-msgstr "付番タイプ"
+msgstr "順序タイプ"
 
 #. module: base
 #: view:base.language.export:0
@@ -5141,7 +5141,7 @@ msgstr "銀行口座タイプ"
 #. module: base
 #: help:ir.sequence,suffix:0
 msgid "Suffix value of the record for the sequence"
-msgstr "この付番定義でレコードに適用するサフィックス値"
+msgstr "順序のためのレコードのサフィックス値"
 
 #. module: base
 #: help:ir.mail_server,smtp_user:0
@@ -5588,7 +5588,7 @@ msgstr "起動設定ウィザード"
 #. module: base
 #: model:ir.module.module,summary:base.module_mrp
 msgid "Manufacturing Orders, Bill of Materials, Routing"
-msgstr "製造オーダ、部品表、工順"
+msgstr ""
 
 #. module: base
 #: field:ir.attachment,name:0
@@ -6140,7 +6140,7 @@ msgstr "ショートカット"
 #. module: base
 #: field:ir.model.data,date_init:0
 msgid "Init Date"
-msgstr "作成日"
+msgstr "整数データ"
 
 #. module: base
 #: selection:base.language.install,lang:0
@@ -7630,7 +7630,7 @@ msgstr ""
 #. module: base
 #: help:ir.sequence,number_next:0
 msgid "Next number of this sequence"
-msgstr "この付番定義の次の番号"
+msgstr "この順序の次の番号"
 
 #. module: base
 #: view:res.partner:0
@@ -7954,7 +7954,7 @@ msgstr "カスタム項目"
 #. module: base
 #: model:ir.module.module,summary:base.module_account_accountant
 msgid "Financial and Analytic Accounting"
-msgstr "財務会計、分析会計"
+msgstr ""
 
 #. module: base
 #: model:ir.module.module,shortdesc:base.module_portal_project
@@ -8248,7 +8248,7 @@ msgstr ""
 #. module: base
 #: model:ir.module.module,summary:base.module_hr_recruitment
 msgid "Jobs, Recruitment, Applications, Job Interviews"
-msgstr "仕事、求人、応募、面接"
+msgstr ""
 
 #. module: base
 #: code:addons/base/module/module.py:539
@@ -8657,7 +8657,7 @@ msgstr "グループのユーザは自動的にグループを継承します。
 #. module: base
 #: model:ir.module.module,summary:base.module_note
 msgid "Sticky notes, Collaborative, Memos"
-msgstr "付箋、コラボレーション、メモ"
+msgstr ""
 
 #. module: base
 #: model:ir.module.module,shortdesc:base.module_hr_attendance
@@ -9991,7 +9991,7 @@ msgstr ""
 #. module: base
 #: model:ir.module.module,summary:base.module_hr_holidays
 msgid "Holidays, Allocation and Leave Requests"
-msgstr "休暇割当、申請・承認"
+msgstr ""
 
 #. module: base
 #: model:ir.module.module,description:base.module_web_hello
@@ -10135,7 +10135,7 @@ msgstr "発注分析計画"
 #: model:ir.actions.act_window,name:base.ir_sequence_type
 #: model:ir.ui.menu,name:base.menu_ir_sequence_type
 msgid "Sequence Codes"
-msgstr "付番コード"
+msgstr "順序コード"
 
 #. module: base
 #: selection:base.language.install,lang:0
@@ -10790,7 +10790,7 @@ msgstr "国の状態"
 #. module: base
 #: model:ir.ui.menu,name:base.next_id_5
 msgid "Sequences & Identifiers"
-msgstr "付番定義とID"
+msgstr "順序と識別子"
 
 #. module: base
 #: model:ir.module.module,description:base.module_l10n_th
@@ -10925,7 +10925,7 @@ msgstr "連絡先が会社の場合はチェックしてください。チェッ
 #. module: base
 #: view:ir.sequence.type:0
 msgid "Sequences Type"
-msgstr "付番タイプ"
+msgstr "順序タイプ"
 
 #. module: base
 #: view:res.partner:0
@@ -11282,7 +11282,7 @@ msgstr ""
 #: view:ir.sequence:0
 #: model:ir.ui.menu,name:base.menu_ir_sequence_form
 msgid "Sequences"
-msgstr "付番"
+msgstr "順序"
 
 #. module: base
 #: help:res.lang,code:0
@@ -11724,7 +11724,7 @@ msgstr "月:%(month)s"
 #: field:multi_company.default,sequence:0
 #: field:res.partner.bank,sequence:0
 msgid "Sequence"
-msgstr "付番"
+msgstr "順序"
 
 #. module: base
 #: model:res.country,name:base.tn
@@ -12190,7 +12190,7 @@ msgstr "ハード島とマクドナルド諸島"
 msgid ""
 "External Key/Identifier that can be used for data integration with third-"
 "party systems"
-msgstr "サードパーティシステムとのデータ統合のために利用する外部キー / ID"
+msgstr "サードパーティのシステムとのデータ統合のために利用する外部キー / 識別子"
 
 #. module: base
 #: field:ir.actions.act_window,view_id:0
@@ -12519,7 +12519,7 @@ msgstr "CRMポータル"
 #. module: base
 #: model:ir.ui.menu,name:base.next_id_4
 msgid "Low Level Objects"
-msgstr "低レベルオブジェクト"
+msgstr "低レベルのオブジェクト"
 
 #. module: base
 #: help:ir.values,model:0
@@ -12596,7 +12596,7 @@ msgstr ""
 #: view:ir.model.data:0
 #: model:ir.ui.menu,name:base.ir_model_data_menu
 msgid "External Identifiers"
-msgstr "外部ID"
+msgstr "外部識別子"
 
 #. module: base
 #: selection:base.language.install,lang:0
@@ -12898,7 +12898,7 @@ msgstr "ガボン"
 #. module: base
 #: model:ir.module.module,summary:base.module_stock
 msgid "Inventory, Logistic, Storage"
-msgstr "在庫、経路、保管場所"
+msgstr ""
 
 #. module: base
 #: view:ir.actions.act_window:0
@@ -13614,7 +13614,7 @@ msgstr ""
 #: view:ir.model.data:0
 #: field:ir.model.data,name:0
 msgid "External Identifier"
-msgstr "外部ID"
+msgstr "外部識別子"
 
 #. module: base
 #: model:ir.module.module,description:base.module_audittrail
@@ -14048,7 +14048,9 @@ msgid ""
 "Two sequence object implementations are offered: Standard and 'No gap'. The "
 "later is slower than the former but forbids any gap in the sequence (while "
 "they are possible in the former)."
-msgstr "「標準」と「ギャップなし」の2種類の付番定義が可能です。後者の場合、付番ごとにギャップを設けることができません。"
+msgstr ""
+"2つのシーケンスオブジェクトの実装が提供されます:標準と\"ギャップなし\"です。後者は前者よりも遅いですが、どんな順序のギャップを禁じます(前者は可能で"
+"す)。"
 
 #. module: base
 #: model:res.country,name:base.gn
@@ -14247,7 +14249,7 @@ msgstr "かつ"
 #: help:ir.values,res_id:0
 msgid ""
 "Database identifier of the record to which this applies. 0 = for all records"
-msgstr ""
+msgstr "これを適用するためのレコードのデータベース識別子。0 = 全てのレコードのため"
 
 #. module: base
 #: field:ir.model.fields,relation:0
@@ -14674,7 +14676,7 @@ msgstr "高度なレポート"
 #. module: base
 #: model:ir.module.module,summary:base.module_purchase
 msgid "Purchase Orders, Receptions, Supplier Invoices"
-msgstr "発注、入荷、仕入先請求"
+msgstr ""
 
 #. module: base
 #: model:ir.module.module,description:base.module_hr_payroll
@@ -14901,7 +14903,7 @@ msgstr "クック諸島"
 #. module: base
 #: field:ir.model.data,noupdate:0
 msgid "Non Updatable"
-msgstr "更新不可"
+msgstr "更新可能でない"
 
 #. module: base
 #: selection:base.language.install,lang:0
@@ -15309,7 +15311,7 @@ msgstr ""
 #. module: base
 #: help:ir.sequence,prefix:0
 msgid "Prefix value of the record for the sequence"
-msgstr "この付番定義でレコードに適用するプレフィックス値"
+msgstr "順序のためのレコードのプレフィックス値"
 
 #. module: base
 #: model:res.country,name:base.sc
@@ -15351,7 +15353,7 @@ msgstr ""
 #. module: base
 #: field:ir.model.data,complete_name:0
 msgid "Complete ID"
-msgstr "完全ID"
+msgstr "完了ID"
 
 #. module: base
 #: model:ir.module.module,description:base.module_stock
@@ -15445,7 +15447,7 @@ msgstr "製造プロセスを管理し、それらのプロセスのレポート
 #. module: base
 #: help:ir.sequence,number_increment:0
 msgid "The next number of the sequence will be incremented by this number"
-msgstr "付番毎にこの数値分だけ番号が増加します。"
+msgstr "順序の次の番号はこの数値だけ増加します。"
 
 #. module: base
 #: selection:workflow.activity,kind:0
index 837f751..a07e569 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-20 05:34+0000\n"
-"X-Generator: Launchpad (build 16967)\n"
+"X-Launchpad-Export-Date: 2014-02-22 06:25+0000\n"
+"X-Generator: Launchpad (build 16926)\n"
 
 #. module: base
 #: model:ir.module.module,description:base.module_account_check_writing
index 5592883..fd1401f 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-20 05:37+0000\n"
-"X-Generator: Launchpad (build 16967)\n"
+"X-Launchpad-Export-Date: 2014-02-22 06:28+0000\n"
+"X-Generator: Launchpad (build 16926)\n"
 
 #. module: base
 #: model:ir.module.module,description:base.module_account_check_writing
index 50fb6e3..68a67e8 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-20 05:37+0000\n"
-"X-Generator: Launchpad (build 16967)\n"
+"X-Launchpad-Export-Date: 2014-02-22 06:28+0000\n"
+"X-Generator: Launchpad (build 16926)\n"
 
 #. module: base
 #: model:ir.module.module,description:base.module_account_check_writing
index 55518a7..860fd21 100644 (file)
@@ -13,8 +13,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-20 05:38+0000\n"
-"X-Generator: Launchpad (build 16967)\n"
+"X-Launchpad-Export-Date: 2014-02-22 06:29+0000\n"
+"X-Generator: Launchpad (build 16926)\n"
 
 #. module: base
 #: model:ir.module.module,description:base.module_account_check_writing
index f64156a..7267dd9 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-20 05:37+0000\n"
-"X-Generator: Launchpad (build 16967)\n"
+"X-Launchpad-Export-Date: 2014-02-22 06:29+0000\n"
+"X-Generator: Launchpad (build 16926)\n"
 
 #. module: base
 #: model:ir.module.module,description:base.module_account_check_writing
index 46cfd2f..ca43ebc 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-20 05:38+0000\n"
-"X-Generator: Launchpad (build 16967)\n"
+"X-Launchpad-Export-Date: 2014-02-22 06:29+0000\n"
+"X-Generator: Launchpad (build 16926)\n"
 
 #. module: base
 #: model:ir.module.module,description:base.module_account_check_writing
index 1d69c95..2399a1f 100644 (file)
@@ -13,8 +13,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-20 05:38+0000\n"
-"X-Generator: Launchpad (build 16967)\n"
+"X-Launchpad-Export-Date: 2014-02-22 06:29+0000\n"
+"X-Generator: Launchpad (build 16926)\n"
 
 #. module: base
 #: model:ir.module.module,description:base.module_account_check_writing
index 066dfdb..24238f3 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-20 05:38+0000\n"
-"X-Generator: Launchpad (build 16967)\n"
+"X-Launchpad-Export-Date: 2014-02-22 06:29+0000\n"
+"X-Generator: Launchpad (build 16926)\n"
 
 #. module: base
 #: model:ir.module.module,description:base.module_account_check_writing
index 9950ea8..262497d 100644 (file)
@@ -13,8 +13,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-20 05:33+0000\n"
-"X-Generator: Launchpad (build 16967)\n"
+"X-Launchpad-Export-Date: 2014-02-22 06:24+0000\n"
+"X-Generator: Launchpad (build 16926)\n"
 
 #. module: base
 #: model:ir.module.module,description:base.module_account_check_writing
@@ -13429,7 +13429,7 @@ msgstr ""
 #. module: base
 #: selection:res.currency,position:0
 msgid "Before Amount"
-msgstr "Voor bedrag"
+msgstr "Voormalig bedrag"
 
 #. module: base
 #: field:res.request,act_from:0
index d8e2ab7..f8fd7bf 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-20 05:44+0000\n"
-"X-Generator: Launchpad (build 16967)\n"
+"X-Launchpad-Export-Date: 2014-02-22 06:36+0000\n"
+"X-Generator: Launchpad (build 16926)\n"
 
 #. module: base
 #: model:ir.module.module,description:base.module_account_check_writing
index bdfe417..743a7aa 100644 (file)
@@ -13,8 +13,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-20 05:39+0000\n"
-"X-Generator: Launchpad (build 16967)\n"
+"X-Launchpad-Export-Date: 2014-02-22 06:30+0000\n"
+"X-Generator: Launchpad (build 16926)\n"
 
 #. module: base
 #: model:ir.module.module,description:base.module_account_check_writing
index ac1ec23..0b8bb5e 100644 (file)
@@ -13,8 +13,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-20 05:39+0000\n"
-"X-Generator: Launchpad (build 16967)\n"
+"X-Launchpad-Export-Date: 2014-02-22 06:30+0000\n"
+"X-Generator: Launchpad (build 16926)\n"
 
 #. module: base
 #: model:ir.module.module,description:base.module_account_check_writing
index 0d5261a..005ec27 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-20 05:43+0000\n"
-"X-Generator: Launchpad (build 16967)\n"
+"X-Launchpad-Export-Date: 2014-02-22 06:35+0000\n"
+"X-Generator: Launchpad (build 16926)\n"
 
 #. module: base
 #: model:ir.module.module,description:base.module_account_check_writing
index f6afb07..e9a77c2 100644 (file)
@@ -13,8 +13,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-20 05:39+0000\n"
-"X-Generator: Launchpad (build 16967)\n"
+"X-Launchpad-Export-Date: 2014-02-22 06:31+0000\n"
+"X-Generator: Launchpad (build 16926)\n"
 
 #. module: base
 #: model:ir.module.module,description:base.module_account_check_writing
index dde0d09..59cab18 100644 (file)
@@ -13,8 +13,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-20 05:40+0000\n"
-"X-Generator: Launchpad (build 16967)\n"
+"X-Launchpad-Export-Date: 2014-02-22 06:31+0000\n"
+"X-Generator: Launchpad (build 16926)\n"
 
 #. module: base
 #: model:ir.module.module,description:base.module_account_check_writing
index fa23b9f..a4cb967 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-20 05:40+0000\n"
-"X-Generator: Launchpad (build 16967)\n"
+"X-Launchpad-Export-Date: 2014-02-22 06:32+0000\n"
+"X-Generator: Launchpad (build 16926)\n"
 
 #. module: base
 #: model:ir.module.module,description:base.module_account_check_writing
index 2ce1102..f86dbc7 100644 (file)
@@ -13,8 +13,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-20 05:41+0000\n"
-"X-Generator: Launchpad (build 16967)\n"
+"X-Launchpad-Export-Date: 2014-02-22 06:32+0000\n"
+"X-Generator: Launchpad (build 16926)\n"
 
 #. module: base
 #: model:ir.module.module,description:base.module_account_check_writing
index 7541898..9fb318a 100644 (file)
@@ -13,8 +13,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-20 05:30+0000\n"
-"X-Generator: Launchpad (build 16967)\n"
+"X-Launchpad-Export-Date: 2014-02-22 06:22+0000\n"
+"X-Generator: Launchpad (build 16926)\n"
 
 #. module: base
 #: model:ir.module.module,description:base.module_account_check_writing
index 61b34a2..7bae2e9 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-20 05:40+0000\n"
-"X-Generator: Launchpad (build 16967)\n"
+"X-Launchpad-Export-Date: 2014-02-22 06:31+0000\n"
+"X-Generator: Launchpad (build 16926)\n"
 
 #. module: base
 #: model:ir.module.module,description:base.module_account_check_writing
index 8c9348c..f307be9 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-20 05:47+0000\n"
-"X-Generator: Launchpad (build 16967)\n"
+"X-Launchpad-Export-Date: 2014-02-22 06:38+0000\n"
+"X-Generator: Launchpad (build 16926)\n"
 
 #. module: base
 #: model:ir.module.module,description:base.module_account_check_writing
index a8e01fb..765f5a2 100644 (file)
@@ -13,8 +13,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-20 05:41+0000\n"
-"X-Generator: Launchpad (build 16967)\n"
+"X-Launchpad-Export-Date: 2014-02-22 06:33+0000\n"
+"X-Generator: Launchpad (build 16926)\n"
 
 #. module: base
 #: model:ir.module.module,description:base.module_account_check_writing
index db7e38e..afd43cf 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-20 05:41+0000\n"
-"X-Generator: Launchpad (build 16967)\n"
+"X-Launchpad-Export-Date: 2014-02-22 06:33+0000\n"
+"X-Generator: Launchpad (build 16926)\n"
 
 #. module: base
 #: model:ir.module.module,description:base.module_account_check_writing
index afcd432..877e3c9 100644 (file)
@@ -13,8 +13,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-20 05:42+0000\n"
-"X-Generator: Launchpad (build 16967)\n"
+"X-Launchpad-Export-Date: 2014-02-22 06:33+0000\n"
+"X-Generator: Launchpad (build 16926)\n"
 
 #. module: base
 #: model:ir.module.module,description:base.module_account_check_writing
index 2411e61..e18e16a 100644 (file)
@@ -13,8 +13,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-20 05:42+0000\n"
-"X-Generator: Launchpad (build 16967)\n"
+"X-Launchpad-Export-Date: 2014-02-22 06:34+0000\n"
+"X-Generator: Launchpad (build 16926)\n"
 
 #. module: base
 #: model:ir.module.module,description:base.module_account_check_writing
index 5ec0276..a4c380e 100644 (file)
@@ -13,8 +13,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-20 05:42+0000\n"
-"X-Generator: Launchpad (build 16967)\n"
+"X-Launchpad-Export-Date: 2014-02-22 06:34+0000\n"
+"X-Generator: Launchpad (build 16926)\n"
 
 #. module: base
 #: model:ir.module.module,description:base.module_account_check_writing
index d18f9aa..0907705 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-20 05:42+0000\n"
-"X-Generator: Launchpad (build 16967)\n"
+"X-Launchpad-Export-Date: 2014-02-22 06:34+0000\n"
+"X-Generator: Launchpad (build 16926)\n"
 
 #. module: base
 #: model:ir.module.module,description:base.module_account_check_writing
index ae1c01c..a88ebdc 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-20 05:43+0000\n"
-"X-Generator: Launchpad (build 16967)\n"
+"X-Launchpad-Export-Date: 2014-02-22 06:34+0000\n"
+"X-Generator: Launchpad (build 16926)\n"
 
 #. module: base
 #: model:ir.module.module,description:base.module_account_check_writing
index 6ea18ad..e6dc69d 100644 (file)
@@ -13,8 +13,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-20 05:46+0000\n"
-"X-Generator: Launchpad (build 16967)\n"
+"X-Launchpad-Export-Date: 2014-02-22 06:37+0000\n"
+"X-Generator: Launchpad (build 16926)\n"
 
 #. module: base
 #: model:ir.module.module,description:base.module_account_check_writing
index 700bf5c..0d10f81 100644 (file)
@@ -14,8 +14,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-20 05:43+0000\n"
-"X-Generator: Launchpad (build 16967)\n"
+"X-Launchpad-Export-Date: 2014-02-22 06:35+0000\n"
+"X-Generator: Launchpad (build 16926)\n"
 
 #. module: base
 #: model:ir.module.module,description:base.module_account_check_writing
index 1b7ff71..0b50ad3 100644 (file)
@@ -13,8 +13,8 @@ msgstr ""
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2014-03-20 05:45+0000\n"
-"X-Generator: Launchpad (build 16967)\n"
+"X-Launchpad-Export-Date: 2014-02-22 06:37+0000\n"
+"X-Generator: Launchpad (build 16926)\n"
 
 #. module: base
 #: model:ir.module.module,description:base.module_account_check_writing
index 9aa1e7c..b3df5bc 100644 (file)
@@ -39,7 +39,6 @@ import ir_mail_server
 import ir_fields
 import ir_qweb
 import ir_http
-import ir_logging
 
 # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
 
index 7b0681f..9adbf2c 100644 (file)
@@ -135,42 +135,35 @@ class ir_actions_report_xml(osv.osv):
     _sequence = 'ir_actions_id_seq'
     _order = 'name'
     _columns = {
-        'type': fields.char('Action Type', size=32, required=True),
         'name': fields.char('Name', size=64, required=True, translate=True),
-
-        'model': fields.char('Model', required=True),
-        'report_type': fields.selection([('qweb-pdf', 'PDF'),
-                    ('qweb-html', 'HTML'),
-                    ('other', 'Other'),
-                    ('pdf', 'RML pdf (deprecated)'),
-                    ('sxw', 'RML sxw (deprecated)'),
-                    ('webkit', 'Webkit (deprecated)'),
-                    ], 'Report Type', required=True, help="PDF will use wkhtmltopdf to render html to pdf, HTML will directly show html, Other will force download the controller output keeping the MIME type."),
-        'report_name': fields.char('Controller Name', required=True, help="URL of the report will be /report/<controller name>/<ids>, the default controller also use this field to get the name of the qweb ir.ui.view to render. For RML reports, this is the LocalService name."),
+        'model': fields.char('Object', size=64, required=True),
+        'type': fields.char('Action Type', size=32, required=True),
+        'report_name': fields.char('Service Name', size=64, required=True),
+        'usage': fields.char('Action Usage', size=32),
+        'report_type': fields.char('Report Type', size=32, required=True, help="Report Type, e.g. pdf, html, raw, sxw, odt, html2html, mako2html, ..."),
         'groups_id': fields.many2many('res.groups', 'res_groups_report_rel', 'uid', 'gid', 'Groups'),
-
-        # options
         'multi': fields.boolean('On Multiple Doc.', help="If set to true, the action will not be displayed on the right toolbar of a form view."),
-        'attachment_use': fields.boolean('Reload from Attachment', help='If you check this, then the second time the user prints with same attachment name, it returns the previous report.'),
         'attachment': fields.char('Save as Attachment Prefix', size=128, help='This is the filename of the attachment used to store the printing result. Keep empty to not save the printed reports. You can use a python expression with the object and time variables.'),
+        'attachment_use': fields.boolean('Reload from Attachment', help='If you check this, then the second time the user prints with same attachment name, it returns the previous report.'),
+        'auto': fields.boolean('Custom Python Parser'),
 
-        # Deprecated rml stuff
-        'usage': fields.char('Action Usage', size=32),
         'header': fields.boolean('Add RML Header', help="Add or not the corporate RML header"),
-        'parser': fields.char('Parser Class'),
-        'auto': fields.boolean('Custom Python Parser'),
 
-        'report_xsl': fields.char('XSL Path'),
-        'report_xml': fields.char('XML Path'),
+        'report_xsl': fields.char('XSL Path', size=256),
+        'report_xml': fields.char('XML Path', size=256, help=''),
 
-        'report_rml': fields.char('Main Report File Path', help="The path to the main report file (depending on Report Type) or NULL if the content is in another data field"),
-        'report_file': fields.related('report_rml', type="char", required=False, readonly=False, string='Report File', help="The path to the main report file (depending on Report Type) or NULL if the content is in another field", store=True),
+        # Pending deprecation... to be replaced by report_file as this object will become the default report object (not so specific to RML anymore)
+        'report_rml': fields.char('Main Report File Path', size=256, help="The path to the main report file (depending on Report Type) or NULL if the content is in another data field"),
+        # temporary related field as report_rml is pending deprecation - this field will replace report_rml after v6.0
+        'report_file': fields.related('report_rml', type="char", size=256, required=False, readonly=False, string='Report File', help="The path to the main report file (depending on Report Type) or NULL if the content is in another field", store=True),
 
         'report_sxw': fields.function(_report_sxw, type='char', string='SXW Path'),
         'report_sxw_content_data': fields.binary('SXW Content'),
         'report_rml_content_data': fields.binary('RML Content'),
         'report_sxw_content': fields.function(_report_content, fnct_inv=_report_content_inv, type='binary', string='SXW Content',),
         'report_rml_content': fields.function(_report_content, fnct_inv=_report_content_inv, type='binary', string='RML Content'),
+
+        'parser': fields.char('Parser Class'),
     }
     _defaults = {
         'type': 'ir.actions.report.xml',
index 77d7eb2..26c08d4 100644 (file)
                     <group>
                         <group>
                             <field name="name"/>
-                            <field name="model"/>
-                            <field name="report_type"/>
                             <field name="report_name"/>
+                            <field name="model"/>
                         </group>
                         <group>
-                            <field name="multi"/>
-                            <field name="attachment_use"/>
-                            <field name="attachment"/>
+                            <field name="usage"/>
+                            <field name="report_type"/>
+                            <field name="report_file"/>
                         </group>
                     </group>
                     <notebook>
-                        <page string="Security">
-                            <field name="groups_id"/>
-                        </page>
-                        <page string="RML Configuration" attrs="{'invisible':[('report_type','not in',['pdf','sxw'])]}">
+                        <page string="Other Configuration">
                             <group>
                                 <group string="RML Report">
                                     <field name="header"/>
-                                    <field name="report_file"/>
-                                    <field name="auto"/>
-                                    <field name="parser"/>
-                                    <field name="usage"/>
                                 </group>
                                 <group string="XML Report">
                                     <field name="report_xsl"/>
                                     <field name="report_xml"/>
                                 </group>
+                                <group string="Attachments">
+                                    <field name="attachment"/>
+                                    <field name="attachment_use"/>
+                                </group>
+                                <group string="Miscellaneous">
+                                    <field name="multi"/>
+                                    <field name="auto"/>
+                                    <field name="parser"/>
+                                </group>
                             </group>
                         </page>
+                        <page string="Security">
+                            <field name="groups_id"/>
+                        </page>
                     </notebook>
                 </form>
             </field>
                         filter_domain="['|', '|', '|', '|', ('name','ilike',self), ('model','ilike',self), ('type','ilike',self), ('report_name','ilike',self), ('report_type','ilike',self)]"
                         string="Report"/>
                     <group expand="0" string="Group By" colspan="4">
-                        <filter string="Report Type" domain="[]" context="{'group_by':'report_type'}"/>
-                        <filter string="Report Model" domain="[]" context="{'group_by':'model'}"/>
+                        <filter string="Report Type" icon="terp-stock_symbol-selection" domain="[]" context="{'group_by':'report_type'}"/>
                     </group>
                 </search>
             </field>
index 992ac1b..6977692 100644 (file)
@@ -64,37 +64,19 @@ class ir_attachment(osv.osv):
                 data[attachment.id] = False
         return data
 
-    def _storage(self, cr, uid, context=None):
-        return self.pool['ir.config_parameter'].get_param(cr, SUPERUSER_ID, 'ir_attachment.location', 'file')
-
-    @tools.ormcache()
-    def _filestore(self, cr, uid, context=None):
-        return os.path.join(tools.config['data_dir'], 'filestore', cr.dbname)
-
     # 'data' field implementation
     def _full_path(self, cr, uid, location, path):
-        # sanitize ath
-        path = re.sub('[.]', '', path)
-        path = path.strip('/\\')
-        return os.path.join(self._filestore(cr, uid), path)
-
-    def _get_path(self, cr, uid, location, bin_data):
-        sha = hashlib.sha1(bin_data).hexdigest()
+        # location = 'file:filestore'
+        assert location.startswith('file:'), "Unhandled filestore location %s" % location
+        location = location[5:]
 
-        # retro compatibility
-        fname = sha[:3] + '/' + sha
-        full_path = self._full_path(cr, uid, location, fname)
-        if os.path.isfile(full_path):
-            return fname, full_path        # keep existing path
+        # sanitize location name and path
+        location = re.sub('[.]','',location)
+        location = location.strip('/\\')
 
-        # scatter files across 256 dirs
-        # we use '/' in the db (even on windows)
-        fname = sha[:2] + '/' + sha
-        full_path = self._full_path(cr, uid, location, fname)
-        dirname = os.path.dirname(full_path)
-        if not os.path.isdir(dirname):
-            os.makedirs(dirname)
-        return fname, full_path
+        path = re.sub('[.]','',path)
+        path = path.strip('/\\')
+        return os.path.join(tools.config['root_path'], location, cr.dbname, path)
 
     def _file_read(self, cr, uid, location, fname, bin_size=False):
         full_path = self._full_path(cr, uid, location, fname)
@@ -110,13 +92,18 @@ class ir_attachment(osv.osv):
 
     def _file_write(self, cr, uid, location, value):
         bin_value = value.decode('base64')
-        fname, full_path = self._get_path(cr, uid, location, bin_value)
-        if not os.path.exists(full_path):
-            try:
-                with open(full_path, 'wb') as fp:
-                    fp.write(bin_value)
-            except IOError:
-                _logger.error("_file_write writing %s", full_path)
+        fname = hashlib.sha1(bin_value).hexdigest()
+        # scatter files across 1024 dirs
+        # we use '/' in the db (even on windows)
+        fname = fname[:3] + '/' + fname
+        full_path = self._full_path(cr, uid, location, fname)
+        try:
+            dirname = os.path.dirname(full_path)
+            if not os.path.isdir(dirname):
+                os.makedirs(dirname)
+            open(full_path,'wb').write(bin_value)
+        except IOError:
+            _logger.error("_file_write writing %s",full_path)
         return fname
 
     def _file_delete(self, cr, uid, location, fname):
@@ -135,10 +122,10 @@ class ir_attachment(osv.osv):
         if context is None:
             context = {}
         result = {}
-        location = self._storage(cr, uid, context)
+        location = self.pool.get('ir.config_parameter').get_param(cr, uid, 'ir_attachment.location')
         bin_size = context.get('bin_size')
         for attach in self.browse(cr, uid, ids, context=context):
-            if location != 'db' and attach.store_fname:
+            if location and attach.store_fname:
                 result[attach.id] = self._file_read(cr, uid, location, attach.store_fname, bin_size)
             else:
                 result[attach.id] = attach.db_datas
@@ -150,9 +137,9 @@ class ir_attachment(osv.osv):
             return True
         if context is None:
             context = {}
-        location = self._storage(cr, uid, context)
+        location = self.pool.get('ir.config_parameter').get_param(cr, uid, 'ir_attachment.location')
         file_size = len(value.decode('base64'))
-        if location != 'db':
+        if location:
             attach = self.browse(cr, uid, id, context=context)
             if attach.store_fname:
                 self._file_delete(cr, uid, location, attach.store_fname)
@@ -298,8 +285,8 @@ class ir_attachment(osv.osv):
         if isinstance(ids, (int, long)):
             ids = [ids]
         self.check(cr, uid, ids, 'unlink', context=context)
-        location = self._storage(cr, uid, context)
-        if location != 'db':
+        location = self.pool.get('ir.config_parameter').get_param(cr, uid, 'ir_attachment.location')
+        if location:
             for attach in self.browse(cr, uid, ids, context=context):
                 if attach.store_fname:
                     self._file_delete(cr, uid, location, attach.store_fname)
@@ -316,3 +303,4 @@ class ir_attachment(osv.osv):
             cr, uid, 'base', 'action_attachment', context=context)
 
 # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
+
index e5a5e5f..60a69cd 100644 (file)
@@ -225,21 +225,12 @@ class ir_cron(osv.osv):
             lock_cr = db.cursor()
             try:
                 # Try to grab an exclusive lock on the job row from within the task transaction
-                # Restrict to the same conditions as for the search since the job may have already
-                # been run by an other thread when cron is running in multi thread
                 lock_cr.execute("""SELECT *
                                    FROM ir_cron
-                                   WHERE numbercall != 0
-                                      AND active
-                                      AND nextcall <= (now() at time zone 'UTC')
-                                      AND id=%s
+                                   WHERE id=%s
                                    FOR UPDATE NOWAIT""",
                                (job['id'],), log_exceptions=False)
 
-                locked_job = lock_cr.fetchone()
-                if not locked_job:
-                    # job was already executed by another parallel process/thread, skipping it.
-                    continue
                 # Got the lock on the job row, run its code
                 _logger.debug('Starting job `%s`.', job['name'])
                 job_cr = db.cursor()
index 62ecd60..8cc24c8 100644 (file)
@@ -53,8 +53,8 @@ class ir_http(osv.AbstractModel):
     def _get_converters(self):
         return {'model': ModelConverter, 'models': ModelsConverter}
 
-    def _find_handler(self, return_rule=False):
-        return self.routing_map().bind_to_environ(request.httprequest.environ).match(return_rule=return_rule)
+    def _find_handler(self):
+        return self.routing_map().bind_to_environ(request.httprequest.environ).match()
 
     def _auth_method_user(self):
         request.uid = request.session.uid
@@ -77,9 +77,7 @@ class ir_http(osv.AbstractModel):
                 # what if error in security.check()
                 #   -> res_users.check()
                 #   -> res_users.check_credentials()
-            except (openerp.exceptions.AccessDenied, openerp.http.SessionExpiredException):
-                # All other exceptions mean undetermined status (e.g. connection pool full),
-                # let them bubble up
+            except Exception:
                 request.session.logout()
         getattr(self, "_auth_method_%s" % auth_method)()
         return auth_method
@@ -91,8 +89,7 @@ class ir_http(osv.AbstractModel):
     def _dispatch(self):
         # locate the controller method
         try:
-            rule, arguments = self._find_handler(return_rule=True)
-            func = rule.endpoint
+            func, arguments = self._find_handler()
         except werkzeug.exceptions.NotFound, e:
             return self._handle_exception(e)
 
@@ -105,7 +102,7 @@ class ir_http(osv.AbstractModel):
                 convert_exception_to(
                     werkzeug.exceptions.Forbidden))
 
-        processing = self._postprocess_args(arguments, rule)
+        processing = self._postprocess_args(arguments)
         if processing:
             return processing
 
@@ -121,7 +118,7 @@ class ir_http(osv.AbstractModel):
 
         return result
 
-    def _postprocess_args(self, arguments, rule):
+    def _postprocess_args(self, arguments):
         """ post process arg to set uid on browse records """
         for arg in arguments.itervalues():
             if isinstance(arg, orm.browse_record) and arg._uid is UID_PLACEHOLDER:
diff --git a/openerp/addons/base/ir/ir_logging.py b/openerp/addons/base/ir/ir_logging.py
deleted file mode 100644 (file)
index dd06a19..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-##############################################################################
-#
-#    OpenERP, Open Source Management Solution
-#    Copyright (C) 2014 OpenERP SA (<http://www.openerp.com>)
-#
-#    This program is free software: you can redistribute it and/or modify
-#    it under the terms of the GNU Affero General Public License as
-#    published by the Free Software Foundation, either version 3 of the
-#    License, or (at your option) any later version.
-#
-#    This program is distributed in the hope that it will be useful,
-#    but WITHOUT ANY WARRANTY; without even the implied warranty of
-#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-#    GNU Affero General Public License for more details.
-#
-#    You should have received a copy of the GNU Affero General Public License
-#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
-#
-##############################################################################
-import logging
-
-from openerp.osv import osv, fields
-from openerp.tools.translate import _
-
-class ir_logging(osv.Model):
-    _name = 'ir.logging'
-    _order = 'id DESC'
-
-    EXCEPTIONS_TYPE = [
-        ('client', 'Client'),
-        ('server', 'Server')
-    ]
-
-    _columns = {
-        'create_date': fields.datetime('Create Date', readonly=True),
-        'create_uid': fields.integer('Uid', readonly=True),  # Integer not m2o is intentionnal
-        'name': fields.char('Name', required=True),
-        'type': fields.selection(EXCEPTIONS_TYPE, string='Type', required=True, select=True),
-        'dbname': fields.char('Database Name'),
-        'level': fields.char('Level'),
-        'message': fields.text('Message', required=True),
-        'path': fields.char('Path', required=True),
-        'func': fields.char('Function', required=True),
-        'line': fields.char('Line', required=True),
-    }
-
diff --git a/openerp/addons/base/ir/ir_logging_view.xml b/openerp/addons/base/ir/ir_logging_view.xml
deleted file mode 100644 (file)
index f963fc0..0000000
+++ /dev/null
@@ -1,66 +0,0 @@
-<?xml version="1.0"?>
-<openerp>
-    <data>
-        <record model="ir.ui.view" id="ir_logging_form_view">
-            <field name="model">ir.logging</field>
-            <field name="arch" type="xml">
-                <form string="Log" version="7.0">
-                    <group>
-                        <field name="create_date" />
-                        <field name="dbname" />
-                        <field name="type" />
-                        <field name="name" />
-                        <field name="level" />
-                        <field name="path" />
-                        <field name="line" />
-                        <field name="func" />
-                        <field name="message" />
-                    </group>
-                </form>
-            </field>
-        </record>
-        <record model="ir.ui.view" id="ir_logging_tree_view">
-            <field name="model">ir.logging</field>
-            <field name="arch" type="xml">
-                <tree string="Logs" version="7.0">
-                    <field name="create_date" />
-                    <field name="create_uid" />
-                    <field name="dbname" />
-                    <field name="type" />
-                    <field name="name" />
-                    <field name="level" />
-                    <field name="path" />
-                    <field name="line" />
-                    <field name="func" />
-                </tree>
-            </field>
-        </record>
-        <record model="ir.ui.view" id="ir_logging_search_view">
-            <field name="model">ir.logging</field>
-            <field name="arch" type="xml">
-                <search string="Logs">
-                    <field name="dbname" />
-                    <field name="type" />
-                    <field name="name" />
-                    <field name="level" />
-                    <field name="message" />
-                    <group expand="0" string="Group By...">
-                        <filter string="Database" domain="[]" context="{'group_by': 'dbname'}" />
-                        <filter string="Level" domain="[]" context="{'group_by': 'level'}" />
-                        <filter string="Type" domain="[]" context="{'group_by': 'type'}" />
-                        <filter string="Month" domain="[]" context="{'group_by': 'create_date'}" />
-                        <filter string="Day" domain="[]" context="{'group_by': 'create_date:day'}" />
-                    </group>
-                </search>
-            </field>
-        </record>
-        <record model="ir.actions.act_window" id="ir_logging_all_act">
-            <field name="name">Logging</field>
-            <field name="res_model">ir.logging</field>
-            <field name="view_type">form</field>
-            <field name="view_mode">tree,form</field>
-            <field name="search_view_id" ref="ir_logging_search_view" />
-        </record>
-        <menuitem parent="base.menu_custom" id="ir_logging_all_menu" action="ir_logging_all_act" />
-    </data>
-</openerp>
index 76166ee..d119c03 100644 (file)
@@ -33,7 +33,7 @@ from openerp.osv.orm import Model, browse_null
 from openerp.tools.safe_eval import safe_eval as eval
 from openerp.tools import config
 from openerp.tools.translate import _
-from openerp.osv.orm import except_orm, browse_record, MAGIC_COLUMNS
+from openerp.osv.orm import except_orm, browse_record
 
 _logger = logging.getLogger(__name__)
 
@@ -302,8 +302,6 @@ class ir_model_fields(osv.osv):
 
     def _drop_column(self, cr, uid, ids, context=None):
         for field in self.browse(cr, uid, ids, context):
-            if field.name in MAGIC_COLUMNS:
-                continue
             model = self.pool[field.model]
             cr.execute('select relkind from pg_class where relname=%s', (model._table,))
             result = cr.fetchone()
@@ -1119,10 +1117,6 @@ class ir_model_data(osv.osv):
                     # Don't remove the LOG_ACCESS_COLUMNS unless _log_access
                     # has been turned off on the model.
                     field = self.pool[model].browse(cr, uid, [res_id], context=context)[0]
-                    if not field.exists():
-                        _logger.info('Deleting orphan external_ids %s', external_ids)
-                        self.unlink(cr, uid, external_ids)
-                        continue
                     if field.name in openerp.osv.orm.LOG_ACCESS_COLUMNS and self.pool[field.model]._log_access:
                         continue
                     if field.name == 'id':
index 0b3bf91..590ce90 100644 (file)
@@ -32,7 +32,7 @@ class QWebException(Exception):
 class QWebTemplateNotFound(QWebException):
     pass
 
-def raise_qweb_exception(etype=None, **kw):
+def convert_to_qweb_exception(etype=None, **kw):
     if etype is None:
         etype = QWebException
     orig_type, original, tb = sys.exc_info()
@@ -43,7 +43,7 @@ def raise_qweb_exception(etype=None, **kw):
             e.qweb[k] = v
         # Will use `raise foo from bar` in python 3 and rename cause to __cause__
         e.qweb['cause'] = original
-        raise
+        return e
 
 class QWebContext(dict):
     def __init__(self, cr, uid, data, loader=None, templates=None, context=None):
@@ -166,7 +166,7 @@ class QWeb(orm.AbstractModel):
             try:
                 xml_doc = qwebcontext.loader(name)
             except ValueError:
-                raise_qweb_exception(QWebTemplateNotFound, message="Loader could not find template %r" % name, template=origin_template)
+                raise convert_to_qweb_exception(QWebTemplateNotFound, message="Loader could not find template %r" % name, template=origin_template)
             self.load_document(xml_doc, qwebcontext=qwebcontext)
 
         if name in qwebcontext.templates:
@@ -179,7 +179,7 @@ class QWeb(orm.AbstractModel):
             return qwebcontext.safe_eval(expr)
         except Exception:
             template = qwebcontext.get('__template__')
-            raise_qweb_exception(message="Could not evaluate expression %r" % expr, expression=expr, template=template)
+            raise convert_to_qweb_exception(message="Could not evaluate expression %r" % expr, expression=expr, template=template)
 
     def eval_object(self, expr, qwebcontext):
         return self.eval(expr, qwebcontext)
@@ -207,7 +207,7 @@ class QWeb(orm.AbstractModel):
             return str(expr % qwebcontext)
         except Exception:
             template = qwebcontext.get('__template__')
-            raise_qweb_exception(message="Format error for expression %r" % expr, expression=expr, template=template)
+            raise convert_to_qweb_exception(message="Format error for expression %r" % expr, expression=expr, template=template)
 
     def eval_bool(self, expr, qwebcontext):
         return int(bool(self.eval(expr, qwebcontext)))
@@ -292,7 +292,7 @@ class QWeb(orm.AbstractModel):
                     raise
                 except Exception:
                     template = qwebcontext.get('__template__')
-                    raise_qweb_exception(message="Could not render element %r" % element.nodeName, node=element, template=template)
+                    raise convert_to_qweb_exception(message="Could not render element %r" % element.nodeName, node=element, template=template)
         name = str(element.nodeName)
         inner = "".join(g_inner)
         trim = template_attributes.get("trim", 0)
@@ -488,6 +488,7 @@ class FieldConverter(osv.AbstractModel):
         A default configuration key is ``widget`` which can override the
         field's own ``_type``.
         """
+        content = None
         try:
             content = self.record_to_html(
                 cr, uid, field_name, record,
@@ -502,14 +503,12 @@ class FieldConverter(osv.AbstractModel):
                             field_name, record._model._name, exc_info=True)
             content = None
 
-        if context and context.get('inherit_branding'):
-            # add branding attributes
-            g_att += ''.join(
-                ' %s="%s"' % (name, werkzeug.utils.escape(value))
-                for name, value in self.attributes(
-                    cr, uid, field_name, record, options,
-                    source_element, g_att, t_att, qweb_context)
-            )
+        g_att += ''.join(
+            ' %s="%s"' % (name, werkzeug.utils.escape(value))
+            for name, value in self.attributes(
+                cr, uid, field_name, record, options,
+                source_element, g_att, t_att, qweb_context)
+        )
 
         return self.render_element(cr, uid, source_element, t_att, g_att,
                                    qweb_context, content)
@@ -612,9 +611,6 @@ class DateTimeConverter(osv.AbstractModel):
             strftime_pattern = (u"%s %s" % (lang.date_format, lang.time_format))
             pattern = openerp.tools.posix_to_ldml(strftime_pattern, locale=locale)
 
-        if options and options.get('hide_seconds'):
-            pattern = pattern.replace(":ss", "").replace(":s", "")
-        
         return babel.dates.format_datetime(value, format=pattern, locale=locale)
 
 class TextConverter(osv.AbstractModel):
index 360c5e3..d4655bf 100644 (file)
@@ -728,26 +728,9 @@ class view(osv.osv):
     def clear_cache(self):
         self.read_template.clear_cache(self)
 
-    def _contains_branded(self, node):
-        return node.tag == 't'\
-            or 't-raw' in node.attrib\
-            or any(self.is_node_branded(child) for child in node.iterdescendants())
-
-    def _pop_view_branding(self, element):
-        distributed_branding = dict(
-            (attribute, element.attrib.pop(attribute))
-            for attribute in MOVABLE_BRANDING
-            if element.get(attribute))
-        return distributed_branding
-
     def distribute_branding(self, e, branding=None, parent_xpath='',
                             index_map=misc.ConstantMapping(1)):
         if e.get('t-ignore') or e.tag == 'head':
-            # remove any view branding possibly injected by inheritance
-            attrs = set(MOVABLE_BRANDING)
-            for descendant in e.iterdescendants(tag=etree.Element):
-                if not attrs.intersection(descendant.attrib): continue
-                self._pop_view_branding(descendant)
             # TODO: find a better name and check if we have a string to boolean helper
             return
 
@@ -759,15 +742,15 @@ class view(osv.osv):
             e.set('data-oe-xpath', node_path)
         if not e.get('data-oe-model'): return
 
-        if set(('t-esc', 't-escf', 't-raw', 't-rawf')).intersection(e.attrib):
-            # nodes which fully generate their content and have no reason to
-            # be branded because they can not sensibly be edited
-            self._pop_view_branding(e)
-        elif self._contains_branded(e):
-            # if a branded element contains branded elements distribute own
-            # branding to children unless it's t-raw, then just remove branding
-            # on current element
-            distributed_branding = self._pop_view_branding(e)
+        # if a branded element contains branded elements distribute own
+        # branding to children unless it's t-raw, then just remove branding
+        # on current element
+        if e.tag == 't' or 't-raw' in e.attrib or \
+                any(self.is_node_branded(child) for child in e.iterdescendants()):
+            distributed_branding = dict(
+                (attribute, e.attrib.pop(attribute))
+                for attribute in MOVABLE_BRANDING
+                if e.get(attribute))
 
             if 't-raw' not in e.attrib:
                 # TODO: collections.Counter if remove p2.6 compat
@@ -777,12 +760,11 @@ class view(osv.osv):
                     if child.get('data-oe-xpath'):
                         # injected by view inheritance, skip otherwise
                         # generated xpath is incorrect
-                        self.distribute_branding(child)
-                    else:
-                        indexes[child.tag] += 1
-                        self.distribute_branding(
-                            child, distributed_branding,
-                            parent_xpath=node_path, index_map=indexes)
+                        continue
+                    indexes[child.tag] += 1
+                    self.distribute_branding(child, distributed_branding,
+                                             parent_xpath=node_path,
+                                             index_map=indexes)
 
     def is_node_branded(self, node):
         """ Finds out whether a node is branded or qweb-active (bears a
index 2ba789f..6d6f0e1 100644 (file)
@@ -28,6 +28,8 @@ from openerp import tools
 from openerp.osv import osv, fields
 from openerp.tools.translate import _
 
+ADDONS_PATH = tools.config['addons_path'].split(",")[-1]
+
 class base_module_import(osv.osv_memory):
     """ Import Module """
 
index 64ab567..ae83aa4 100644 (file)
@@ -208,19 +208,20 @@ class res_company(osv.osv):
         res['value'] = {'currency_id': currency_id}
         return res
 
-    def name_search(self, cr, uid, name='', args=None, operator='ilike', context=None, limit=100):
+    def _search(self, cr, uid, args, offset=0, limit=None, order=None,
+            context=None, count=False, access_rights_uid=None):
         if context is None:
             context = {}
-        if context.pop('user_preference', None):
+        if context.get('user_preference'):
             # We browse as superuser. Otherwise, the user would be able to
             # select only the currently visible companies (according to rules,
             # which are probably to allow to see the child companies) even if
             # she belongs to some other companies.
             user = self.pool.get('res.users').browse(cr, SUPERUSER_ID, uid, context=context)
             cmp_ids = list(set([user.company_id.id] + [cmp.id for cmp in user.company_ids]))
-            uid = SUPERUSER_ID
-            args = (args or []) + [('id', 'in', cmp_ids)]
-        return super(res_company, self).name_search(cr, uid, name=name, args=args, operator=operator, context=context, limit=limit)
+            return cmp_ids
+        return super(res_company, self)._search(cr, uid, args, offset=offset, limit=limit, order=order,
+            context=context, count=count, access_rights_uid=access_rights_uid)
 
     def _company_default_get(self, cr, uid, object=False, field=False, context=None):
         """
index 46f0218..e957308 100644 (file)
@@ -350,7 +350,6 @@ class res_partner(osv.osv, format_address):
     def copy(self, cr, uid, id, default=None, context=None):
         if default is None:
             default = {}
-        default['user_ids'] = False
         name = self.read(cr, uid, [id], ['name'], context)[0]['name']
         default.update({'name': _('%s (copy)') % name})
         return super(res_partner, self).copy(cr, uid, id, default, context)
index 1668cbd..b2aba69 100644 (file)
@@ -3,7 +3,7 @@
 #
 #    OpenERP, Open Source Management Solution
 #    Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>).
-#    Copyright (C) 2010-2014 OpenERP s.a. (<http://openerp.com>).
+#    Copyright (C) 2010-2013 OpenERP s.a. (<http://openerp.com>).
 #
 #    This program is free software: you can redistribute it and/or modify
 #    it under the terms of the GNU Affero General Public License as
@@ -169,9 +169,8 @@ class res_users(osv.osv):
     }
 
     def on_change_login(self, cr, uid, ids, login, context=None):
-        if login and tools.single_email_re.match(login):
-            return {'value': {'email': login}}
-        return {}
+        v = {'email': login} if tools.single_email_re.match(login) else {}
+        return {'value': v}
 
     def onchange_state(self, cr, uid, ids, state_id, context=None):
         partner_ids = [user.partner_id.id for user in self.browse(cr, uid, ids, context=context)]
@@ -900,22 +899,18 @@ class change_password_wizard(osv.TransientModel):
             }))
         return {'user_ids': res}
 
+
     def change_password_button(self, cr, uid, id, context=None):
         wizard = self.browse(cr, uid, id, context=context)[0]
-        need_reload = any(uid == user.user_id.id for user in wizard.user_ids)
-        line_ids = [user.id for user in wizard.user_ids]
-
-        self.pool.get('change.password.user').change_password_button(cr, uid, line_ids, context=context)
+        user_ids = []
+        for user in wizard.user_ids:
+            user_ids.append(user.id)
+        self.pool.get('change.password.user').change_password_button(cr, uid, user_ids, context=context)
         # don't keep temporary password copies in the database longer than necessary
-        self.pool.get('change.password.user').write(cr, uid, line_ids, {'new_passwd': False}, context=context)
-
-        if need_reload:
-            return {
-                'type': 'ir.actions.client',
-                'tag': 'reload'
-            }
-
-        return {'type': 'ir.actions.act_window_close'}
+        self.pool.get('change.password.user').unlink(cr, uid, user_ids)
+        return {
+            'type': 'ir.actions.act_window_close',
+        }
 
 class change_password_user(osv.TransientModel):
     """
index 8a3f372..ba603c7 100644 (file)
                     <group name="preferences" col="4">
                         <field name="lang" readonly="0"/>
                         <field name="tz" readonly="0"/>
-                        <field name="company_id" options="{'no_create': True}" readonly="0"
+                        <field name="company_id" widget="selection" readonly="0"
                             groups="base.group_multi_company"/>
                     </group>
                     <group string="Email Preferences">
index 6113f17..25df6e1 100644 (file)
 "access_ir_needaction_mixin","ir_needaction_mixin","model_ir_needaction_mixin",,1,1,1,1
 "access_res_font_all","res_res_font all","model_res_font",,1,0,0,0
 "access_res_font_group_user","res_res_font group_user","model_res_font","group_user",1,1,1,1
-"access_ir_logging","ir_logging admin","model_ir_logging","group_erp_manager",1,1,1,1
index bbc5b21..263cb0a 100644 (file)
@@ -9,7 +9,6 @@ class test_base(common.TransactionCase):
         super(test_base,self).setUp()
         self.res_partner = self.registry('res.partner')
         self.res_users = self.registry('res.users')
-        self.res_partner_title = self.registry('res.partner.title')
 
         # samples use effective TLDs from the Mozilla public suffix
         # list at http://publicsuffix.org
@@ -286,99 +285,27 @@ class test_base(common.TransactionCase):
 
     def test_60_read_group(self):
         cr, uid = self.cr, self.uid
-        title_sir = self.res_partner_title.create(cr, uid, {'name': 'Sir', 'domain': 'contact'})
-        title_lady = self.res_partner_title.create(cr, uid, {'name': 'Lady', 'domain': 'contact'})
-        test_users = [
-            {'name': 'Alice', 'login': 'alice', 'color': 1, 'function': 'Friend', 'date': '2015-03-28', 'title': title_lady},
-            {'name': 'Alice', 'login': 'alice2', 'color': 0, 'function': 'Friend',  'date': '2015-01-28', 'title': title_lady},
-            {'name': 'Bob', 'login': 'bob', 'color': 2, 'function': 'Friend', 'date': '2015-03-02', 'title': title_sir},
-            {'name': 'Eve', 'login': 'eve', 'color': 3, 'function': 'Eavesdropper', 'date': '2015-03-20', 'title': title_lady},
-            {'name': 'Nab', 'login': 'nab', 'color': -3, 'function': '5$ Wrench', 'date': '2014-09-10', 'title': title_sir},
-            {'name': 'Nab', 'login': 'nab-she', 'color': 6, 'function': '5$ Wrench', 'date': '2014-01-02', 'title': title_lady},
-        ]
-        ids = [self.res_users.create(cr, uid, u) for u in test_users]
-        domain = [('id', 'in', ids)]
-
-        # group on local char field without domain and without active_test (-> empty WHERE clause)
-        groups_data = self.res_users.read_group(cr, uid, [], fields=['login'], groupby=['login'], orderby='login DESC', context={'active_test': False})
-        self.assertGreater(len(groups_data), 6, "Incorrect number of results when grouping on a field")
-
-        # group on local char field with limit
-        groups_data = self.res_users.read_group(cr, uid, domain, fields=['login'], groupby=['login'], orderby='login DESC', limit=3, offset=3)
-        self.assertEqual(len(groups_data), 3, "Incorrect number of results when grouping on a field with limit")
-        self.assertEqual(['bob', 'alice2', 'alice'], [g['login'] for g in groups_data], 'Result mismatch')
-
-        # group on inherited char field, aggregate on int field (second groupby ignored on purpose)
-        groups_data = self.res_users.read_group(cr, uid, domain, fields=['name', 'color', 'function'], groupby=['function', 'login'])
-        self.assertEqual(len(groups_data), 3, "Incorrect number of results when grouping on a field")
-        self.assertEqual(['5$ Wrench', 'Eavesdropper', 'Friend'], [g['function'] for g in groups_data], 'incorrect read_group order')
-        for group_data in groups_data:
-            self.assertIn('color', group_data, "Aggregated data for the column 'color' is not present in read_group return values")
-            self.assertEqual(group_data['color'], 3, "Incorrect sum for aggregated data for the column 'color'")
-
-        # group on inherited char field, reverse order
-        groups_data = self.res_users.read_group(cr, uid, domain, fields=['name', 'color'], groupby='name', orderby='name DESC')
-        self.assertEqual(['Nab', 'Eve', 'Bob', 'Alice'], [g['name'] for g in groups_data], 'Incorrect ordering of the list')
-
-        # group on int field, default ordering
-        groups_data = self.res_users.read_group(cr, uid, domain, fields=['color'], groupby='color')
-        self.assertEqual([-3, 0, 1, 2, 3, 6], [g['color'] for g in groups_data], 'Incorrect ordering of the list')
-
-        # multi group, second level is int field, should still be summed in first level grouping
-        groups_data = self.res_users.read_group(cr, uid, domain, fields=['name', 'color'], groupby=['name', 'color'], orderby='name DESC')
-        self.assertEqual(['Nab', 'Eve', 'Bob', 'Alice'], [g['name'] for g in groups_data], 'Incorrect ordering of the list')
-        self.assertEqual([3, 3, 2, 1], [g['color'] for g in groups_data], 'Incorrect ordering of the list')
-
-        # group on inherited char field, multiple orders with directions
-        groups_data = self.res_users.read_group(cr, uid, domain, fields=['name', 'color'], groupby='name', orderby='color DESC, name')
-        self.assertEqual(len(groups_data), 4, "Incorrect number of results when grouping on a field")
-        self.assertEqual(['Eve', 'Nab', 'Bob', 'Alice'], [g['name'] for g in groups_data], 'Incorrect ordering of the list')
-        self.assertEqual([1, 2, 1, 2], [g['name_count'] for g in groups_data], 'Incorrect number of results')
-
-        # group on inherited date column (res_partner.date) -> Year-Month, default ordering
-        groups_data = self.res_users.read_group(cr, uid, domain, fields=['function', 'color', 'date'], groupby=['date'])
-        self.assertEqual(len(groups_data), 4, "Incorrect number of results when grouping on a field")
-        self.assertEqual(['January 2014', 'September 2014', 'January 2015', 'March 2015'], [g['date'] for g in groups_data], 'Incorrect ordering of the list')
-        self.assertEqual([1, 1, 1, 3], [g['date_count'] for g in groups_data], 'Incorrect number of results')
-
-        # group on inherited date column (res_partner.date) -> Year-Month, custom order
-        groups_data = self.res_users.read_group(cr, uid, domain, fields=['function', 'color', 'date'], groupby=['date'], orderby='date DESC')
-        self.assertEqual(len(groups_data), 4, "Incorrect number of results when grouping on a field")
-        self.assertEqual(['March 2015', 'January 2015', 'September 2014', 'January 2014'], [g['date'] for g in groups_data], 'Incorrect ordering of the list')
-        self.assertEqual([3, 1, 1, 1], [g['date_count'] for g in groups_data], 'Incorrect number of results')
-
-        # group on inherited many2one (res_partner.title), default order
-        groups_data = self.res_users.read_group(cr, uid, domain, fields=['function', 'color', 'title'], groupby=['title'])
-        self.assertEqual(len(groups_data), 2, "Incorrect number of results when grouping on a field")
-        # m2o is returned as a (id, label) pair
-        self.assertEqual([(title_lady, 'Lady'), (title_sir, 'Sir')], [g['title'] for g in groups_data], 'Incorrect ordering of the list')
-        self.assertEqual([4, 2], [g['title_count'] for g in groups_data], 'Incorrect number of results')
-        self.assertEqual([10, -1], [g['color'] for g in groups_data], 'Incorrect aggregation of int column')
-
-        # group on inherited many2one (res_partner.title), reversed natural order
-        groups_data = self.res_users.read_group(cr, uid, domain, fields=['function', 'color', 'title'], groupby=['title'], orderby="title desc")
-        self.assertEqual(len(groups_data), 2, "Incorrect number of results when grouping on a field")
-        # m2o is returned as a (id, label) pair
-        self.assertEqual([(title_sir, 'Sir'), (title_lady, 'Lady')], [g['title'] for g in groups_data], 'Incorrect ordering of the list')
-        self.assertEqual([2, 4], [g['title_count'] for g in groups_data], 'Incorrect number of results')
-        self.assertEqual([-1, 10], [g['color'] for g in groups_data], 'Incorrect aggregation of int column')
+        for user_data in [
+          {'name': 'Alice', 'login': 'alice', 'color': 1, 'function': 'Friend'},
+          {'name': 'Bob', 'login': 'bob', 'color': 2, 'function': 'Friend'},
+          {'name': 'Eve', 'login': 'eve', 'color': 3, 'function': 'Eavesdropper'},
+          {'name': 'Nab', 'login': 'nab', 'color': 2, 'function': '5$ Wrench'},
+        ]:
+          self.res_users.create(cr, uid, user_data)
 
-        # group on inherited many2one (res_partner.title), multiple orders with m2o in second position
-        groups_data = self.res_users.read_group(cr, uid, domain, fields=['function', 'color', 'title'], groupby=['title'], orderby="color desc, title desc")
+        groups_data = self.res_users.read_group(cr, uid, domain=[('login', 'in', ('alice', 'bob', 'eve'))], fields=['name', 'color', 'function'], groupby='function')
         self.assertEqual(len(groups_data), 2, "Incorrect number of results when grouping on a field")
-        # m2o is returned as a (id, label) pair
-        self.assertEqual([(title_lady, 'Lady'), (title_sir, 'Sir')], [g['title'] for g in groups_data], 'Incorrect ordering of the result')
-        self.assertEqual([4, 2], [g['title_count'] for g in groups_data], 'Incorrect number of results')
-        self.assertEqual([10, -1], [g['color'] for g in groups_data], 'Incorrect aggregation of int column')
+        for group_data in groups_data:
+          self.assertIn('color', group_data, "Aggregated data for the column 'color' is not present in read_group return values")
+          self.assertEqual(group_data['color'], 3, "Incorrect sum for aggregated data for the column 'color'")
 
-        # group on inherited many2one (res_partner.title), ordered by other inherited field (color)
-        groups_data = self.res_users.read_group(cr, uid, domain, fields=['function', 'color', 'title'], groupby=['title'], orderby='color')
-        self.assertEqual(len(groups_data), 2, "Incorrect number of results when grouping on a field")
-        # m2o is returned as a (id, label) pair
-        self.assertEqual([(title_sir, 'Sir'), (title_lady, 'Lady')], [g['title'] for g in groups_data], 'Incorrect ordering of the list')
-        self.assertEqual([2, 4], [g['title_count'] for g in groups_data], 'Incorrect number of results')
-        self.assertEqual([-1, 10], [g['color'] for g in groups_data], 'Incorrect aggregation of int column')
+        groups_data = self.res_users.read_group(cr, uid, domain=[('login', 'in', ('alice', 'bob', 'eve'))], fields=['name', 'color'], groupby='name', orderby='name DESC, color asc')
+        self.assertEqual(len(groups_data), 3, "Incorrect number of results when grouping on a field")
+        self.assertEqual([user['name'] for user in groups_data], ['Eve', 'Bob', 'Alice'], 'Incorrect ordering of the list')
 
+        groups_data = self.res_users.read_group(cr, uid, domain=[('login', 'in', ('alice', 'bob', 'eve', 'nab'))], fields=['function', 'color'], groupby='function', orderby='color ASC')
+        self.assertEqual(len(groups_data), 3, "Incorrect number of results when grouping on a field")
+        self.assertEqual(groups_data, sorted(groups_data, key=lambda x: x['color']), 'Incorrect ordering of the list')
 
 class test_partner_recursion(common.TransactionCase):
 
index ce34bce..47ffcd2 100644 (file)
@@ -179,51 +179,3 @@ class TestPropertyField(common.TransactionCase):
         self.partner.write(cr, alice, [partner_id], {'property_country': country_be})
         self.assertEqual(self.partner.browse(cr, alice, partner_id).property_country.id, country_be, "Alice does not see the value he has set on the property field")
         self.assertEqual(self.partner.browse(cr, bob, partner_id).property_country.id, country_fr, "Changes made by Alice have overwritten Bob's value")
-
-
-class TestHtmlField(common.TransactionCase):
-
-    def setUp(self):
-        super(TestHtmlField, self).setUp()
-        self.partner = self.registry('res.partner')
-
-    def test_00_sanitize(self):
-        cr, uid, context = self.cr, self.uid, {}
-        old_columns = self.partner._columns
-        self.partner._columns = dict(old_columns)
-        self.partner._columns.update({
-            'comment': fields.html('Secure Html', sanitize=False),
-        })
-        some_ugly_html = """<p>Oops this should maybe be sanitized
-% if object.some_field and not object.oriented:
-<table>
-    % if object.other_field:
-    <tr>
-        ${object.mako_thing}
-        <td>
-    </tr>
-    % endif
-    <tr>
-%if object.dummy_field:
-        <p>Youpie</p>
-%endif"""
-
-        pid = self.partner.create(cr, uid, {
-            'name': 'Raoul Poilvache',
-            'comment': some_ugly_html,
-        }, context=context)
-        partner = self.partner.browse(cr, uid, pid, context=context)
-        self.assertEqual(partner.comment, some_ugly_html, 'Error in HTML field: content was sanitized but field has sanitize=False')
-
-        self.partner._columns.update({
-            'comment': fields.html('Unsecure Html', sanitize=True),
-        })
-        self.partner.write(cr, uid, [pid], {
-            'comment': some_ugly_html,
-        }, context=context)
-        partner = self.partner.browse(cr, uid, pid, context=context)
-        # sanitize should have closed tags left open in the original html
-        self.assertIn('</table>', partner.comment, 'Error in HTML field: content does not seem to have been sanitized despise sanitize=True')
-        self.assertIn('</td>', partner.comment, 'Error in HTML field: content does not seem to have been sanitized despise sanitize=True')
-
-        self.partner._columns = old_columns
index 891b38b..4d96ec4 100644 (file)
@@ -1,92 +1,89 @@
 import hashlib
 import os
 
+import unittest2
+
 import openerp
 import openerp.tests.common
 
-HASH_SPLIT = 2      # FIXME: testing implementations detail is not a good idea
-
 class test_ir_attachment(openerp.tests.common.TransactionCase):
-    def setUp(self):
-        super(test_ir_attachment, self).setUp()
+
+    def test_00_attachment_flow(self):
         registry, cr, uid = self.registry, self.cr, self.uid
-        self.ira = registry('ir.attachment')
-        self.filestore = self.ira._filestore(cr, uid)
+        root_path = openerp.tools.config['root_path']
+        ira = registry('ir.attachment')
 
         # Blob1
-        self.blob1 = 'blob1'
-        self.blob1_b64 = self.blob1.encode('base64')
-        blob1_hash = hashlib.sha1(self.blob1).hexdigest()
-        self.blob1_fname = blob1_hash[:HASH_SPLIT] + '/' + blob1_hash
+        blob1 = 'blob1'
+        blob1_b64 = blob1.encode('base64')
+        blob1_hash = hashlib.sha1(blob1).hexdigest()
+        blob1_fname = blob1_hash[:3] + '/' + blob1_hash
 
         # Blob2
         blob2 = 'blob2'
-        self.blob2_b64 = blob2.encode('base64')
-
-    def test_01_store_in_db(self):
-        registry, cr, uid = self.registry, self.cr, self.uid
-
-        # force storing in database
-        registry('ir.config_parameter').set_param(cr, uid, 'ir_attachment.location', 'db')
+        blob2_b64 = blob2.encode('base64')
+        blob2_hash = hashlib.sha1(blob2).hexdigest()
+        blob2_fname = blob2_hash[:3] + '/' + blob2_hash
 
         # 'ir_attachment.location' is undefined test database storage
-        a1 = self.ira.create(cr, uid, {'name': 'a1', 'datas': self.blob1_b64})
-        a1_read = self.ira.read(cr, uid, [a1], ['datas'])
-        self.assertEqual(a1_read[0]['datas'], self.blob1_b64)
-
-        a1_db_datas = self.ira.browse(cr, uid, a1).db_datas
-        self.assertEqual(a1_db_datas, self.blob1_b64)
+        a1 = ira.create(cr, uid, {'name': 'a1', 'datas': blob1_b64})
+        a1_read = ira.read(cr, uid, [a1], ['datas'])
+        self.assertEqual(a1_read[0]['datas'], blob1_b64)
 
-    def test_02_store_on_disk(self):
-        registry, cr, uid = self.registry, self.cr, self.uid
+        cr.execute("select id,db_datas from ir_attachment where id = %s", (a1,) )
+        a1_db_datas = str(cr.fetchall()[0][1])
+        self.assertEqual(a1_db_datas, blob1_b64)
 
-        a2 = self.ira.create(cr, uid, {'name': 'a2', 'datas': self.blob1_b64})
-        a2_store_fname = self.ira.browse(cr, uid, a2).store_fname
+        # define a location for filestore
+        registry('ir.config_parameter').set_param(cr, uid, 'ir_attachment.location', 'file:///filestore')
 
-        self.assertEqual(a2_store_fname, self.blob1_fname)
-        self.assertTrue(os.path.isfile(os.path.join(self.filestore, a2_store_fname)))
+        # Test file storage
+        a2 = ira.create(cr, uid, {'name': 'a2', 'datas': blob1_b64})
+        a2_read = ira.read(cr, uid, [a2], ['datas'])
+        self.assertEqual(a2_read[0]['datas'], blob1_b64)
 
-    def test_03_no_duplication(self):
-        registry, cr, uid = self.registry, self.cr, self.uid
+        cr.execute("select id,store_fname from ir_attachment where id = %s", (a2,) )
+        a2_store_fname = cr.fetchall()[0][1]
+        self.assertEqual(a2_store_fname, blob1_fname)
 
-        a2 = self.ira.create(cr, uid, {'name': 'a2', 'datas': self.blob1_b64})
-        a2_store_fname = self.ira.browse(cr, uid, a2).store_fname
+        a2_fn = os.path.join(root_path, 'filestore', cr.dbname, blob1_hash[:3], blob1_hash)
+        fc = file(a2_fn).read()
+        self.assertEqual(fc, blob1)
 
-        a3 = self.ira.create(cr, uid, {'name': 'a3', 'datas': self.blob1_b64})
-        a3_store_fname = self.ira.browse(cr, uid, a3).store_fname
+        # create a3 with same blob
+        a3 = ira.create(cr, uid, {'name': 'a3', 'datas': blob1_b64})
+        a3_read = ira.read(cr, uid, [a3], ['datas'])
+        self.assertEqual(a3_read[0]['datas'], blob1_b64)
 
+        cr.execute("select id,store_fname from ir_attachment where id = %s", (a3,) )
+        a3_store_fname = cr.fetchall()[0][1]
         self.assertEqual(a3_store_fname, a2_store_fname)
 
-    def test_04_keep_file(self):
-        registry, cr, uid = self.registry, self.cr, self.uid
-
-        a2 = self.ira.create(cr, uid, {'name': 'a2', 'datas': self.blob1_b64})
-        a3 = self.ira.create(cr, uid, {'name': 'a3', 'datas': self.blob1_b64})
+        # create a4 blob2
+        a4 = ira.create(cr, uid, {'name': 'a4', 'datas': blob2_b64})
+        a4_read = ira.read(cr, uid, [a4], ['datas'])
+        self.assertEqual(a4_read[0]['datas'], blob2_b64)
 
-        a2_store_fname = self.ira.browse(cr, uid, a2).store_fname
-        a2_fn = os.path.join(self.filestore, a2_store_fname)
+        a4_fn = os.path.join(root_path, 'filestore', cr.dbname, blob2_hash[:3], blob2_hash)
+        self.assertTrue(os.path.isfile(a4_fn))
 
-        self.ira.unlink(cr, uid, [a3])
+        # delete a3 but file stays
+        ira.unlink(cr, uid, [a3])
         self.assertTrue(os.path.isfile(a2_fn))
 
         # delete a2 it is unlinked
-        self.ira.unlink(cr, uid, [a2])
+        ira.unlink(cr, uid, [a2])
         self.assertFalse(os.path.isfile(a2_fn))
 
-    def test_05_change_data_change_file(self):
-        registry, cr, uid = self.registry, self.cr, self.uid
-
-        a2 = self.ira.create(cr, uid, {'name': 'a2', 'datas': self.blob1_b64})
-        a2_store_fname = self.ira.browse(cr, uid, a2).store_fname
-        a2_fn = os.path.join(self.filestore, a2_store_fname)
+        # update a4 blob2 by blob1
+        ira.write(cr, uid, [a4], {'datas': blob1_b64})
+        a4_read = ira.read(cr, uid, [a4], ['datas'])
+        self.assertEqual(a4_read[0]['datas'], blob1_b64)
 
+        # file of a4 disapear and a2 reappear
+        self.assertFalse(os.path.isfile(a4_fn))
         self.assertTrue(os.path.isfile(a2_fn))
 
-        self.ira.write(cr, uid, [a2], {'datas': self.blob2_b64})
-        self.assertFalse(os.path.isfile(a2_fn))
+        # everybody applause
 
-        new_a2_store_fname = self.ira.browse(cr, uid, a2).store_fname
-        self.assertNotEqual(a2_store_fname, new_a2_store_fname)
 
-        new_a2_fn = os.path.join(self.filestore, new_a2_store_fname)
-        self.assertTrue(os.path.isfile(new_a2_fn))
index e925fff..bc428d7 100644 (file)
@@ -8,7 +8,6 @@
 #      OPENERP_DATABASE=yy PYTHONPATH=../:. unit2 test_ir_sequence
 # This assume an existing database.
 import psycopg2
-import psycopg2.errorcodes
 import unittest2
 
 import openerp
@@ -112,11 +111,11 @@ class test_ir_sequence_no_gap(unittest2.TestCase):
         cr0 = cursor()
         cr1 = cursor()
         cr1._default_log_exceptions = False # Prevent logging a traceback
-        with self.assertRaises(psycopg2.OperationalError) as e:
+        msg_re = '^could not obtain lock on row in relation "ir_sequence"$'
+        with self.assertRaisesRegexp(psycopg2.OperationalError, msg_re):
             n0 = registry('ir.sequence').next_by_code(cr0, ADMIN_USER_ID, 'test_sequence_type_2', {})
             assert n0
             n1 = registry('ir.sequence').next_by_code(cr1, ADMIN_USER_ID, 'test_sequence_type_2', {})
-        self.assertEqual(e.exception.pgcode, psycopg2.errorcodes.LOCK_NOT_AVAILABLE, msg="postgresql returned an incorrect errcode")
         cr0.close()
         cr1.close()
 
index ca1503a..71beaab 100644 (file)
@@ -14,8 +14,7 @@ class TestQWebTField(common.TransactionCase):
         self.engine = self.registry('ir.qweb')
 
     def context(self, values):
-        return ir_qweb.QWebContext(
-            self.cr, self.uid, values, context={'inherit_branding': True})
+        return ir_qweb.QWebContext(self.cr, self.uid, values)
 
     def test_trivial(self):
         field = document.createElement('span')
index 06030a8..6780996 100644 (file)
@@ -1,8 +1,6 @@
 # -*- encoding: utf-8 -*-
 from functools import partial
 
-import unittest2
-
 from lxml import etree as ET
 from lxml.builder import E
 
@@ -10,24 +8,6 @@ from openerp.tests import common
 
 Field = E.field
 
-class ViewCase(common.TransactionCase):
-    def setUp(self):
-        super(ViewCase, self).setUp()
-        self.addTypeEqualityFunc(ET._Element, self.assertTreesEqual)
-
-    def assertTreesEqual(self, n1, n2, msg=None):
-        self.assertEqual(n1.tag, n2.tag)
-        self.assertEqual((n1.text or '').strip(), (n2.text or '').strip(), msg)
-        self.assertEqual((n1.tail or '').strip(), (n2.tail or '').strip(), msg)
-
-        # Because lxml uses ordereddicts in which order is important to
-        # equality (!?!?!?!)
-        self.assertEqual(dict(n1.attrib), dict(n2.attrib), msg)
-
-        for c1, c2 in zip(n1, n2):
-            self.assertTreesEqual(c1, c2, msg)
-
-
 class TestNodeLocator(common.BaseCase):
     """
     The node locator returns None when it can not find a node, and the first
@@ -118,7 +98,7 @@ class TestNodeLocator(common.BaseCase):
             E.foo(attr='1', version='3'))
         self.assertIsNone(node)
 
-class TestViewInheritance(ViewCase):
+class TestViewInheritance(common.TransactionCase):
     def arch_for(self, name, view_type='form', parent=None):
         """ Generates a trivial view of the specified ``view_type``.
 
@@ -226,7 +206,7 @@ class TestViewInheritance(ViewCase):
             self.View.default_view(
                 self.cr, self.uid, model=self.model, view_type='graph'))
 
-class TestApplyInheritanceSpecs(ViewCase):
+class TestApplyInheritanceSpecs(common.TransactionCase):
     """ Applies a sequence of inheritance specification nodes to a base
     architecture. IO state parameters (cr, uid, model, context) are used for
     error reporting
@@ -250,8 +230,8 @@ class TestApplyInheritanceSpecs(ViewCase):
                                           spec, None)
 
         self.assertEqual(
-            self.base_arch,
-            E.form(Field(name="replacement"), string="Title"))
+            ET.tostring(self.base_arch),
+            ET.tostring(E.form(Field(name="replacement"), string="Title")))
 
     def test_delete(self):
         spec = Field(name="target", position="replace")
@@ -261,8 +241,8 @@ class TestApplyInheritanceSpecs(ViewCase):
                                           spec, None)
 
         self.assertEqual(
-            self.base_arch,
-            E.form(string="Title"))
+            ET.tostring(self.base_arch),
+            ET.tostring(E.form(string="Title")))
 
     def test_insert_after(self):
         spec = Field(
@@ -274,12 +254,12 @@ class TestApplyInheritanceSpecs(ViewCase):
                                           spec, None)
 
         self.assertEqual(
-            self.base_arch,
-            E.form(
+            ET.tostring(self.base_arch),
+            ET.tostring(E.form(
                 Field(name="target"),
                 Field(name="inserted"),
                 string="Title"
-            ))
+            )))
 
     def test_insert_before(self):
         spec = Field(
@@ -291,11 +271,11 @@ class TestApplyInheritanceSpecs(ViewCase):
                                           spec, None)
 
         self.assertEqual(
-            self.base_arch,
-            E.form(
+            ET.tostring(self.base_arch),
+            ET.tostring(E.form(
                 Field(name="inserted"),
                 Field(name="target"),
-                string="Title"))
+                string="Title")))
 
     def test_insert_inside(self):
         default = Field(Field(name="inserted"), name="target")
@@ -309,13 +289,13 @@ class TestApplyInheritanceSpecs(ViewCase):
                                           spec, None)
 
         self.assertEqual(
-            self.base_arch,
-            E.form(
+            ET.tostring(self.base_arch),
+            ET.tostring(E.form(
                 Field(
                     Field(name="inserted"),
                     Field(name="inserted 2"),
                     name="target"),
-                string="Title"))
+                string="Title")))
 
     def test_unpack_data(self):
         spec = E.data(
@@ -330,15 +310,15 @@ class TestApplyInheritanceSpecs(ViewCase):
                                           spec, None)
 
         self.assertEqual(
-            self.base_arch,
-            E.form(
+            ET.tostring(self.base_arch),
+            ET.tostring(E.form(
                 Field(
                     Field(name="inserted 0"),
                     Field(name="inserted 1"),
                     Field(name="inserted 2"),
                     Field(name="inserted 3"),
                     name="target"),
-                string="Title"))
+                string="Title")))
 
     def test_invalid_position(self):
         spec = Field(
@@ -370,18 +350,18 @@ class TestApplyInheritanceSpecs(ViewCase):
                                               self.base_arch,
                                               spec, None)
 
-class TestApplyInheritedArchs(ViewCase):
+class TestApplyInheritedArchs(common.TransactionCase):
     """ Applies a sequence of modificator archs to a base view
     """
 
-class TestViewCombined(ViewCase):
+class TestViewCombined(common.TransactionCase):
     """
     Test fallback operations of View.read_combined:
     * defaults mapping
     * ?
     """
 
-class TestNoModel(ViewCase):
+class TestNoModel(common.TransactionCase):
     def test_create_view_nomodel(self):
         View = self.registry('ir.ui.view')
         view_id = View.create(self.cr, self.uid, {
@@ -431,11 +411,13 @@ class TestNoModel(ViewCase):
             'value': translated_text,
         })
         sarch = View.translate_qweb(self.cr, self.uid, None, self.arch, 'fr_FR')
-
+        
         self.text_para.text = translated_text
-        self.assertEqual(sarch, self.arch)
+        self.assertEqual(
+            ET.tostring(sarch, encoding='utf-8'),
+            ET.tostring(self.arch, encoding='utf-8'))
 
-class TestTemplating(ViewCase):
+class TestTemplating(common.TransactionCase):
     def setUp(self):
         import openerp.modules
         super(TestTemplating, self).setUp()
@@ -491,126 +473,7 @@ class TestTemplating(ViewCase):
             second.get('data-oe-id'),
             "second should come from the extension view")
 
-    def test_branding_distribute_inner(self):
-        """ Checks that the branding is correctly distributed within a view
-        extension
-        """
-        Views = self.registry('ir.ui.view')
-        id = Views.create(self.cr, self.uid, {
-            'name': "Base view",
-            'type': 'qweb',
-            'arch': """<root>
-                <item order="1"/>
-            </root>"""
-        })
-        id2 = Views.create(self.cr, self.uid, {
-            'name': "Extension",
-            'type': 'qweb',
-            'inherit_id': id,
-            'arch': """<xpath expr="//item" position="before">
-                <item order="2">
-                    <content t-att-href="foo">bar</content>
-                </item>
-            </xpath>"""
-        })
-
-        arch_string = Views.read_combined(
-            self.cr, self.uid, id, fields=['arch'],
-            context={'inherit_branding': True})['arch']
-
-        arch = ET.fromstring(arch_string)
-        Views.distribute_branding(arch)
-
-        self.assertEqual(
-            arch,
-            E.root(
-                E.item(
-                    E.content("bar", {
-                        't-att-href': "foo",
-                        'data-oe-model': 'ir.ui.view',
-                        'data-oe-id': str(id2),
-                        'data-oe-field': 'arch',
-                        'data-oe-xpath': '/xpath/item/content[1]',
-                    }), {
-                        'order': '2',
-                        'data-oe-source-id': str(id)
-                    }),
-                E.item({
-                    'order': '1',
-                    'data-oe-model': 'ir.ui.view',
-                    'data-oe-id': str(id),
-                    'data-oe-field': 'arch',
-                    'data-oe-xpath': '/root[1]/item[1]'
-                })
-            )
-        )
-
-    def test_esc_no_branding(self):
-        Views = self.registry('ir.ui.view')
-        id = Views.create(self.cr, self.uid, {
-            'name': "Base View",
-            'type': 'qweb',
-            'arch': """<root>
-                <item><span t-esc="foo"/></item>
-            </root>""",
-        })
-
-        arch_string = Views.read_combined(
-            self.cr, self.uid, id, fields=['arch'],
-            context={'inherit_branding': True})['arch']
-        arch = ET.fromstring(arch_string)
-        Views.distribute_branding(arch)
-
-        self.assertEqual(arch, E.root(E.item(E.span({'t-esc': "foo"}))))
-
-    def test_ignore_unbrand(self):
-        Views = self.registry('ir.ui.view')
-        id = Views.create(self.cr, self.uid, {
-            'name': "Base view",
-            'type': 'qweb',
-            'arch': """<root>
-                <item order="1" t-ignore="true">
-                    <t t-esc="foo"/>
-                </item>
-            </root>"""
-        })
-        id2 = Views.create(self.cr, self.uid, {
-            'name': "Extension",
-            'type': 'qweb',
-            'inherit_id': id,
-            'arch': """<xpath expr="//item[@order='1']" position="inside">
-                <item order="2">
-                    <content t-att-href="foo">bar</content>
-                </item>
-            </xpath>"""
-        })
-
-        arch_string = Views.read_combined(
-            self.cr, self.uid, id, fields=['arch'],
-            context={'inherit_branding': True})['arch']
-
-        arch = ET.fromstring(arch_string)
-        Views.distribute_branding(arch)
-
-        self.assertEqual(
-            arch,
-            E.root(
-                E.item(
-                    {'t-ignore': 'true', 'order': '1'},
-                    E.t({'t-esc': 'foo'}),
-                    E.item(
-                        {'order': '2', 'data-oe-source-id': str(id)},
-                        E.content(
-                            {'t-att-href': 'foo'},
-                            "bar")
-                    )
-                )
-            ),
-            "t-ignore should apply to injected sub-view branding, not just to"
-            " the main view's"
-        )
-
-class test_views(ViewCase):
+class test_views(common.TransactionCase):
 
     def test_nonexistent_attribute_removal(self):
         Views = self.registry('ir.ui.view')
@@ -726,17 +589,16 @@ class test_views(ViewCase):
             })
         self.assertEqual(view['type'], 'form')
         self.assertEqual(
-            ET.fromstring(
+            ET.tostring(ET.fromstring(
                 view['arch'],
                 parser=ET.XMLParser(remove_blank_text=True)
-            ),
-            E.form(
-                E.p("Replacement data"),
-                E.footer(
-                    E.button(name="action_next", type="object", string="New button"),
-                    thing="bob"
-                ),
-                string="Replacement title", version="7.0"))
+            )),
+            '<form string="Replacement title" version="7.0">'
+                '<p>Replacement data</p>'
+                '<footer thing="bob">'
+                    '<button name="action_next" type="object" string="New button"/>'
+                '</footer>'
+            '</form>')
 
     def test_view_inheritance_divergent_models(self):
         Views = self.registry('ir.ui.view')
@@ -794,13 +656,14 @@ class test_views(ViewCase):
             })
         self.assertEqual(view['type'], 'form')
         self.assertEqual(
-            ET.fromstring(
+            ET.tostring(ET.fromstring(
                 view['arch'],
                 parser=ET.XMLParser(remove_blank_text=True)
-            ),
-            E.form(
-                E.p("Replacement data"),
-                E.footer(
-                    E.button(name="action_next", type="object", string="New button")),
-                string="Replacement title", version="7.0"
-            ))
+            )),
+            '<form string="Replacement title" version="7.0">'
+                '<p>Replacement data</p>'
+                '<footer>'
+                    '<button name="action_next" type="object" string="New button"/>'
+                '</footer>'
+            '</form>')
+
index 3ef6566..2f08969 100644 (file)
@@ -112,14 +112,11 @@ class TestCurrencyExport(TestExport):
             'widget': 'monetary',
             'display_currency': 'c2'
         }
-        context = dict(inherit_branding=True)
         converted = converter.to_html(
             self.cr, self.uid, 'value', obj, options,
             doc.createElement('span'),
             {'field': 'obj.value', 'field-options': json.dumps(options)},
-            '', ir_qweb.QWebContext(self.cr, self.uid, {'obj': obj, 'c2': dest, }),
-            context=context,
-        )
+            '', ir_qweb.QWebContext(self.cr, self.uid, {'obj': obj, 'c2': dest, }))
         return converted
 
     def test_currency_post(self):
index 995d694..26219b3 100644 (file)
@@ -309,9 +309,8 @@ class test_m2o(CreatorCase):
     def test_external_id(self):
         integer_id = self.registry('export.integer').create(
             self.cr, openerp.SUPERUSER_ID, {'value': 42})
-        # Expecting the m2o target model name in the external id,
-        # not this model's name
-        external_id = u'__export__.export_integer_%d' % integer_id
+        # __export__.$class.$id
+        external_id = u'__export__.export_many2one_%d' % integer_id
         self.assertEqual(
             self.export(integer_id, fields=['value/id']),
             [[external_id]])
index 42d920d..004cb1a 100644 (file)
@@ -72,7 +72,7 @@ def report_configuration():
     """
     config = openerp.tools.config
     _logger.info("OpenERP version %s", __version__)
-    for name, value in [('addons paths', openerp.modules.module.ad_paths),
+    for name, value in [('addons paths', config['addons_path']),
                         ('database hostname', config['db_host'] or 'localhost'),
                         ('database port', config['db_port'] or '5432'),
                         ('database user', config['db_user'])]:
index 5876cdc..74d833e 100644 (file)
@@ -23,7 +23,6 @@ import urlparse
 import warnings
 
 import babel.core
-import psutil
 import psycopg2
 import simplejson
 import werkzeug.contrib.sessions
@@ -36,6 +35,7 @@ import werkzeug.wsgi
 
 import openerp
 from openerp.service import security, model as service_model
+import openerp.tools
 
 _logger = logging.getLogger(__name__)
 
@@ -50,70 +50,6 @@ request = _request_stack()
     A global proxy that always redirect to the current request object.
 """
 
-def replace_request_password(args):
-    # password is always 3rd argument in a request, we replace it in RPC logs
-    # so it's easier to forward logs for diagnostics/debugging purposes...
-    if len(args) > 2:
-        args = list(args)
-        args[2] = '*'
-    return tuple(args)
-
-def dispatch_rpc(service_name, method, params):
-    """ Handle a RPC call.
-
-    This is pure Python code, the actual marshalling (from/to XML-RPC) is done
-    in a upper layer.
-    """
-    try:
-        rpc_request = logging.getLogger(__name__ + '.rpc.request')
-        rpc_response = logging.getLogger(__name__ + '.rpc.response')
-        rpc_request_flag = rpc_request.isEnabledFor(logging.DEBUG)
-        rpc_response_flag = rpc_response.isEnabledFor(logging.DEBUG)
-        if rpc_request_flag or rpc_response_flag:
-            start_time = time.time()
-            start_rss, start_vms = 0, 0
-            start_rss, start_vms = psutil.Process(os.getpid()).get_memory_info()
-            if rpc_request and rpc_response_flag:
-                openerp.netsvc.log(rpc_request, logging.DEBUG, '%s.%s' % (service_name, method), replace_request_password(params))
-
-        threading.current_thread().uid = None
-        threading.current_thread().dbname = None
-        if service_name == 'common':
-            dispatch = openerp.service.common.dispatch
-        elif service_name == 'db':
-            dispatch = openerp.service.db.dispatch
-        elif service_name == 'object':
-            dispatch = openerp.service.model.dispatch
-        elif service_name == 'report':
-            dispatch = openerp.service.report.dispatch
-        else:
-            dispatch = openerp.service.wsgi_server.rpc_handlers.get(service_name)
-        result = dispatch(method, params)
-
-        if rpc_request_flag or rpc_response_flag:
-            end_time = time.time()
-            end_rss, end_vms = 0, 0
-            end_rss, end_vms = psutil.Process(os.getpid()).get_memory_info()
-            logline = '%s.%s time:%.3fs mem: %sk -> %sk (diff: %sk)' % (service_name, method, end_time - start_time, start_vms / 1024, end_vms / 1024, (end_vms - start_vms)/1024)
-            if rpc_response_flag:
-                openerp.netsvc.log(rpc_response, logging.DEBUG, logline, result)
-            else:
-                openerp.netsvc.log(rpc_request, logging.DEBUG, logline, replace_request_password(params), depth=1)
-
-        return result
-    except (openerp.osv.orm.except_orm, openerp.exceptions.AccessError, \
-            openerp.exceptions.AccessDenied, openerp.exceptions.Warning, \
-            openerp.exceptions.RedirectWarning):
-        raise
-    except openerp.exceptions.DeferredException, e:
-        _logger.exception(openerp.tools.exception_to_unicode(e))
-        openerp.tools.debugger.post_mortem(openerp.tools.config, e.traceback)
-        raise
-    except Exception, e:
-        _logger.exception(openerp.tools.exception_to_unicode(e))
-        openerp.tools.debugger.post_mortem(openerp.tools.config, sys.exc_info())
-        raise
-
 def local_redirect(path, query=None, keep_hash=False, forward_debug=True, code=303):
     url = path
     if not query:
@@ -193,14 +129,12 @@ class WebRequest(object):
         self.session_id = httprequest.session.sid
         self.disable_db = False
         self.uid = None
-        self.endpoint = None
+        self.func = None
+        self.func_arguments = {}
         self.auth_method = None
         self._cr_cm = None
         self._cr = None
-
-        # prevents transaction commit, use when you catch an exception during handling
-        self._failed = None
-
+        self.func_request_type = None
         # set db/uid trackers - they're cleaned up at the WSGI
         # dispatching phase in openerp.service.wsgi_server.application
         if self.db:
@@ -248,51 +182,50 @@ class WebRequest(object):
         _request_stack.pop()
 
         if self._cr:
-            # Dont close test cursors
-            if not openerp.tests.common.release_test_cursor(self._cr):
-                if exc_type is None and not self._failed:
+            # Dont commit test cursors
+            if not openerp.tests.common.release_test_cursor(self.session_id):
+                if exc_type is None:
                     self._cr.commit()
-                else:
-                    # just to be explicit - happens at close() anyway
-                    self._cr.rollback()
                 self._cr.close()
         # just to be sure no one tries to re-use the request
         self.disable_db = True
         self.uid = None
 
-    def set_handler(self, endpoint, arguments, auth):
+    def set_handler(self, func, arguments, auth):
         # is this needed ?
         arguments = dict((k, v) for k, v in arguments.iteritems()
                          if not k.startswith("_ignored_"))
 
-        endpoint.arguments = arguments
-        self.endpoint = endpoint
+        self.func = func
+        self.func_request_type = func.routing['type']
+        self.func_arguments = arguments
         self.auth_method = auth
 
     def _call_function(self, *args, **kwargs):
         request = self
-        if self.endpoint.routing['type'] != self._request_type:
+        if self.func_request_type != self._request_type:
             raise Exception("%s, %s: Function declared as capable of handling request of type '%s' but called with a request of type '%s'" \
-                % (self.endpoint.original, self.httprequest.path, self.endpoint.routing['type'], self._request_type))
+                % (self.func, self.httprequest.path, self.func_request_type, self._request_type))
 
-        kwargs.update(self.endpoint.arguments)
+        kwargs.update(self.func_arguments)
 
         # Backward for 7.0
-        if self.endpoint.first_arg_is_req:
+        if getattr(self.func.method, '_first_arg_is_req', False):
             args = (request,) + args
-
         # Correct exception handling and concurency retry
         @service_model.check
         def checked_call(___dbname, *a, **kw):
-            # The decorator can call us more than once if there is an database error. In this
-            # case, the request cursor is unusable. Rollback transaction to create a new one.
+            return self.func(*a, **kw)
+
+        # FIXME: code and rollback management could be cleaned
+        try:
+            if self.db:
+                return checked_call(self.db, *args, **kwargs)
+            return self.func(*args, **kwargs)
+        except Exception:
             if self._cr:
                 self._cr.rollback()
-            return self.endpoint(*a, **kw)
-
-        if self.db:
-            return checked_call(self.db, *args, **kwargs)
-        return self.endpoint(*args, **kwargs)
+            raise
 
     @property
     def debug(self):
@@ -332,23 +265,8 @@ def route(route=None, **kw):
             else:
                 routes = [route]
             routing['routes'] = routes
-        @functools.wraps(f)
-        def response_wrap(*args, **kw):
-            response = f(*args, **kw)
-            if isinstance(response, Response) or f.routing_type == 'json':
-                return response
-            elif isinstance(response, werkzeug.wrappers.BaseResponse):
-                response = Response.force_type(response)
-                response.set_default()
-                return response
-            elif isinstance(response, basestring):
-                return Response(response)
-            else:
-                _logger.warn("<function %s.%s> returns an invalid response type for an http request" % (f.__module__, f.__name__))
-            return response
-        response_wrap.routing = routing
-        response_wrap.original_func = f
-        return response_wrap
+        f.routing = routing
+        return f
     return decorator
 
 class JsonRequest(WebRequest):
@@ -432,25 +350,21 @@ class JsonRequest(WebRequest):
             response['id'] = self.jsonrequest.get('id')
             response["result"] = self._call_function(**self.params)
         except AuthenticationError, e:
-            _logger.exception("JSON-RPC AuthenticationError in %s.", self.httprequest.path)
+            _logger.exception("Exception during JSON request handling.")
             se = serialize_exception(e)
             error = {
                 'code': 100,
                 'message': "OpenERP Session Invalid",
                 'data': se
             }
-            self._failed = e # prevent tx commit
         except Exception, e:
-            # Mute test cursor error for runbot
-            if not (openerp.tools.config['test_enable'] and isinstance(e, psycopg2.OperationalError)):
-                _logger.exception("JSON-RPC Exception in %s.", self.httprequest.path)
+            _logger.exception("Exception during JSON request handling.")
             se = serialize_exception(e)
             error = {
                 'code': 200,
                 'message': "OpenERP Server Error",
                 'data': se
             }
-            self._failed = e # prevent tx commit
         if error:
             response["error"] = error
 
@@ -465,7 +379,7 @@ class JsonRequest(WebRequest):
             mime = 'application/json'
             body = simplejson.dumps(response)
 
-        r = Response(body, headers=[('Content-Type', mime), ('Content-Length', len(body))])
+        r = werkzeug.wrappers.Response(body, headers=[('Content-Type', mime), ('Content-Length', len(body))])
         return r
 
 def serialize_exception(e):
@@ -523,16 +437,23 @@ class HttpRequest(WebRequest):
         self.params = params
 
     def dispatch(self):
-        if request.httprequest.method == 'OPTIONS' and request.endpoint and request.endpoint.routing.get('cors'):
-            headers = {
-                'Access-Control-Max-Age': 60 * 60 * 24,
-                'Access-Control-Allow-Headers': 'Origin, X-Requested-With, Content-Type, Accept'
-            }
-            return Response(status=200, headers=headers)
+        # TODO: refactor this correctly. This is a quick fix for pos demo.
+        if request.httprequest.method == 'OPTIONS' and request.func and request.func.routing.get('cors'):
+            response = werkzeug.wrappers.Response(status=200)
+            response.headers.set('Access-Control-Allow-Origin', request.func.routing['cors'])
+            methods = 'GET, POST'
+            if request.func_request_type == 'json':
+                methods = 'POST'
+            elif request.func.routing.get('methods'):
+                methods = ', '.join(request.func.routing['methods'])
+            response.headers.set('Access-Control-Allow-Methods', methods)
+            response.headers.set('Access-Control-Max-Age',60*60*24)
+            response.headers.set('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept')
+            return response
 
         r = self._call_function(**self.params)
         if not r:
-            r = Response(status=204)  # no content
+            r = werkzeug.wrappers.Response(status=204)  # no content
         return r
 
     def make_response(self, data, headers=None, cookies=None):
@@ -549,24 +470,12 @@ class HttpRequest(WebRequest):
         :type headers: ``[(name, value)]``
         :param collections.Mapping cookies: cookies to set on the client
         """
-        response = Response(data, headers=headers)
+        response = werkzeug.wrappers.Response(data, headers=headers)
         if cookies:
             for k, v in cookies.iteritems():
                 response.set_cookie(k, v)
         return response
 
-    def render(self, template, qcontext=None, **kw):
-        """ Lazy render of QWeb template.
-
-        The actual rendering of the given template will occur at then end of
-        the dispatching. Meanwhile, the template and/or qcontext can be
-        altered or even replaced by a static response.
-
-        :param basestring template: template to render
-        :param dict qcontext: Rendering context to use
-        """
-        return Response(template=template, qcontext=qcontext, **kw)
-
     def not_found(self, description=None):
         """ Helper for 404 response, return its result from the method
         """
@@ -621,15 +530,7 @@ class Controller(object):
 class EndPoint(object):
     def __init__(self, method, routing):
         self.method = method
-        self.original = getattr(method, 'original_func', method)
         self.routing = routing
-        self.arguments = {}
-
-    @property
-    def first_arg_is_req(self):
-        # Backward for 7.0
-        return getattr(self.method, '_first_arg_is_req', False)
-
     def __call__(self, *args, **kw):
         return self.method(*args, **kw)
 
@@ -652,19 +553,9 @@ def routing_map(modules, nodb_only, converters=None):
                 if inspect.ismethod(mv) and hasattr(mv, 'routing'):
                     routing = dict(type='http', auth='user', methods=None, routes=None)
                     methods_done = list()
-                    routing_type = None
                     for claz in reversed(mv.im_class.mro()):
                         fn = getattr(claz, mv.func_name, None)
                         if fn and hasattr(fn, 'routing') and fn not in methods_done:
-                            fn_type = fn.routing.get('type')
-                            if not routing_type:
-                                routing_type = fn_type
-                            else:
-                                if fn_type and routing_type != fn_type:
-                                    _logger.warn("Subclass re-defines <function %s.%s> with different type than original."
-                                                    " Will use original type: %r", fn.__module__, fn.__name__, routing_type)
-                                fn.routing['type'] = routing_type
-                            fn.original_func.routing_type = routing_type
                             methods_done.append(fn)
                             routing.update(fn.routing)
                     if not nodb_only or nodb_only == (routing['auth'] == "none"):
@@ -692,7 +583,7 @@ class SessionExpiredException(Exception):
 class Service(object):
     """
         .. deprecated:: 8.0
-        Use ``dispatch_rpc()`` instead.
+        Use ``openerp.netsvc.dispatch_rpc()`` instead.
     """
     def __init__(self, session, service_name):
         self.session = session
@@ -700,7 +591,7 @@ class Service(object):
 
     def __getattr__(self, method):
         def proxy_method(*args):
-            result = dispatch_rpc(self.service_name, method, args)
+            result = openerp.netsvc.dispatch_rpc(self.service_name, method, args)
             return result
         return proxy_method
 
@@ -773,7 +664,7 @@ class OpenERPSession(werkzeug.contrib.sessions.Session):
                 HTTP_HOST=wsgienv['HTTP_HOST'],
                 REMOTE_ADDR=wsgienv['REMOTE_ADDR'],
             )
-            uid = dispatch_rpc('common', 'authenticate', [db, login, password, env])
+            uid = openerp.netsvc.dispatch_rpc('common', 'authenticate', [db, login, password, env])
         else:
             security.check(db, uid, password)
         self.db = db
@@ -807,7 +698,7 @@ class OpenERPSession(werkzeug.contrib.sessions.Session):
         self.setdefault("uid", None)
         self.setdefault("login", None)
         self.setdefault("password", None)
-        self.setdefault("context", {})
+        self.setdefault("context", {'tz': "UTC", "uid": None})
 
     def get_context(self):
         """
@@ -877,14 +768,14 @@ class OpenERPSession(werkzeug.contrib.sessions.Session):
     def send(self, service_name, method, *args):
         """
         .. deprecated:: 8.0
-        Use ``dispatch_rpc()`` instead.
+        Use ``openerp.netsvc.dispatch_rpc()`` instead.
         """
-        return dispatch_rpc(service_name, method, args)
+        return openerp.netsvc.dispatch_rpc(service_name, method, args)
 
     def proxy(self, service):
         """
         .. deprecated:: 8.0
-        Use ``dispatch_rpc()`` instead.
+        Use ``openerp.netsvc.dispatch_rpc()`` instead.
         """
         return Service(self, service)
 
@@ -1001,51 +892,19 @@ mimetypes.add_type('application/font-woff', '.woff')
 mimetypes.add_type('application/vnd.ms-fontobject', '.eot')
 mimetypes.add_type('application/x-font-ttf', '.ttf')
 
-class Response(werkzeug.wrappers.Response):
-    """ Response object passed through controller route chain.
-
-    In addition to the werkzeug.wrappers.Response parameters, this
-    classe's constructor can take the following additional parameters
-    for QWeb Lazy Rendering.
-
-    :param basestring template: template to render
-    :param dict qcontext: Rendering context to use
-    :param int uid: User id to use for the ir.ui.view render call
-    """
-    default_mimetype = 'text/html'
-    def __init__(self, *args, **kw):
-        template = kw.pop('template', None)
-        qcontext = kw.pop('qcontext', None)
-        uid = kw.pop('uid', None)
-        super(Response, self).__init__(*args, **kw)
-        self.set_default(template, qcontext, uid)
-
-    def set_default(self, template=None, qcontext=None, uid=None):
-        self.template = template
-        self.qcontext = qcontext or dict()
-        self.uid = uid
-        # Support for Cross-Origin Resource Sharing
-        if request.endpoint and 'cors' in request.endpoint.routing:
-            self.headers.set('Access-Control-Allow-Origin', request.endpoint.routing['cors'])
-            methods = 'GET, POST'
-            if request.endpoint.routing['type'] == 'json':
-                methods = 'POST'
-            elif request.endpoint.routing.get('methods'):
-                methods = ', '.join(request.endpoint.routing['methods'])
-            self.headers.set('Access-Control-Allow-Methods', methods)
-
-    @property
-    def is_qweb(self):
-        return self.template is not None
-
-    def render(self):
-        view_obj = request.registry["ir.ui.view"]
-        uid = self.uid or request.uid or openerp.SUPERUSER_ID
-        return view_obj.render(request.cr, uid, self.template, self.qcontext, context=request.context)
+class LazyResponse(werkzeug.wrappers.Response):
+    """ Lazy werkzeug response.
+    API not yet frozen"""
 
-    def flatten(self):
-        self.response.append(self.render())
-        self.template = None
+    def __init__(self, callback, status_code=None, **kwargs):
+        super(LazyResponse, self).__init__(mimetype='text/html')
+        if status_code:
+            self.status_code = status_code
+        self.callback = callback
+        self.params = kwargs
+    def process(self):
+        response = self.callback(**self.params)
+        self.response.append(response)
 
 class DisableCacheMiddleware(object):
     def __init__(self, app):
@@ -1069,12 +928,33 @@ class DisableCacheMiddleware(object):
             start_response(status, new_headers)
         return self.app(environ, start_wrapped)
 
+def session_path():
+    try:
+        import pwd
+        username = pwd.getpwuid(os.geteuid()).pw_name
+    except ImportError:
+        try:
+            username = getpass.getuser()
+        except Exception:
+            username = "unknown"
+    path = os.path.join(tempfile.gettempdir(), "oe-sessions-" + username)
+    try:
+        os.mkdir(path, 0700)
+    except OSError as exc:
+        if exc.errno == errno.EEXIST:
+            # directory exists: ensure it has the correct permissions
+            # this will fail if the directory is not owned by the current user
+            os.chmod(path, 0700)
+        else:
+            raise
+    return path
+
 class Root(object):
     """Root WSGI application for the OpenERP Web Client.
     """
     def __init__(self):
         # Setup http sessions
-        path = openerp.tools.config.session_dir
+        path = session_path()
         _logger.debug('HTTP sessions stored in: %s', path)
         self.session_store = werkzeug.contrib.sessions.FilesystemSessionStore(path, session_class=OpenERPSession)
 
@@ -1159,9 +1039,9 @@ class Root(object):
             return HttpRequest(httprequest)
 
     def get_response(self, httprequest, result, explicit_session):
-        if isinstance(result, Response) and result.is_qweb:
+        if isinstance(result, LazyResponse):
             try:
-                result.flatten()
+                result.process()
             except(Exception), e:
                 if request.db:
                     result = request.registry['ir.http']._handle_exception(e)
@@ -1169,7 +1049,7 @@ class Root(object):
                     raise
 
         if isinstance(result, basestring):
-            response = Response(result, mimetype='text/html')
+            response = werkzeug.wrappers.Response(result, mimetype='text/html')
         else:
             response = result
 
@@ -1184,6 +1064,16 @@ class Root(object):
         if not explicit_session and hasattr(response, 'set_cookie'):
             response.set_cookie('session_id', httprequest.session.sid, max_age=90 * 24 * 60 * 60)
 
+        # Support for Cross-Origin Resource Sharing
+        if request.func and 'cors' in request.func.routing:
+            response.headers.set('Access-Control-Allow-Origin', request.func.routing['cors'])
+            methods = 'GET, POST'
+            if request.func_request_type == 'json':
+                methods = 'POST'
+            elif request.func.routing.get('methods'):
+                methods = ', '.join(request.func.routing['methods'])
+            response.headers.set('Access-Control-Allow-Methods', methods)
+
         return response
 
     def dispatch(self, environ, start_response):
@@ -1237,12 +1127,12 @@ class Root(object):
         return request.registry['ir.http'].routing_map()
 
 def db_list(force=False, httprequest=None):
-    dbs = dispatch_rpc("db", "list", [force])
+    dbs = openerp.netsvc.dispatch_rpc("db", "list", [force])
     return db_filter(dbs, httprequest=httprequest)
 
 def db_filter(dbs, httprequest=None):
     httprequest = httprequest or request.httprequest
-    h = httprequest.environ.get('HTTP_HOST', '').split(':')[0]
+    h = httprequest.environ['HTTP_HOST'].split(':')[0]
     d = h.split('.')[0]
     r = openerp.tools.config['dbfilter'].replace('%h', h).replace('%d', d)
     dbs = [i for i in dbs if re.match(r, i)]
@@ -1282,7 +1172,12 @@ class CommonController(Controller):
     @route('/jsonrpc', type='json', auth="none")
     def jsonrpc(self, service, method, args):
         """ Method used by client APIs to contact OpenERP. """
-        return dispatch_rpc(service, method, args)
+        return openerp.netsvc.dispatch_rpc(service, method, args)
+
+    @route('/gen_session_id', type='json', auth="none")
+    def gen_session_id(self):
+        nsession = root.session_store.new()
+        return nsession.sid
 
 root = None
 
index 681d853..7ca0a67 100644 (file)
@@ -187,10 +187,6 @@ def load_module_graph(cr, graph, status=None, perform_checks=True, skip_modules=
                     # Yamel test
                     report.record_result(load_test(module_name, idref, mode))
                     # Python tests
-                    ir_http = registry['ir.http']
-                    if hasattr(ir_http, '_routing_map'):
-                        # Force routing map to be rebuilt between each module test suite
-                        del(ir_http._routing_map)
                     report.record_result(openerp.modules.module.run_unit_tests(module_name, cr.dbname))
 
             processed_modules.append(package.name)
index 8958813..a443a25 100644 (file)
@@ -3,7 +3,7 @@
 #
 #    OpenERP, Open Source Management Solution
 #    Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>).
-#    Copyright (C) 2010-2014 OpenERP s.a. (<http://openerp.com>).
+#    Copyright (C) 2010-2012 OpenERP s.a. (<http://openerp.com>).
 #
 #    This program is free software: you can redistribute it and/or modify
 #    it under the terms of the GNU Affero General Public License as
@@ -38,6 +38,10 @@ import openerp.release as release
 from openerp.tools.safe_eval import safe_eval as eval
 
 _logger = logging.getLogger(__name__)
+_test_logger = logging.getLogger('openerp.tests')
+
+# addons path ','.joined
+_ad = os.path.join(os.path.dirname(os.path.dirname(__file__)), 'addons') # default addons path (base)
 
 # addons path as a list
 ad_paths = []
@@ -86,13 +90,8 @@ def initialize_sys_path():
     if ad_paths:
         return
 
-    ad_paths = [tools.config.addons_data_dir]
-    ad_paths += map(lambda m: os.path.abspath(tools.ustr(m.strip())), tools.config['addons_path'].split(','))
-
-    # add base module path
-    base_path = os.path.abspath(os.path.join(os.path.dirname(os.path.dirname(__file__)), 'addons'))
-    ad_paths += [base_path]
-
+    ad_paths = map(lambda m: os.path.abspath(tools.ustr(m.strip())), tools.config['addons_path'].split(','))
+    ad_paths.append(os.path.abspath(_ad)) # for get_module_path
     sys.meta_path.append(AddonsImportHook())
 
 def get_module_path(module, downloaded=False, display_warning=True):
@@ -109,7 +108,7 @@ def get_module_path(module, downloaded=False, display_warning=True):
             return opj(adp, module)
 
     if downloaded:
-        return opj(tools.config.addons_data_dir, module)
+        return opj(_ad, module)
     if display_warning:
         _logger.warning('module %s: module not found', module)
     return False
@@ -339,8 +338,7 @@ def get_test_modules(module):
 
 # Use a custom stream object to log the test executions.
 class TestStream(object):
-    def __init__(self, logger_name='openerp.tests'):
-        self.logger = logging.getLogger(logger_name)
+    def __init__(self):
         self.r = re.compile(r'^-*$|^ *... *$|^ok$')
     def flush(self):
         pass
@@ -352,7 +350,7 @@ class TestStream(object):
             if not first:
                 c = '` ' + c
             first = False
-            self.logger.info(c)
+            _test_logger.info(c)
 
 current_test = None
 
@@ -369,9 +367,9 @@ def run_unit_tests(module_name, dbname):
     for m in mods:
         tests = unwrap_suite(unittest2.TestLoader().loadTestsFromModule(m))
         suite = unittest2.TestSuite(itertools.ifilter(runs_at_install, tests))
-        _logger.info('running %s tests.', m.__name__)
+        _logger.info('module %s: running test %s.', module_name, m.__name__)
 
-        result = unittest2.TextTestRunner(verbosity=2, stream=TestStream(m.__name__)).run(suite)
+        result = unittest2.TextTestRunner(verbosity=2, stream=TestStream()).run(suite)
 
         if not result.wasSuccessful():
             r = False
index d762eb5..755f651 100644 (file)
@@ -2,7 +2,7 @@
 ##############################################################################
 #
 #    OpenERP, Open Source Management Solution
-#    Copyright (C) 2004-2014 OpenERP SA (<http://www.openerp.com>)
+#    Copyright (C) 2004-2012 OpenERP SA (<http://www.openerp.com>)
 #
 #    This program is free software: you can redistribute it and/or modify
 #    it under the terms of the GNU Affero General Public License as
 #
 ##############################################################################
 
+
 import logging
 import logging.handlers
 import os
-import pprint
 import release
 import sys
 import threading
+import time
+import types
+from pprint import pformat
+import psutil
 
-import psycopg2
-
-import openerp
-import sql_db
 import tools
+import openerp
 
 _logger = logging.getLogger(__name__)
 
-def log(logger, level, prefix, msg, depth=None):
-    indent=''
-    indent_after=' '*len(prefix)
-    for line in (prefix + pprint.pformat(msg, depth=depth)).split('\n'):
-        logger.log(level, indent+line)
-        indent=indent_after
-
 def LocalService(name):
     """
     The openerp.netsvc.LocalService() function is deprecated. It still works
@@ -68,36 +62,6 @@ def LocalService(name):
                 with registry.cursor() as cr:
                     return registry['ir.actions.report.xml']._lookup_report(cr, name[len('report.'):])
 
-class PostgreSQLHandler(logging.Handler):
-    """ PostgreSQL Loggin Handler will store logs in the database, by default
-    the current database, can be set using --log-db=DBNAME
-    """
-    def emit(self, record):
-        ct = threading.current_thread()
-        ct_db = getattr(ct, 'dbname', None)
-        ct_uid = getattr(ct, 'uid', None)
-        dbname = tools.config['log_db'] or ct_db
-        if dbname:
-            cr = None
-            try:
-                cr = sql_db.db_connect(dbname).cursor()
-                msg = unicode(record.msg)
-                traceback = getattr(record, 'exc_text', '')
-                if traceback:
-                    msg = "%s\n%s" % (msg, traceback)
-                level = logging.getLevelName(record.levelno)
-                val = (ct_uid, ct_uid, 'server', dbname, record.name, level, msg, record.pathname, record.lineno, record.funcName)
-                cr.execute("""
-                    INSERT INTO ir_logging(create_date, write_date, create_uid, write_uid, type, dbname, name, level, message, path, line, func)
-                    VALUES (NOW() at time zone 'UTC', NOW() at time zone 'UTC', %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)
-                """, val )
-                cr.commit()
-            except Exception, e:
-                pass
-            finally:
-                if cr:
-                    cr.close()
-
 BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE, _NOTHING, DEFAULT = range(10)
 #The background is set with 40 plus the number of the color, and the foreground with 30
 #These are the sequences need to get colored ouput
@@ -125,13 +89,7 @@ class ColoredFormatter(DBFormatter):
         record.levelname = COLOR_PATTERN % (30 + fg_color, 40 + bg_color, record.levelname)
         return DBFormatter.format(self, record)
 
-_logger_init = False
 def init_logger():
-    global _logger_init
-    if _logger_init:
-        return
-    _logger_init = True
-
     from tools.translate import resetlocale
     resetlocale()
 
@@ -143,7 +101,7 @@ def init_logger():
         if os.name == 'nt':
             handler = logging.handlers.NTEventLogHandler("%s %s" % (release.description, release.version))
         else:
-            handler = logging.handlers.SysLogHandler()
+            handler = logging.handlers.SysLogHandler('/dev/log')
         format = '%s %s' % (release.description, release.version) \
                 + ':%(dbname)s:%(levelname)s:%(name)s:%(message)s'
 
@@ -151,12 +109,11 @@ def init_logger():
         # LogFile Handler
         logf = tools.config['logfile']
         try:
-            # We check we have the right location for the log files
             dirname = os.path.dirname(logf)
             if dirname and not os.path.isdir(dirname):
                 os.makedirs(dirname)
             if tools.config['logrotate'] is not False:
-                handler = logging.handlers.TimedRotatingFileHandler(filename=logf, when='D', interval=1, backupCount=30)
+                handler = logging.handlers.TimedRotatingFileHandler(logf,'D',1,30)
             elif os.name == 'posix':
                 handler = logging.handlers.WatchedFileHandler(logf)
             else:
@@ -172,23 +129,15 @@ def init_logger():
     # behind Apache with mod_wsgi, handler.stream will have type mod_wsgi.Log,
     # which has no fileno() method. (mod_wsgi.Log is what is being bound to
     # sys.stderr when the logging.StreamHandler is being constructed above.)
-    def is_a_tty(stream):
-        return hasattr(stream, 'fileno') and os.isatty(stream.fileno())
-
-    if isinstance(handler, logging.StreamHandler) and is_a_tty(handler.stream):
+    if isinstance(handler, logging.StreamHandler) \
+        and hasattr(handler.stream, 'fileno') \
+        and os.isatty(handler.stream.fileno()):
         formatter = ColoredFormatter(format)
     else:
         formatter = DBFormatter(format)
     handler.setFormatter(formatter)
 
-    logging.getLogger().addHandler(handler)
-
-    if tools.config['log_db']:
-        postgresqlHandler = PostgreSQLHandler()
-        postgresqlHandler.setLevel(logging.WARNING)
-        logging.getLogger().addHandler(postgresqlHandler)
-
-    # Configure loggers levels
+    # Configure handlers
     pseudo_config = PSEUDOCONFIG_MAPPER.get(tools.config['log_level'], [])
 
     logconfig = tools.config['log_handler']
@@ -198,22 +147,26 @@ def init_logger():
         loggername, level = logconfig_item.split(':')
         level = getattr(logging, level, logging.INFO)
         logger = logging.getLogger(loggername)
+        logger.handlers = []
         logger.setLevel(level)
+        logger.addHandler(handler)
+        if loggername != '':
+            logger.propagate = False
 
     for logconfig_item in logging_configurations:
         _logger.debug('logger level set: "%s"', logconfig_item)
 
 DEFAULT_LOG_CONFIGURATION = [
     'openerp.workflow.workitem:WARNING',
-    'openerp.http.rpc.request:INFO',
-    'openerp.http.rpc.response:INFO',
+    'openerp.netsvc.rpc.request:INFO',
+    'openerp.netsvc.rpc.response:INFO',
     'openerp.addons.web.http:INFO',
     'openerp.sql_db:INFO',
     ':INFO',
 ]
 PSEUDOCONFIG_MAPPER = {
-    'debug_rpc_answer': ['openerp:DEBUG','openerp.http.rpc.request:DEBUG', 'openerp.http.rpc.response:DEBUG'],
-    'debug_rpc': ['openerp:DEBUG','openerp.http.rpc.request:DEBUG'],
+    'debug_rpc_answer': ['openerp:DEBUG','openerp.netsvc.rpc.request:DEBUG', 'openerp.netsvc.rpc.response:DEBUG'],
+    'debug_rpc': ['openerp:DEBUG','openerp.netsvc.rpc.request:DEBUG'],
     'debug': ['openerp:DEBUG'],
     'debug_sql': ['openerp.sql_db:DEBUG'],
     'info': [],
@@ -222,4 +175,99 @@ PSEUDOCONFIG_MAPPER = {
     'critical': ['openerp:CRITICAL'],
 }
 
+# A alternative logging scheme for automated runs of the
+# server intended to test it.
+def init_alternative_logger():
+    class H(logging.Handler):
+        def emit(self, record):
+            if record.levelno > 20:
+                print record.levelno, record.pathname, record.msg
+    handler = H()
+    # Add the handler to the 'openerp' logger.
+    logger = logging.getLogger('openerp')
+    logger.addHandler(handler)
+    logger.setLevel(logging.ERROR)
+
+def replace_request_password(args):
+    # password is always 3rd argument in a request, we replace it in RPC logs
+    # so it's easier to forward logs for diagnostics/debugging purposes...
+    if len(args) > 2:
+        args = list(args)
+        args[2] = '*'
+    return tuple(args)
+
+def log(logger, level, prefix, msg, depth=None):
+    indent=''
+    indent_after=' '*len(prefix)
+    for line in (prefix+pformat(msg, depth=depth)).split('\n'):
+        logger.log(level, indent+line)
+        indent=indent_after
+
+def dispatch_rpc(service_name, method, params):
+    """ Handle a RPC call.
+
+    This is pure Python code, the actual marshalling (from/to XML-RPC) is done
+    in a upper layer.
+    """
+    try:
+        rpc_request = logging.getLogger(__name__ + '.rpc.request')
+        rpc_response = logging.getLogger(__name__ + '.rpc.response')
+        rpc_request_flag = rpc_request.isEnabledFor(logging.DEBUG)
+        rpc_response_flag = rpc_response.isEnabledFor(logging.DEBUG)
+        if rpc_request_flag or rpc_response_flag:
+            start_time = time.time()
+            start_rss, start_vms = 0, 0
+            start_rss, start_vms = psutil.Process(os.getpid()).get_memory_info()
+            if rpc_request and rpc_response_flag:
+                log(rpc_request,logging.DEBUG,'%s.%s'%(service_name,method), replace_request_password(params))
+
+        threading.current_thread().uid = None
+        threading.current_thread().dbname = None
+        if service_name == 'common':
+            dispatch = openerp.service.common.dispatch
+        elif service_name == 'db':
+            dispatch = openerp.service.db.dispatch
+        elif service_name == 'object':
+            dispatch = openerp.service.model.dispatch
+        elif service_name == 'report':
+            dispatch = openerp.service.report.dispatch
+        else:
+            dispatch = openerp.service.wsgi_server.rpc_handlers.get(service_name)
+        result = dispatch(method, params)
+
+        if rpc_request_flag or rpc_response_flag:
+            end_time = time.time()
+            end_rss, end_vms = 0, 0
+            end_rss, end_vms = psutil.Process(os.getpid()).get_memory_info()
+            logline = '%s.%s time:%.3fs mem: %sk -> %sk (diff: %sk)' % (service_name, method, end_time - start_time, start_vms / 1024, end_vms / 1024, (end_vms - start_vms)/1024)
+            if rpc_response_flag:
+                log(rpc_response,logging.DEBUG, logline, result)
+            else:
+                log(rpc_request,logging.DEBUG, logline, replace_request_password(params), depth=1)
+
+        return result
+    except openerp.osv.orm.except_orm:
+        raise
+    except openerp.exceptions.AccessError:
+        raise
+    except openerp.exceptions.AccessDenied:
+        raise
+    except openerp.exceptions.Warning:
+        raise
+    except openerp.exceptions.RedirectWarning:
+        raise
+    except openerp.exceptions.DeferredException, e:
+        _logger.exception(tools.exception_to_unicode(e))
+        post_mortem(e.traceback)
+        raise
+    except Exception, e:
+        _logger.exception(tools.exception_to_unicode(e))
+        post_mortem(sys.exc_info())
+        raise
+
+def post_mortem(info):
+    if tools.config['debug_mode'] and isinstance(info[2], types.TracebackType):
+        import pdb
+        pdb.post_mortem(info[2])
+
 # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
index d5d0ee0..478f982 100644 (file)
@@ -236,24 +236,15 @@ class char(_column):
 class text(_column):
     _type = 'text'
 
-
 class html(text):
     _type = 'html'
     _symbol_c = '%s'
-
-    def _symbol_set_html(self, value):
-        if value is None or value is False:
+    def _symbol_f(x):
+        if x is None or x == False:
             return None
-        if not self._sanitize:
-            return value
-        return html_sanitize(value)
-
-    def __init__(self, string='unknown', sanitize=True, **args):
-        super(html, self).__init__(string=string, **args)
-        self._sanitize = sanitize
-        # symbol_set redefinition because of sanitize specific behavior
-        self._symbol_f = self._symbol_set_html
-        self._symbol_set = (self._symbol_c, self._symbol_f)
+        return html_sanitize(x)
+        
+    _symbol_set = (_symbol_c, _symbol_f)
 
 import __builtin__
 
index 64fa067..3126507 100644 (file)
@@ -75,7 +75,7 @@ _schema = logging.getLogger(__name__ + '.schema')
 # List of etree._Element subclasses that we choose to ignore when parsing XML.
 from openerp.tools import SKIPPED_ELEMENT_TYPES
 
-regex_order = re.compile('^( *([a-z0-9_]+|"[a-z0-9_]+")( *desc| *asc)?( *, *|))+$', re.I)
+regex_order = re.compile('^(([a-z0-9_]+|"[a-z0-9_]+")( *desc| *asc)?( *, *|))+$', re.I)
 regex_object_name = re.compile(r'^[a-z0-9_.]+$')
 
 AUTOINIT_RECALCULATE_STORED_FIELDS = 1000
@@ -1124,7 +1124,7 @@ class BaseModel(object):
 
         def _get_xml_id(self, cr, uid, r):
             model_data = self.pool.get('ir.model.data')
-            data_ids = model_data.search(cr, uid, [('model', '=', r._model._name), ('res_id', '=', r['id'])])
+            data_ids = model_data.search(cr, uid, [('model', '=', r._table_name), ('res_id', '=', r['id'])])
             if len(data_ids):
                 d = model_data.read(cr, uid, data_ids, ['name', 'module'])[0]
                 if d['module']:
@@ -1134,13 +1134,13 @@ class BaseModel(object):
             else:
                 postfix = 0
                 while True:
-                    n = r._model._table+'_'+str(r['id']) + (postfix and ('_'+str(postfix)) or '' )
+                    n = self._table+'_'+str(r['id']) + (postfix and ('_'+str(postfix)) or '' )
                     if not model_data.search(cr, uid, [('name', '=', n)]):
                         break
                     postfix += 1
                 model_data.create(cr, SUPERUSER_ID, {
                     'name': n,
-                    'model': r._model._name,
+                    'model': self._name,
                     'res_id': r['id'],
                     'module': '__export__',
                 })
@@ -2185,42 +2185,36 @@ class BaseModel(object):
                 r['__fold'] = folded.get(r[groupby] and r[groupby][0], False)
         return result
 
-    def _read_group_prepare(self, orderby, aggregated_fields, groupby, qualified_groupby_field, query, groupby_type=None):
+    def _read_group_generate_order_by(self, orderby, aggregated_fields, groupby, query):
         """
-        Prepares the GROUP BY and ORDER BY terms for the read_group method. Adds the missing JOIN clause
+        Generates the ORDER BY sql clause for the read group method. Adds the missing JOIN clause
         to the query if order should be computed against m2o field. 
         :param orderby: the orderby definition in the form "%(field)s %(order)s"
         :param aggregated_fields: list of aggregated fields in the query
         :param groupby: the current groupby field name
-        :param qualified_groupby_field: the fully qualified SQL name for the grouped field
-        :param osv.Query query: the query under construction
-        :param groupby_type: the type of the grouped field
-        :return: (groupby_terms, orderby_terms)
+        :param query: the query object used to construct the query afterwards
         """
-        orderby_terms = []
-        groupby_terms = [qualified_groupby_field] if groupby else []
-        if not orderby:
-            return groupby_terms, orderby_terms    
-
-        self._check_qorder(orderby)
-        for order_part in orderby.split(','):
-            order_split = order_part.split()
-            order_field = order_split[0]
-            if order_field == groupby:
-                if groupby_type == 'many2one':
-                    order_clause = self._generate_order_by(order_part, query).replace('ORDER BY ', '')
-                    if order_clause:
-                        orderby_terms.append(order_clause)
-                        groupby_terms += [order_term.split()[0] for order_term in order_clause.split(',')]
-                else:
-                    orderby_terms.append(order_part)
-            elif order_field in aggregated_fields:
-                orderby_terms.append(order_part)
-            else:
-                # Cannot order by a field that will not appear in the results (needs to be grouped or aggregated)
-                _logger.warn('%s: read_group order by `%s` ignored, cannot sort on empty columns (not grouped/aggregated)',
-                             self._name, order_part)
-        return groupby_terms, orderby_terms
+        orderby_list = []
+        ob = []
+        for order_splits in orderby.split(','):
+            order_split = order_splits.split()
+            orderby_field = order_split[0]
+            fields = openerp.osv.fields
+            if isinstance(self._all_columns[orderby_field].column, (fields.date, fields.datetime)):
+                continue
+            orderby_dir = len(order_split) == 2 and order_split[1].upper() == 'ASC' and 'ASC' or 'DESC'
+            if orderby_field == groupby:
+                orderby_item = self._generate_order_by(order_splits, query).replace('ORDER BY ', '')
+                if orderby_item:
+                    orderby_list.append(orderby_item)
+                    ob += [obi.split()[0] for obi in orderby_item.split(',')]
+            elif orderby_field in aggregated_fields:
+                orderby_list.append('%s %s' % (orderby_field,orderby_dir))
+
+        if orderby_list:
+            return ' ORDER BY %s' % (','.join(orderby_list)), ob and ','.join(ob) or ''
+        else:
+            return '', ''
 
     def read_group(self, cr, uid, domain, fields, groupby, offset=0, limit=None, context=None, orderby=False):
         """
@@ -2281,9 +2275,9 @@ class BaseModel(object):
 
         # TODO it seems fields_get can be replaced by _all_columns (no need for translation)
         fget = self.fields_get(cr, uid, fields)
+        flist = ''
+        group_count = group_by = groupby
         group_by_params = {}
-        select_terms = []
-        groupby_type = None
         if groupby:
             if fget.get(groupby):
                 groupby_type = fget[groupby]['type']
@@ -2311,9 +2305,12 @@ class BaseModel(object):
                         timezone = context.get('tz', 'UTC')
                         qualified_groupby_field = "timezone('%s', timezone('UTC',%s))" % (timezone, qualified_groupby_field)
                     qualified_groupby_field = "date_trunc('%s', %s)" % (interval, qualified_groupby_field)
+                    flist = "%s as %s " % (qualified_groupby_field, groupby)
                 elif groupby_type == 'boolean':
                     qualified_groupby_field = "coalesce(%s,false)" % qualified_groupby_field
-                select_terms.append("%s as %s " % (qualified_groupby_field, groupby))
+                    flist = "%s as %s " % (qualified_groupby_field, groupby)
+                else:
+                    flist = qualified_groupby_field
             else:
                 # Don't allow arbitrary values, as this would be a SQL injection vector!
                 raise except_orm(_('Invalid group_by'),
@@ -2321,48 +2318,34 @@ class BaseModel(object):
 
         aggregated_fields = [
             f for f in fields
-            if f not in ('id', 'sequence', groupby)
+            if f not in ('id', 'sequence')
             if fget[f]['type'] in ('integer', 'float')
             if (f in self._all_columns and getattr(self._all_columns[f].column, '_classic_write'))]
         for f in aggregated_fields:
             group_operator = fget[f].get('group_operator', 'sum')
+            if flist:
+                flist += ', '
             qualified_field = self._inherits_join_calc(f, query)
-            select_terms.append("%s(%s) AS %s" % (group_operator, qualified_field, f))
+            flist += "%s(%s) AS %s" % (group_operator, qualified_field, f)
+
+        order = orderby or groupby
+        orderby_clause = ''
+        ob = ''
+        if order:
+            orderby_clause, ob = self._read_group_generate_order_by(order, aggregated_fields, groupby, query)
 
-        order = orderby or groupby or ''
-        groupby_terms, orderby_terms = self._read_group_prepare(order, aggregated_fields, groupby, qualified_groupby_field, query, groupby_type)
+        gb = groupby and (' GROUP BY ' + qualified_groupby_field) or ''
 
         from_clause, where_clause, where_clause_params = query.get_sql()
+        where_clause = where_clause and ' WHERE ' + where_clause
+        limit_str = limit and ' limit %d' % limit or ''
+        offset_str = offset and ' offset %d' % offset or ''
         if len(groupby_list) < 2 and context.get('group_by_no_leaf'):
-            count_field = '_'
-        else:
-            count_field = groupby
-
-        prefix_terms = lambda prefix, terms: (prefix + " " + ",".join(terms)) if terms else ''
-        prefix_term = lambda prefix, term: ('%s %s' % (prefix, term)) if term else ''
-
-        query = """
-            SELECT min(%(table)s.id) AS id, count(%(table)s.id) AS %(count_field)s_count
-                   %(extra_fields)s
-            FROM %(from)s
-            %(where)s
-            %(groupby)s
-            %(orderby)s
-            %(limit)s
-            %(offset)s
-        """ % {
-            'table': self._table,
-            'count_field': count_field,
-            'extra_fields': prefix_terms(',', select_terms),
-            'from': from_clause,
-            'where': prefix_term('WHERE', where_clause),
-            'groupby': prefix_terms('GROUP BY', groupby_terms),
-            'orderby': prefix_terms('ORDER BY', orderby_terms),
-            'limit': prefix_term('LIMIT', int(limit) if limit else None),
-            'offset': prefix_term('OFFSET', int(offset) if limit else None),
-        }
-        cr.execute(query, where_clause_params)
+            group_count = '_'
+        cr.execute('SELECT min(%s.id) AS id, count(%s.id) AS %s_count' % (self._table, self._table, group_count) + (flist and ',') + flist + ' FROM ' + from_clause + where_clause + gb + (ob and ',') + ob + orderby_clause + limit_str + offset_str, where_clause_params)
         alldata = {}
+        groupby = group_by
+
         fetched_data = cr.dictfetchall()
 
         data_ids = []
@@ -2373,6 +2356,8 @@ class BaseModel(object):
             data_ids.append(r['id'])
             del r['id']
 
+
+
         if groupby:
             data = self.read(cr, uid, data_ids, [groupby], context=context)
             # restore order of the search as read() uses the default _order (this is only for groups, so the footprint of data should be small):
@@ -2862,7 +2847,7 @@ class BaseModel(object):
                                 msg = "Table '%s': dropping index for column '%s' of type '%s' as it is not required anymore"
                                 _schema.debug(msg, self._table, k, f._type)
 
-                            if isinstance(f, fields.many2one) or (isinstance(f, fields.function) and f._type == 'many2one' and f.store):
+                            if isinstance(f, fields.many2one):
                                 dest_model = self.pool[f._obj]
                                 if dest_model._table != 'ir_actions':
                                     self._m2o_fix_foreign_key(cr, self._table, k, dest_model, f.ondelete)
@@ -2897,7 +2882,7 @@ class BaseModel(object):
                                 todo_end.append((order, self._update_store, (f, k)))
 
                             # and add constraints if needed
-                            if isinstance(f, fields.many2one) or (isinstance(f, fields.function) and f._type == 'many2one' and f.store):
+                            if isinstance(f, fields.many2one):
                                 if f._obj not in self.pool:
                                     raise except_orm('Programming Error', 'There is no reference available for %s' % (f._obj,))
                                 dest_model = self.pool[f._obj]
index 1a9c863..1ad3534 100644 (file)
@@ -32,7 +32,7 @@ RELEASE_LEVELS_DISPLAY = {ALPHA: ALPHA,
 #  (6,1,0,'candidate',2) < (6,1,0,'final',0) < (6,1,2,'final',0)
 version_info = (8, 0, 0, ALPHA, 1)
 version = '.'.join(map(str, version_info[:2])) + RELEASE_LEVELS_DISPLAY[version_info[3]] + str(version_info[4] or '')
-series = serie = major_version = '.'.join(map(str, version_info[:2]))
+serie = major_version = '.'.join(map(str, version_info[:2]))
 
 description = 'OpenERP Server'
 long_desc = '''OpenERP is a complete ERP and CRM. The main features are accounting (analytic
@@ -50,6 +50,6 @@ author = 'OpenERP S.A.'
 author_email = 'info@openerp.com'
 license = 'AGPL-3'
 
-nt_service_name = "openerp-server-" + series
+nt_service_name = "openerp-server-" + serie
 
 # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
index f10f39a..adbd058 100644 (file)
@@ -1,15 +1,12 @@
 # -*- coding: utf-8 -*-
-from contextlib import closing
-from functools import wraps
+
+import base64
+import contextlib
 import logging
 import os
-import shutil
 import threading
 import traceback
-import tempfile
-import zipfile
-
-import psycopg2
+from contextlib import contextmanager, closing
 
 import openerp
 from openerp import SUPERUSER_ID
@@ -31,8 +28,7 @@ def _initialize_db(id, db_name, demo, lang, user_password):
         self_actions[id]['progress'] = 0
         db = openerp.sql_db.db_connect(db_name)
         with closing(db.cursor()) as cr:
-            # TODO this should be removed as it is done by RegistryManager.new().
-            openerp.modules.db.initialize(cr)
+            openerp.modules.db.initialize(cr) # TODO this should be removed as it is done by RegistryManager.new().
             openerp.tools.config['lang'] = lang
             cr.commit()
 
@@ -59,13 +55,14 @@ def _initialize_db(id, db_name, demo, lang, user_password):
         self_actions[id]['traceback'] = traceback.format_exc()
 
 def dispatch(method, params):
-    if method in ['create', 'get_progress', 'drop', 'dump', 'restore', 'rename',
-                  'change_admin_password', 'migrate_databases',
-                  'create_database', 'duplicate_database']:
+    if method in [ 'create', 'get_progress', 'drop', 'dump',
+        'restore', 'rename',
+        'change_admin_password', 'migrate_databases',
+        'create_database', 'duplicate_database' ]:
         passwd = params[0]
         params = params[1:]
         security.check_super(passwd)
-    elif method in ['db_exist', 'list', 'list_lang', 'server_version']:
+    elif method in [ 'db_exist', 'list', 'list_lang', 'server_version' ]:
         # params = params
         # No security check for these methods
         pass
@@ -81,9 +78,9 @@ def _create_empty_database(name):
         cr.execute("SELECT datname FROM pg_database WHERE datname = %s",
                    (name,))
         if cr.fetchall():
-            raise openerp.exceptions.Warning("database %r already exists!" % (name,))
+            raise openerp.exceptions.Warning(" %s database already exists!" % name )
         else:
-            cr.autocommit(True)     # avoid transaction block
+            cr.autocommit(True) # avoid transaction block
             cr.execute("""CREATE DATABASE "%s" ENCODING 'unicode' TEMPLATE "%s" """ % (name, chosen_template))
 
 def exp_create(db_name, demo, lang, user_password='admin'):
@@ -99,7 +96,7 @@ def exp_create(db_name, demo, lang, user_password='admin'):
 
     _logger.info('CREATE DATABASE %s', db_name.lower())
     create_thread = threading.Thread(target=_initialize_db,
-                                     args=(id, db_name, demo, lang, user_password))
+            args=(id, db_name, demo, lang, user_password))
     create_thread.start()
     self_actions[id]['thread'] = create_thread
     return id
@@ -124,14 +121,14 @@ def exp_duplicate_database(db_original_name, db_name):
     openerp.sql_db.close_db(db_original_name)
     db = openerp.sql_db.db_connect('postgres')
     with closing(db.cursor()) as cr:
-        cr.autocommit(True)     # avoid transaction block
+        cr.autocommit(True) # avoid transaction block
         cr.execute("""CREATE DATABASE "%s" ENCODING 'unicode' TEMPLATE "%s" """ % (db_name, db_original_name))
     return True
 
 def exp_get_progress(id):
     if self_actions[id]['thread'].isAlive():
 #       return openerp.modules.init_progress[db_name]
-        return min(self_actions[id].get('progress', 0), 0.95), []
+        return min(self_actions[id].get('progress', 0),0.95), []
     else:
         clean = self_actions[id]['clean']
         if clean:
@@ -143,9 +140,9 @@ def exp_get_progress(id):
             self_actions.pop(id)
             return 1.0, users
         else:
-            a = self_actions.pop(id)
-            exc, tb = a['exception'], a['traceback']
-            raise Exception, exc, tb
+            e = self_actions[id]['exception'] # TODO this seems wrong: actions[id]['traceback'] is set, but not 'exception'.
+            self_actions.pop(id)
+            raise Exception, e
 
 def exp_drop(db_name):
     if db_name not in exp_list(True):
@@ -155,17 +152,18 @@ def exp_drop(db_name):
 
     db = openerp.sql_db.db_connect('postgres')
     with closing(db.cursor()) as cr:
-        cr.autocommit(True)     # avoid transaction block
+        cr.autocommit(True) # avoid transaction block
         # Try to terminate all other connections that might prevent
         # dropping the database
         try:
+
             # PostgreSQL 9.2 renamed pg_stat_activity.procpid to pid:
             # http://www.postgresql.org/docs/9.2/static/release-9-2.html#AEN110389
             pid_col = 'pid' if cr._cnx.server_version >= 90200 else 'procpid'
 
             cr.execute("""SELECT pg_terminate_backend(%(pid_col)s)
                           FROM pg_stat_activity
-                          WHERE datname = %%s AND
+                          WHERE datname = %%s AND 
                                 %(pid_col)s != pg_backend_pid()""" % {'pid_col': pid_col},
                        (db_name,))
         except Exception:
@@ -180,140 +178,94 @@ def exp_drop(db_name):
             _logger.info('DROP DB: %s', db_name)
     return True
 
-def _set_pg_password_in_environment(func):
+@contextlib.contextmanager
+def _set_pg_password_in_environment():
     """ On systems where pg_restore/pg_dump require an explicit
     password (i.e. when not connecting via unix sockets, and most
     importantly on Windows), it is necessary to pass the PG user
     password in the environment or in a special .pgpass file.
 
-    This decorator handles setting
+    This context management method handles setting
     :envvar:`PGPASSWORD` if it is not already
     set, and removing it afterwards.
 
     See also http://www.postgresql.org/docs/8.4/static/libpq-envars.html
-
+    
     .. note:: This is not thread-safe, and should never be enabled for
          SaaS (giving SaaS users the super-admin password is not a good idea
          anyway)
     """
-    @wraps(func)
-    def wrapper(*args, **kwargs):
-        if os.environ.get('PGPASSWORD') or not openerp.tools.config['db_password']:
-            return func(*args, **kwargs)
-        else:
-            os.environ['PGPASSWORD'] = openerp.tools.config['db_password']
-            try:
-                return func(*args, **kwargs)
-            finally:
-                del os.environ['PGPASSWORD']
-    return wrapper
+    if os.environ.get('PGPASSWORD') or not openerp.tools.config['db_password']:
+        yield
+    else:
+        os.environ['PGPASSWORD'] = openerp.tools.config['db_password']
+        try:
+            yield
+        finally:
+            del os.environ['PGPASSWORD']
+
 
 def exp_dump(db_name):
-    with tempfile.TemporaryFile() as t:
-        dump_db(db_name, t)
-        t.seek(0)
-        return t.read().encode('base64')
-
-@_set_pg_password_in_environment
-def dump_db(db, stream):
-    """Dump database `db` into file-like object `stream`"""
-    with openerp.tools.osutil.tempdir() as dump_dir:
-        registry = openerp.modules.registry.RegistryManager.get(db)
-        with registry.cursor() as cr:
-            filestore = registry['ir.attachment']._filestore(cr, SUPERUSER_ID)
-            if os.path.exists(filestore):
-                shutil.copytree(filestore, os.path.join(dump_dir, 'filestore'))
-
-        dump_file = os.path.join(dump_dir, 'dump.sql')
-        cmd = ['pg_dump', '--format=p', '--no-owner', '--file=' + dump_file]
+    with _set_pg_password_in_environment():
+        cmd = ['pg_dump', '--format=c', '--no-owner']
         if openerp.tools.config['db_user']:
             cmd.append('--username=' + openerp.tools.config['db_user'])
         if openerp.tools.config['db_host']:
             cmd.append('--host=' + openerp.tools.config['db_host'])
         if openerp.tools.config['db_port']:
             cmd.append('--port=' + str(openerp.tools.config['db_port']))
-        cmd.append(db)
-
-        if openerp.tools.exec_pg_command(*cmd):
-            _logger.error('DUMP DB: %s failed! Please verify the configuration of the database '
-                          'password on the server. You may need to create a .pgpass file for '
-                          'authentication, or specify `db_password` in the server configuration '
-                          'file.', db)
-            raise Exception("Couldn't dump database")
-
-        openerp.tools.osutil.zip_dir(dump_dir, stream, include_dir=False)
-
-    _logger.info('DUMP DB successful: %s', db)
+        cmd.append(db_name)
 
-def exp_restore(db_name, data, copy=False):
-    data_file = tempfile.NamedTemporaryFile(delete=False)
-    try:
-        data_file.write(data.decode('base64'))
-        data_file.close()
-        restore_db(db_name, data_file.name, copy=copy)
-    finally:
-        os.unlink(data_file.name)
-    return True
-
-@_set_pg_password_in_environment
-def restore_db(db, dump_file, copy=False):
-    assert isinstance(db, basestring)
-    if exp_db_exist(db):
-        _logger.warning('RESTORE DB: %s already exists', db)
-        raise Exception("Database already exists")
+        stdin, stdout = openerp.tools.exec_pg_command_pipe(*tuple(cmd))
+        stdin.close()
+        data = stdout.read()
+        res = stdout.close()
 
-    _create_empty_database(db)
+        if not data or res:
+            _logger.error(
+                    'DUMP DB: %s failed! Please verify the configuration of the database password on the server. '
+                    'You may need to create a .pgpass file for authentication, or specify `db_password` in the '
+                    'server configuration file.\n %s', db_name, data)
+            raise Exception, "Couldn't dump database"
+        _logger.info('DUMP DB successful: %s', db_name)
 
-    filestore_path = None
-    with openerp.tools.osutil.tempdir() as dump_dir:
-        if zipfile.is_zipfile(dump_file):
-            # v8 format
-            with zipfile.ZipFile(dump_file, 'r') as z:
-                # only extract known members!
-                filestore = [m for m in z.namelist() if m.startswith('filestore/')]
-                z.extractall(dump_dir, ['dump.sql'] + filestore)
+        return base64.encodestring(data)
 
-                if filestore:
-                    filestore_path = os.path.join(dump_dir, 'filestore')
+def exp_restore(db_name, data):
+    with _set_pg_password_in_environment():
+        if exp_db_exist(db_name):
+            _logger.warning('RESTORE DB: %s already exists', db_name)
+            raise Exception, "Database already exists"
 
-            pg_cmd = 'psql'
-            pg_args = ['-q', '-f', os.path.join(dump_dir, 'dump.sql')]
+        _create_empty_database(db_name)
 
-        else:
-            # <= 7.0 format (raw pg_dump output)
-            pg_cmd = 'pg_restore'
-            pg_args = ['--no-owner', dump_file]
-
-        args = []
+        cmd = ['pg_restore', '--no-owner']
         if openerp.tools.config['db_user']:
-            args.append('--username=' + openerp.tools.config['db_user'])
+            cmd.append('--username=' + openerp.tools.config['db_user'])
         if openerp.tools.config['db_host']:
-            args.append('--host=' + openerp.tools.config['db_host'])
+            cmd.append('--host=' + openerp.tools.config['db_host'])
         if openerp.tools.config['db_port']:
-            args.append('--port=' + str(openerp.tools.config['db_port']))
-        args.append('--dbname=' + db)
-        pg_args = args + pg_args
-
-        if openerp.tools.exec_pg_command(pg_cmd, *pg_args):
-            raise Exception("Couldn't restore database")
-
-        registry = openerp.modules.registry.RegistryManager.new(db)
-        with registry.cursor() as cr:
-            if copy:
-                # if it's a copy of a database, force generation of a new dbuuid
-                registry['ir.config_parameter'].init(cr, force=True)
-            if filestore_path:
-                filestore_dest = registry['ir.attachment']._filestore(cr, SUPERUSER_ID)
-                shutil.move(filestore_path, filestore_dest)
-
-            if openerp.tools.config['unaccent']:
-                try:
-                    with cr.savepoint():
-                        cr.execute("CREATE EXTENSION unaccent")
-                except psycopg2.Error:
-                    pass
-
-    _logger.info('RESTORE DB: %s', db)
+            cmd.append('--port=' + str(openerp.tools.config['db_port']))
+        cmd.append('--dbname=' + db_name)
+        args2 = tuple(cmd)
+
+        buf=base64.decodestring(data)
+        if os.name == "nt":
+            tmpfile = (os.environ['TMP'] or 'C:\\') + os.tmpnam()
+            file(tmpfile, 'wb').write(buf)
+            args2=list(args2)
+            args2.append(tmpfile)
+            args2=tuple(args2)
+        stdin, stdout = openerp.tools.exec_pg_command_pipe(*args2)
+        if not os.name == "nt":
+            stdin.write(base64.decodestring(data))
+        stdin.close()
+        res = stdout.close()
+        if res:
+            raise Exception, "Couldn't restore database"
+        _logger.info('RESTORE DB: %s', db_name)
+
+        return True
 
 def exp_rename(old_name, new_name):
     openerp.modules.registry.RegistryManager.delete(old_name)
@@ -321,16 +273,20 @@ def exp_rename(old_name, new_name):
 
     db = openerp.sql_db.db_connect('postgres')
     with closing(db.cursor()) as cr:
-        cr.autocommit(True)     # avoid transaction block
+        cr.autocommit(True) # avoid transaction block
         try:
             cr.execute('ALTER DATABASE "%s" RENAME TO "%s"' % (old_name, new_name))
-            _logger.info('RENAME DB: %s -> %s', old_name, new_name)
         except Exception, e:
             _logger.error('RENAME DB: %s -> %s failed:\n%s', old_name, new_name, e)
             raise Exception("Couldn't rename database %s to %s: %s" % (old_name, new_name, e))
+        else:
+            fs = os.path.join(openerp.tools.config['root_path'], 'filestore')
+            if os.path.exists(os.path.join(fs, old_name)):
+                os.rename(os.path.join(fs, old_name), os.path.join(fs, new_name))
+
+            _logger.info('RENAME DB: %s -> %s', old_name, new_name)
     return True
 
-@openerp.tools.mute_logger('openerp.sql_db')
 def exp_db_exist(db_name):
     ## Not True: in fact, check if connection to database is possible. The database may exists
     return bool(openerp.sql_db.db_connect(db_name))
index f9db66a..ec78aac 100644 (file)
@@ -9,10 +9,7 @@ import os.path
 import platform
 import psutil
 import random
-if os.name == 'posix':
-    import resource
-else:
-    resource = None
+import resource
 import select
 import signal
 import socket
@@ -111,14 +108,15 @@ class AutoReload(object):
         self.handler = EventHandler(self)
         self.notifier = pyinotify.Notifier(self.wm, self.handler, timeout=0)
         mask = pyinotify.IN_MODIFY | pyinotify.IN_CREATE  # IN_MOVED_FROM, IN_MOVED_TO ?
-        for path in openerp.modules.modules.ad_paths:
+        for path in openerp.tools.config.options["addons_path"].split(','):
             _logger.info('Watching addons folder %s', path)
             self.wm.add_watch(path, mask, rec=True)
 
     def process_data(self, files):
         xml_files = [i for i in files if i.endswith('.xml')]
+        addons_path = openerp.tools.config.options["addons_path"].split(',')
         for i in xml_files:
-            for path in openerp.modules.modules.ad_paths:
+            for path in addons_path:
                 if i.startswith(path):
                     # find out wich addons path the file belongs to
                     # and extract it's module name
@@ -288,9 +286,8 @@ class ThreadedServer(CommonServer):
         _logger.info("Initiating shutdown")
         _logger.info("Hit CTRL-C again or send a second signal to force the shutdown.")
 
-        if self.httpd:
-            self.httpd.shutdown()
-            self.close_socket(self.httpd.socket)
+        self.httpd.shutdown()
+        self.close_socket(self.httpd.socket)
 
         # Manually join() all threads before calling sys.exit() to allow a second signal
         # to trigger _force_quit() in case some non-daemon threads won't exit cleanly.
@@ -641,8 +638,6 @@ class Worker(object):
                 raise
 
     def process_limit(self):
-        if resource is None:
-            return
         # If our parent changed sucide
         if self.ppid != os.getppid():
             _logger.info("Worker (%s) Parent changed", self.pid)
@@ -851,8 +846,7 @@ def load_test_file_py(registry, test_file):
                 stream = openerp.modules.module.TestStream()
                 result = unittest2.TextTestRunner(verbosity=2, stream=stream).run(suite)
                 success = result.wasSuccessful()
-                if hasattr(registry._assertion_report,'report_result'):
-                    registry._assertion_report.report_result(success)
+                registry._assertion_report.report_result(success)
                 if not success:
                     _logger.error('%s: at least one error occurred in a test', test_file)
 
index b31736b..506a07d 100644 (file)
@@ -72,7 +72,7 @@ def xmlrpc_return(start_response, service, method, params, string_faultcode=Fals
     # This also mimics SimpleXMLRPCDispatcher._marshaled_dispatch() for
     # exception handling.
     try:
-        result = openerp.http.dispatch_rpc(service, method, params)
+        result = openerp.netsvc.dispatch_rpc(service, method, params)
         response = xmlrpclib.dumps((result,), methodresponse=1, allow_none=False, encoding=None)
     except Exception, e:
         if string_faultcode:
index 5984165..694ae02 100644 (file)
@@ -148,7 +148,7 @@ class Cursor(object):
     def check(f):
         @wraps(f)
         def wrapper(self, *args, **kwargs):
-            if self._closed:
+            if self.__closed:
                 msg = 'Unable to use a closed cursor.'
                 if self.__closer:
                     msg += ' It was closed at %s, line %s' % self.__closer
@@ -165,7 +165,7 @@ class Cursor(object):
         self.sql_log = _logger.isEnabledFor(logging.DEBUG)
 
         self.sql_log_count = 0
-        self._closed = True    # avoid the call of close() (by __del__) if an exception
+        self.__closed = True    # avoid the call of close() (by __del__) if an exception
                                 # is raised by any of the following initialisations
         self._pool = pool
         self.dbname = dbname
@@ -180,7 +180,7 @@ class Cursor(object):
             self.__caller = frame_codeinfo(currentframe(),2)
         else:
             self.__caller = False
-        self._closed = False   # real initialisation value
+        self.__closed = False   # real initialisation value
         self.autocommit(False)
         self.__closer = False
 
@@ -189,7 +189,7 @@ class Cursor(object):
         self.cache = {}
 
     def __del__(self):
-        if not self._closed and not self._cnx.closed:
+        if not self.__closed and not self._cnx.closed:
             # Oops. 'self' has not been closed explicitly.
             # The cursor will be deleted by the garbage collector,
             # but the database connection is not put back into the connection
@@ -302,7 +302,7 @@ class Cursor(object):
         # collected as fast as they should). The problem is probably due in
         # part because browse records keep a reference to the cursor.
         del self._obj
-        self._closed = True
+        self.__closed = True
 
         # Clean the underlying connection.
         self._cnx.rollback()
index a53a8d8..b68bbfe 100644 (file)
@@ -13,11 +13,7 @@ import subprocess
 import threading
 import time
 import unittest2
-import urllib2
 import xmlrpclib
-from datetime import datetime, timedelta
-
-import werkzeug
 
 import openerp
 
@@ -49,9 +45,10 @@ def acquire_test_cursor(session_id):
             cr._test_lock.acquire()
             return cr
 
-def release_test_cursor(cr):
+def release_test_cursor(session_id):
     if openerp.tools.config['test_enable']:
-        if hasattr(cr, '_test_lock'):
+        cr = HTTP_SESSION.get(session_id)
+        if cr:
             cr._test_lock.release()
             return True
     return False
@@ -153,7 +150,7 @@ class SingleTransactionCase(BaseCase):
 
 
 class HttpCase(TransactionCase):
-    """ Transactionnal HTTP TestCase with url_open and phantomjs helpers.
+    """ Transactionnal HTTP TestCase with a phantomjs helper.
     """
 
     def __init__(self, methodName='runTest'):
@@ -174,17 +171,11 @@ class HttpCase(TransactionCase):
         self.cr._test_lock = threading.RLock()
         HTTP_SESSION[self.session_id] = self.cr
 
+
     def tearDown(self):
         del HTTP_SESSION[self.session_id]
         super(HttpCase, self).tearDown()
 
-    def url_open(self, url, data=None, timeout=10):
-        opener = urllib2.build_opener()
-        opener.addheaders.append(('Cookie', 'session_id=%s' % self.session_id))
-        if url.startswith('/'):
-            url = "http://localhost:%s%s" % (PORT, url)
-        return opener.open(url, data, timeout)
-
     def phantom_poll(self, phantom, timeout):
         """ Phantomjs Test protocol.
 
@@ -196,12 +187,11 @@ class HttpCase(TransactionCase):
         Other lines are relayed to the test log.
 
         """
-        t0 = datetime.now()
-        td = timedelta(seconds=timeout)
+        t0 = time.time()
         buf = bytearray()
         while True:
             # timeout
-            self.assertLess(datetime.now() - t0, td,
+            self.assertLess(time.time(), t0 + timeout,
                 "PhantomJS tests should take less than %s seconds" % timeout)
 
             # read a byte
@@ -212,8 +202,7 @@ class HttpCase(TransactionCase):
                 # OSError, and no errno/strerror/filename, only a pair of
                 # unnamed arguments (matching errno and strerror)
                 err, _ = e.args
-                if err == errno.EINTR:
-                    continue
+                if err == errno.EINTR: continue
                 raise
 
             if ready:
@@ -225,24 +214,24 @@ class HttpCase(TransactionCase):
             # process lines
             if '\n' in buf:
                 line, buf = buf.split('\n', 1)
-                line = str(line)
-
-                # relay everything from console.log, even 'ok' or 'error...' lines
-                _logger.info("phantomjs: %s", line)
 
+                line = str(line)
+                if 'CoreText' in line:
+                    continue
                 if line == "ok":
                     break
                 if line.startswith("error"):
                     line_ = line[6:]
-                    # when error occurs the execution stack may be sent as as JSON
-                    try:
-                        line_ = json.loads(line_)
-                    except ValueError: 
-                        pass
+                    try: line_ = json.loads(line_)
+                    except ValueError: pass
                     self.fail(line_ or "phantomjs test failed")
 
+                try: line = json.loads(line)
+                except ValueError: pass
+                _logger.info("phantomjs: %s", line)
+
     def phantom_run(self, cmd, timeout):
-        _logger.info('phantom_run executing %s', ' '.join(cmd))
+        _logger.debug('executing `%s`', ' '.join(cmd))
         try:
             phantom = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
         except OSError:
@@ -253,7 +242,6 @@ class HttpCase(TransactionCase):
             # kill phantomjs if phantom.exit() wasn't called in the test
             if phantom.poll() is None:
                 phantom.terminate()
-            _logger.info("phantom_run execution finished")
 
     def phantom_jsfile(self, jsfile, timeout=30, **kw):
         options = {
index 63a3b2e..1cdfeab 100644 (file)
@@ -2,17 +2,22 @@
 
 function waitFor (ready, callback, timeout, timeoutMessageCallback) {
     timeout = timeout || 10000;
-    var start = new Date;
-
-    (function waitLoop() {
-        if(new Date - start > timeout) {
-            error(timeoutMessageCallback ? timeoutMessageCallback() : "Timeout after "+timeout+" ms");
-        } else if (ready()) {
-            callback();
+    var start = new Date().getTime();
+    var condition = ready();
+    var interval = setInterval(function() {
+        if ((new Date().getTime() - start < timeout) && !condition ) {
+            condition = ready();
         } else {
-            setTimeout(waitLoop, 250);
+            if(!condition) {
+                var message = timeoutMessageCallback ? timeoutMessageCallback() : "Timeout after "+timeout+" ms";
+                console.log("Waiting for " + ready);
+                error(message);
+            } else {
+                clearInterval(interval);
+                callback();
+            }
         }
-    }());
+    }, 250);
 }
 
 function error(message) {
@@ -98,12 +103,12 @@ function PhantomTest() {
     // ----------------------------------------------------
     this.run = function(url_path, code, ready) {
         if(self.options.login) {
-            var qp = [];
+            qp = [];
             qp.push('db=' + self.options.db);
             qp.push('login=' + self.options.login);
             qp.push('key=' + self.options.password);
             qp.push('redirect=' + encodeURIComponent(url_path));
-            url_path = "/login?" + qp.join('&');
+            var url_path = "/login?" + qp.join('&');
         }
         var url = self.origin + url_path;
         self.page.open(url, function(status) {
@@ -113,22 +118,18 @@ function PhantomTest() {
                 console.log('loaded', url, status);
                 // process ready
                 waitFor(function() {
-                    console.log("PhantomTest.run: wait for condition: " + ready);
-                    return self.page.evaluate(function (ready) {
+                    return self.page.evaluate(function (ready) { 
                         var r = false;
                         try {
-                            console.log("page.evaluate eval expr:", ready);
                             r = !!eval(ready);
-                        } catch(ex) { 
+                        } catch(ex) {
+                            console.log("waiting for " + ready);
                         }
-                        console.log("page.evaluate eval result:", r);
                         return r;
                     }, ready);
                 // run test
                 }, function() {
-                    console.log("PhantomTest.run: condition statified, executing: " + code);
                     self.page.evaluate(function (code) { return eval(code); }, code);
-                    console.log("PhantomTest.run: execution launched, waiting for console.log('ok')...");
                 });
             }
         });
index c927b2f..18dab08 100644 (file)
@@ -21,7 +21,6 @@
 
 import copy
 import win32
-import appdirs
 from config import config
 from misc import *
 from convert import *
@@ -35,7 +34,7 @@ from yaml_import import *
 from sql import *
 from float_utils import *
 from mail import *
-from debugger import *
+
 
 # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
 
diff --git a/openerp/tools/appdirs.py b/openerp/tools/appdirs.py
deleted file mode 100644 (file)
index 1d24dd8..0000000
+++ /dev/null
@@ -1,477 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-# Copyright (c) 2005-2010 ActiveState Software Inc.
-# Copyright (c) 2013 Eddy Petrișor
-
-"""Utilities for determining application-specific dirs.
-
-See <http://github.com/ActiveState/appdirs> for details and usage.
-"""
-# Dev Notes:
-# - MSDN on where to store app data files:
-#   http://support.microsoft.com/default.aspx?scid=kb;en-us;310294#XSLTH3194121123120121120120
-# - Mac OS X: http://developer.apple.com/documentation/MacOSX/Conceptual/BPFileSystem/index.html
-# - XDG spec for Un*x: http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html
-
-__version_info__ = (1, 3, 0)
-__version__ = '.'.join(map(str, __version_info__))
-
-
-import sys
-import os
-
-PY3 = sys.version_info[0] == 3
-
-if PY3:
-    unicode = str
-
-
-
-def user_data_dir(appname=None, appauthor=None, version=None, roaming=False):
-    r"""Return full path to the user-specific data dir for this application.
-
-        "appname" is the name of application.
-            If None, just the system directory is returned.
-        "appauthor" (only required and used on Windows) is the name of the
-            appauthor or distributing body for this application. Typically
-            it is the owning company name. This falls back to appname.
-        "version" is an optional version path element to append to the
-            path. You might want to use this if you want multiple versions
-            of your app to be able to run independently. If used, this
-            would typically be "<major>.<minor>".
-            Only applied when appname is present.
-        "roaming" (boolean, default False) can be set True to use the Windows
-            roaming appdata directory. That means that for users on a Windows
-            network setup for roaming profiles, this user data will be
-            sync'd on login. See
-            <http://technet.microsoft.com/en-us/library/cc766489(WS.10).aspx>
-            for a discussion of issues.
-
-    Typical user data directories are:
-        Mac OS X:               ~/Library/Application Support/<AppName>
-        Unix:                   ~/.local/share/<AppName>    # or in $XDG_DATA_HOME, if defined
-        Win XP (not roaming):   C:\Documents and Settings\<username>\Application Data\<AppAuthor>\<AppName>
-        Win XP (roaming):       C:\Documents and Settings\<username>\Local Settings\Application Data\<AppAuthor>\<AppName>
-        Win 7  (not roaming):   C:\Users\<username>\AppData\Local\<AppAuthor>\<AppName>
-        Win 7  (roaming):       C:\Users\<username>\AppData\Roaming\<AppAuthor>\<AppName>
-
-    For Unix, we follow the XDG spec and support $XDG_DATA_HOME.
-    That means, by deafult "~/.local/share/<AppName>".
-    """
-    if sys.platform == "win32":
-        if appauthor is None:
-            appauthor = appname
-        const = roaming and "CSIDL_APPDATA" or "CSIDL_LOCAL_APPDATA"
-        path = os.path.normpath(_get_win_folder(const))
-        if appname:
-            path = os.path.join(path, appauthor, appname)
-    elif sys.platform == 'darwin':
-        path = os.path.expanduser('~/Library/Application Support/')
-        if appname:
-            path = os.path.join(path, appname)
-    else:
-        path = os.getenv('XDG_DATA_HOME', os.path.expanduser("~/.local/share"))
-        if appname:
-            path = os.path.join(path, appname)
-    if appname and version:
-        path = os.path.join(path, version)
-    return path
-
-
-def site_data_dir(appname=None, appauthor=None, version=None, multipath=False):
-    """Return full path to the user-shared data dir for this application.
-
-        "appname" is the name of application.
-            If None, just the system directory is returned.
-        "appauthor" (only required and used on Windows) is the name of the
-            appauthor or distributing body for this application. Typically
-            it is the owning company name. This falls back to appname.
-        "version" is an optional version path element to append to the
-            path. You might want to use this if you want multiple versions
-            of your app to be able to run independently. If used, this
-            would typically be "<major>.<minor>".
-            Only applied when appname is present.
-        "multipath" is an optional parameter only applicable to *nix
-            which indicates that the entire list of data dirs should be
-            returned. By default, the first item from XDG_DATA_DIRS is
-            returned, or '/usr/local/share/<AppName>',
-            if XDG_DATA_DIRS is not set
-
-    Typical user data directories are:
-        Mac OS X:   /Library/Application Support/<AppName>
-        Unix:       /usr/local/share/<AppName> or /usr/share/<AppName>
-        Win XP:     C:\Documents and Settings\All Users\Application Data\<AppAuthor>\<AppName>
-        Vista:      (Fail! "C:\ProgramData" is a hidden *system* directory on Vista.)
-        Win 7:      C:\ProgramData\<AppAuthor>\<AppName>   # Hidden, but writeable on Win 7.
-
-    For Unix, this is using the $XDG_DATA_DIRS[0] default.
-
-    WARNING: Do not use this on Windows. See the Vista-Fail note above for why.
-    """
-    if sys.platform == "win32":
-        if appauthor is None:
-            appauthor = appname
-        path = os.path.normpath(_get_win_folder("CSIDL_COMMON_APPDATA"))
-        if appname:
-            path = os.path.join(path, appauthor, appname)
-    elif sys.platform == 'darwin':
-        path = os.path.expanduser('/Library/Application Support')
-        if appname:
-            path = os.path.join(path, appname)
-    else:
-        # XDG default for $XDG_DATA_DIRS
-        # only first, if multipath is False
-        path = os.getenv('XDG_DATA_DIRS',
-                        os.pathsep.join(['/usr/local/share', '/usr/share']))
-        pathlist = [ os.path.expanduser(x.rstrip(os.sep)) for x in path.split(os.pathsep) ]
-        if appname:
-            if version:
-                appname = os.path.join(appname, version)
-            pathlist = [ os.sep.join([x, appname]) for x in pathlist ]
-
-        if multipath:
-            path = os.pathsep.join(pathlist)
-        else:
-            path = pathlist[0]
-        return path
-
-    if appname and version:
-        path = os.path.join(path, version)
-    return path
-
-
-def user_config_dir(appname=None, appauthor=None, version=None, roaming=False):
-    r"""Return full path to the user-specific config dir for this application.
-
-        "appname" is the name of application.
-            If None, just the system directory is returned.
-        "appauthor" (only required and used on Windows) is the name of the
-            appauthor or distributing body for this application. Typically
-            it is the owning company name. This falls back to appname.
-        "version" is an optional version path element to append to the
-            path. You might want to use this if you want multiple versions
-            of your app to be able to run independently. If used, this
-            would typically be "<major>.<minor>".
-            Only applied when appname is present.
-        "roaming" (boolean, default False) can be set True to use the Windows
-            roaming appdata directory. That means that for users on a Windows
-            network setup for roaming profiles, this user data will be
-            sync'd on login. See
-            <http://technet.microsoft.com/en-us/library/cc766489(WS.10).aspx>
-            for a discussion of issues.
-
-    Typical user data directories are:
-        Mac OS X:               same as user_data_dir
-        Unix:                   ~/.config/<AppName>     # or in $XDG_CONFIG_HOME, if defined
-        Win *:                  same as user_data_dir
-
-    For Unix, we follow the XDG spec and support $XDG_DATA_HOME.
-    That means, by deafult "~/.local/share/<AppName>".
-    """
-    if sys.platform in [ "win32", "darwin" ]:
-        path = user_data_dir(appname, appauthor, None, roaming)
-    else:
-        path = os.getenv('XDG_CONFIG_HOME', os.path.expanduser("~/.config"))
-        if appname:
-            path = os.path.join(path, appname)
-    if appname and version:
-        path = os.path.join(path, version)
-    return path
-
-
-def site_config_dir(appname=None, appauthor=None, version=None, multipath=False):
-    """Return full path to the user-shared data dir for this application.
-
-        "appname" is the name of application.
-            If None, just the system directory is returned.
-        "appauthor" (only required and used on Windows) is the name of the
-            appauthor or distributing body for this application. Typically
-            it is the owning company name. This falls back to appname.
-        "version" is an optional version path element to append to the
-            path. You might want to use this if you want multiple versions
-            of your app to be able to run independently. If used, this
-            would typically be "<major>.<minor>".
-            Only applied when appname is present.
-        "multipath" is an optional parameter only applicable to *nix
-            which indicates that the entire list of config dirs should be
-            returned. By default, the first item from XDG_CONFIG_DIRS is
-            returned, or '/etc/xdg/<AppName>', if XDG_CONFIG_DIRS is not set
-
-    Typical user data directories are:
-        Mac OS X:   same as site_data_dir
-        Unix:       /etc/xdg/<AppName> or $XDG_CONFIG_DIRS[i]/<AppName> for each value in
-                    $XDG_CONFIG_DIRS
-        Win *:      same as site_data_dir
-        Vista:      (Fail! "C:\ProgramData" is a hidden *system* directory on Vista.)
-
-    For Unix, this is using the $XDG_CONFIG_DIRS[0] default, if multipath=False
-
-    WARNING: Do not use this on Windows. See the Vista-Fail note above for why.
-    """
-    if sys.platform in [ "win32", "darwin" ]:
-        path = site_data_dir(appname, appauthor)
-        if appname and version:
-            path = os.path.join(path, version)
-    else:
-        # XDG default for $XDG_CONFIG_DIRS
-        # only first, if multipath is False
-        path = os.getenv('XDG_CONFIG_DIRS', '/etc/xdg')
-        pathlist = [ os.path.expanduser(x.rstrip(os.sep)) for x in path.split(os.pathsep) ]
-        if appname:
-            if version:
-                appname = os.path.join(appname, version)
-            pathlist = [ os.sep.join([x, appname]) for x in pathlist ]
-
-        if multipath:
-            path = os.pathsep.join(pathlist)
-        else:
-            path = pathlist[0]
-    return path
-
-def user_cache_dir(appname=None, appauthor=None, version=None, opinion=True):
-    r"""Return full path to the user-specific cache dir for this application.
-
-        "appname" is the name of application.
-            If None, just the system directory is returned.
-        "appauthor" (only required and used on Windows) is the name of the
-            appauthor or distributing body for this application. Typically
-            it is the owning company name. This falls back to appname.
-        "version" is an optional version path element to append to the
-            path. You might want to use this if you want multiple versions
-            of your app to be able to run independently. If used, this
-            would typically be "<major>.<minor>".
-            Only applied when appname is present.
-        "opinion" (boolean) can be False to disable the appending of
-            "Cache" to the base app data dir for Windows. See
-            discussion below.
-
-    Typical user cache directories are:
-        Mac OS X:   ~/Library/Caches/<AppName>
-        Unix:       ~/.cache/<AppName> (XDG default)
-        Win XP:     C:\Documents and Settings\<username>\Local Settings\Application Data\<AppAuthor>\<AppName>\Cache
-        Vista:      C:\Users\<username>\AppData\Local\<AppAuthor>\<AppName>\Cache
-
-    On Windows the only suggestion in the MSDN docs is that local settings go in
-    the `CSIDL_LOCAL_APPDATA` directory. This is identical to the non-roaming
-    app data dir (the default returned by `user_data_dir` above). Apps typically
-    put cache data somewhere *under* the given dir here. Some examples:
-        ...\Mozilla\Firefox\Profiles\<ProfileName>\Cache
-        ...\Acme\SuperApp\Cache\1.0
-    OPINION: This function appends "Cache" to the `CSIDL_LOCAL_APPDATA` value.
-    This can be disabled with the `opinion=False` option.
-    """
-    if sys.platform == "win32":
-        if appauthor is None:
-            appauthor = appname
-        path = os.path.normpath(_get_win_folder("CSIDL_LOCAL_APPDATA"))
-        if appname:
-            path = os.path.join(path, appauthor, appname)
-            if opinion:
-                path = os.path.join(path, "Cache")
-    elif sys.platform == 'darwin':
-        path = os.path.expanduser('~/Library/Caches')
-        if appname:
-            path = os.path.join(path, appname)
-    else:
-        path = os.getenv('XDG_CACHE_HOME', os.path.expanduser('~/.cache'))
-        if appname:
-            path = os.path.join(path, appname)
-    if appname and version:
-        path = os.path.join(path, version)
-    return path
-
-def user_log_dir(appname=None, appauthor=None, version=None, opinion=True):
-    r"""Return full path to the user-specific log dir for this application.
-
-        "appname" is the name of application.
-            If None, just the system directory is returned.
-        "appauthor" (only required and used on Windows) is the name of the
-            appauthor or distributing body for this application. Typically
-            it is the owning company name. This falls back to appname.
-        "version" is an optional version path element to append to the
-            path. You might want to use this if you want multiple versions
-            of your app to be able to run independently. If used, this
-            would typically be "<major>.<minor>".
-            Only applied when appname is present.
-        "opinion" (boolean) can be False to disable the appending of
-            "Logs" to the base app data dir for Windows, and "log" to the
-            base cache dir for Unix. See discussion below.
-
-    Typical user cache directories are:
-        Mac OS X:   ~/Library/Logs/<AppName>
-        Unix:       ~/.cache/<AppName>/log  # or under $XDG_CACHE_HOME if defined
-        Win XP:     C:\Documents and Settings\<username>\Local Settings\Application Data\<AppAuthor>\<AppName>\Logs
-        Vista:      C:\Users\<username>\AppData\Local\<AppAuthor>\<AppName>\Logs
-
-    On Windows the only suggestion in the MSDN docs is that local settings
-    go in the `CSIDL_LOCAL_APPDATA` directory. (Note: I'm interested in
-    examples of what some windows apps use for a logs dir.)
-
-    OPINION: This function appends "Logs" to the `CSIDL_LOCAL_APPDATA`
-    value for Windows and appends "log" to the user cache dir for Unix.
-    This can be disabled with the `opinion=False` option.
-    """
-    if sys.platform == "darwin":
-        path = os.path.join(
-            os.path.expanduser('~/Library/Logs'),
-            appname)
-    elif sys.platform == "win32":
-        path = user_data_dir(appname, appauthor, version); version=False
-        if opinion:
-            path = os.path.join(path, "Logs")
-    else:
-        path = user_cache_dir(appname, appauthor, version); version=False
-        if opinion:
-            path = os.path.join(path, "log")
-    if appname and version:
-        path = os.path.join(path, version)
-    return path
-
-
-class AppDirs(object):
-    """Convenience wrapper for getting application dirs."""
-    def __init__(self, appname, appauthor=None, version=None,
-                    roaming=False, multipath=False):
-        self.appname = appname
-        self.appauthor = appauthor
-        self.version = version
-        self.roaming = roaming
-        self.multipath = multipath
-    @property
-    def user_data_dir(self):
-        return user_data_dir(self.appname, self.appauthor,
-            version=self.version, roaming=self.roaming)
-    @property
-    def site_data_dir(self):
-        return site_data_dir(self.appname, self.appauthor,
-            version=self.version, multipath=self.multipath)
-    @property
-    def user_config_dir(self):
-        return user_config_dir(self.appname, self.appauthor,
-            version=self.version, roaming=self.roaming)
-    @property
-    def site_config_dir(self):
-        return site_data_dir(self.appname, self.appauthor,
-            version=self.version, multipath=self.multipath)
-    @property
-    def user_cache_dir(self):
-        return user_cache_dir(self.appname, self.appauthor,
-            version=self.version)
-    @property
-    def user_log_dir(self):
-        return user_log_dir(self.appname, self.appauthor,
-            version=self.version)
-
-
-
-
-#---- internal support stuff
-
-def _get_win_folder_from_registry(csidl_name):
-    """This is a fallback technique at best. I'm not sure if using the
-    registry for this guarantees us the correct answer for all CSIDL_*
-    names.
-    """
-    import _winreg
-
-    shell_folder_name = {
-        "CSIDL_APPDATA": "AppData",
-        "CSIDL_COMMON_APPDATA": "Common AppData",
-        "CSIDL_LOCAL_APPDATA": "Local AppData",
-    }[csidl_name]
-
-    key = _winreg.OpenKey(_winreg.HKEY_CURRENT_USER,
-        r"Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders")
-    dir, type = _winreg.QueryValueEx(key, shell_folder_name)
-    return dir
-
-def _get_win_folder_with_pywin32(csidl_name):
-    from win32com.shell import shellcon, shell
-    dir = shell.SHGetFolderPath(0, getattr(shellcon, csidl_name), 0, 0)
-    # Try to make this a unicode path because SHGetFolderPath does
-    # not return unicode strings when there is unicode data in the
-    # path.
-    try:
-        dir = unicode(dir)
-
-        # Downgrade to short path name if have highbit chars. See
-        # <http://bugs.activestate.com/show_bug.cgi?id=85099>.
-        has_high_char = False
-        for c in dir:
-            if ord(c) > 255:
-                has_high_char = True
-                break
-        if has_high_char:
-            try:
-                import win32api
-                dir = win32api.GetShortPathName(dir)
-            except ImportError:
-                pass
-    except UnicodeError:
-        pass
-    return dir
-
-def _get_win_folder_with_ctypes(csidl_name):
-    import ctypes
-
-    csidl_const = {
-        "CSIDL_APPDATA": 26,
-        "CSIDL_COMMON_APPDATA": 35,
-        "CSIDL_LOCAL_APPDATA": 28,
-    }[csidl_name]
-
-    buf = ctypes.create_unicode_buffer(1024)
-    ctypes.windll.shell32.SHGetFolderPathW(None, csidl_const, None, 0, buf)
-
-    # Downgrade to short path name if have highbit chars. See
-    # <http://bugs.activestate.com/show_bug.cgi?id=85099>.
-    has_high_char = False
-    for c in buf:
-        if ord(c) > 255:
-            has_high_char = True
-            break
-    if has_high_char:
-        buf2 = ctypes.create_unicode_buffer(1024)
-        if ctypes.windll.kernel32.GetShortPathNameW(buf.value, buf2, 1024):
-            buf = buf2
-
-    return buf.value
-
-if sys.platform == "win32":
-    try:
-        import win32com.shell
-        _get_win_folder = _get_win_folder_with_pywin32
-    except ImportError:
-        try:
-            import ctypes
-            _get_win_folder = _get_win_folder_with_ctypes
-        except ImportError:
-            _get_win_folder = _get_win_folder_from_registry
-
-
-
-#---- self test code
-
-if __name__ == "__main__":
-    appname = "MyApp"
-    appauthor = "MyCompany"
-
-    props = ("user_data_dir", "site_data_dir",
-             "user_config_dir", "site_config_dir",
-             "user_cache_dir", "user_log_dir")
-
-    print("-- app dirs (with optional 'version')")
-    dirs = AppDirs(appname, appauthor, version="1.0")
-    for prop in props:
-        print("%s: %s" % (prop, getattr(dirs, prop)))
-
-    print("\n-- app dirs (without optional 'version')")
-    dirs = AppDirs(appname, appauthor)
-    for prop in props:
-        print("%s: %s" % (prop, getattr(dirs, prop)))
-
-    print("\n-- app dirs (without optional 'appauthor')")
-    dirs = AppDirs(appname)
-    for prop in props:
-        print("%s: %s" % (prop, getattr(dirs, prop)))
-
index 8313f4d..0743507 100644 (file)
@@ -1,9 +1,9 @@
-#openerp.loggers.handlers. -*- coding: utf-8 -*-
+# -*- coding: utf-8 -*-
 ##############################################################################
 #
 #    OpenERP, Open Source Management Solution
 #    Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>).
-#    Copyright (C) 2010-2014 OpenERP s.a. (<http://openerp.com>).
+#    Copyright (C) 2010-2012 OpenERP s.a. (<http://openerp.com>).
 #
 #    This program is free software: you can redistribute it and/or modify
 #    it under the terms of the GNU Affero General Public License as
@@ -29,7 +29,6 @@ import openerp.conf
 import openerp.loglevels as loglevels
 import logging
 import openerp.release as release
-import appdirs
 
 class MyOption (optparse.Option, object):
     """ optparse Option with two additional attributes.
@@ -60,9 +59,6 @@ def check_ssl():
 
 DEFAULT_LOG_HANDLER = [':INFO']
 
-def _get_default_datadir():
-    return appdirs.user_data_dir(appname='OpenERP', appauthor=release.author)
-
 class configmanager(object):
     def __init__(self, fname=None):
         # Options not exposed on the command line. Command line options will be added
@@ -76,10 +72,9 @@ class configmanager(object):
         }
 
         # Not exposed in the configuration file.
-        self.blacklist_for_save = set([
-            'publisher_warranty_url', 'load_language', 'root_path',
-            'init', 'save', 'config', 'update', 'stop_after_init'
-        ])
+        self.blacklist_for_save = set(
+            ['publisher_warranty_url', 'load_language', 'root_path',
+            'init', 'save', 'config', 'update', 'stop_after_init'])
 
         # dictionary mapping option destination (keys in self.options) to MyOptions.
         self.casts = {}
@@ -88,10 +83,7 @@ class configmanager(object):
         self.config_file = fname
         self.has_ssl = check_ssl()
 
-        self._LOGLEVELS = dict([
-            (getattr(loglevels, 'LOG_%s' % x), getattr(logging, x)) 
-            for x in ('CRITICAL', 'ERROR', 'WARNING', 'INFO', 'DEBUG', 'NOTSET')
-        ])
+        self._LOGLEVELS = dict([(getattr(loglevels, 'LOG_%s' % x), getattr(logging, x)) for x in ('CRITICAL', 'ERROR', 'WARNING', 'INFO', 'DEBUG', 'NOTSET')])
 
         version = "%s %s" % (release.description, release.version)
         self.parser = parser = optparse.OptionParser(version=version, option_class=MyOption)
@@ -114,9 +106,6 @@ class configmanager(object):
                          help="specify additional addons paths (separated by commas).",
                          action="callback", callback=self._check_addons_path, nargs=1, type="string")
         group.add_option("--load", dest="server_wide_modules", help="Comma-separated list of server-wide modules default=web")
-
-        group.add_option("-D", "--data-dir", dest="data_dir", my_default=_get_default_datadir(),
-                         help="Directory where to store OpenERP data")
         parser.add_option_group(group)
 
         # XML-RPC / HTTP
@@ -183,20 +172,16 @@ class configmanager(object):
         group.add_option("--logrotate", dest="logrotate", action="store_true", my_default=False, help="enable logfile rotation")
         group.add_option("--syslog", action="store_true", dest="syslog", my_default=False, help="Send the log to the syslog server")
         group.add_option('--log-handler', action="append", default=DEFAULT_LOG_HANDLER, my_default=DEFAULT_LOG_HANDLER, metavar="PREFIX:LEVEL", help='setup a handler at LEVEL for a given PREFIX. An empty PREFIX indicates the root logger. This option can be repeated. Example: "openerp.orm:DEBUG" or "werkzeug:CRITICAL" (default: ":INFO")')
-        group.add_option('--log-request', action="append_const", dest="log_handler", const="openerp.http.rpc.request:DEBUG", help='shortcut for --log-handler=openerp.http.rpc.request:DEBUG')
-        group.add_option('--log-response', action="append_const", dest="log_handler", const="openerp.http.rpc.response:DEBUG", help='shortcut for --log-handler=openerp.http.rpc.response:DEBUG')
-        group.add_option('--log-web', action="append_const", dest="log_handler", const="openerp.http:DEBUG", help='shortcut for --log-handler=openerp.http:DEBUG')
+        group.add_option('--log-request', action="append_const", dest="log_handler", const="openerp.netsvc.rpc.request:DEBUG", help='shortcut for --log-handler=openerp.netsvc.rpc.request:DEBUG')
+        group.add_option('--log-response', action="append_const", dest="log_handler", const="openerp.netsvc.rpc.response:DEBUG", help='shortcut for --log-handler=openerp.netsvc.rpc.response:DEBUG')
+        group.add_option('--log-web', action="append_const", dest="log_handler", const="openerp.addons.web.http:DEBUG", help='shortcut for --log-handler=openerp.addons.web.http:DEBUG')
         group.add_option('--log-sql', action="append_const", dest="log_handler", const="openerp.sql_db:DEBUG", help='shortcut for --log-handler=openerp.sql_db:DEBUG')
-        group.add_option('--log-db', dest='log_db', help="Logging database", my_default=False)
         # For backward-compatibility, map the old log levels to something
         # quite close.
-        levels = [
-            'info', 'debug_rpc', 'warn', 'test', 'critical',
-            'debug_sql', 'error', 'debug', 'debug_rpc_answer', 'notset'
-        ]
-        group.add_option('--log-level', dest='log_level', type='choice',
-                         choices=levels, my_default='info',
-                         help='specify the level of the logging. Accepted values: %s (deprecated option).' % (levels,))
+        levels = ['info', 'debug_rpc', 'warn', 'test', 'critical',
+            'debug_sql', 'error', 'debug', 'debug_rpc_answer', 'notset']
+        group.add_option('--log-level', dest='log_level', type='choice', choices=levels,
+            my_default='info', help='specify the level of the logging. Accepted values: ' + str(levels) + ' (deprecated option).')
 
         parser.add_option_group(group)
 
@@ -260,8 +245,7 @@ class configmanager(object):
 
         # Advanced options
         group = optparse.OptionGroup(parser, "Advanced options")
-        if os.name == 'posix':
-            group.add_option('--auto-reload', dest='auto_reload', action='store_true', my_default=False, help='enable auto reload')
+        group.add_option('--auto-reload', dest='auto_reload', action='store_true', my_default=False, help='enable auto reload')
         group.add_option('--debug', dest='debug_mode', action='store_true', my_default=False, help='enable debug mode')
         group.add_option("--stop-after-init", action="store_true", dest="stop_after_init", my_default=False,
                           help="stop the server after its initialization")
@@ -283,28 +267,27 @@ class configmanager(object):
                          help="Use the unaccent function provided by the database when available.")
         parser.add_option_group(group)
 
-        if os.name == 'posix':
-            group = optparse.OptionGroup(parser, "Multiprocessing options")
-            # TODO sensible default for the three following limits.
-            group.add_option("--workers", dest="workers", my_default=0,
-                             help="Specify the number of workers, 0 disable prefork mode.",
-                             type="int")
-            group.add_option("--limit-memory-soft", dest="limit_memory_soft", my_default=2048 * 1024 * 1024,
-                             help="Maximum allowed virtual memory per worker, when reached the worker be reset after the current request (default 671088640 aka 640MB).",
-                             type="int")
-            group.add_option("--limit-memory-hard", dest="limit_memory_hard", my_default=2560 * 1024 * 1024,
-                             help="Maximum allowed virtual memory per worker, when reached, any memory allocation will fail (default 805306368 aka 768MB).",
-                             type="int")
-            group.add_option("--limit-time-cpu", dest="limit_time_cpu", my_default=60,
-                             help="Maximum allowed CPU time per request (default 60).",
-                             type="int")
-            group.add_option("--limit-time-real", dest="limit_time_real", my_default=120,
-                             help="Maximum allowed Real time per request (default 120).",
-                             type="int")
-            group.add_option("--limit-request", dest="limit_request", my_default=8192,
-                             help="Maximum number of request to be processed per worker (default 8192).",
-                             type="int")
-            parser.add_option_group(group)
+        group = optparse.OptionGroup(parser, "Multiprocessing options")
+        # TODO sensible default for the three following limits.
+        group.add_option("--workers", dest="workers", my_default=0,
+                         help="Specify the number of workers, 0 disable prefork mode.",
+                         type="int")
+        group.add_option("--limit-memory-soft", dest="limit_memory_soft", my_default=2048 * 1024 * 1024,
+                         help="Maximum allowed virtual memory per worker, when reached the worker be reset after the current request (default 671088640 aka 640MB).",
+                         type="int")
+        group.add_option("--limit-memory-hard", dest="limit_memory_hard", my_default=2560 * 1024 * 1024,
+                         help="Maximum allowed virtual memory per worker, when reached, any memory allocation will fail (default 805306368 aka 768MB).",
+                         type="int")
+        group.add_option("--limit-time-cpu", dest="limit_time_cpu", my_default=60,
+                         help="Maximum allowed CPU time per request (default 60).",
+                         type="int")
+        group.add_option("--limit-time-real", dest="limit_time_real", my_default=120,
+                         help="Maximum allowed Real time per request (default 120).",
+                         type="int")
+        group.add_option("--limit-request", dest="limit_request", my_default=8192,
+                         help="Maximum number of request to be processed per worker (default 8192).",
+                         type="int")
+        parser.add_option_group(group)
 
         # Copy all optparse options (i.e. MyOption) into self.options.
         for group in parser.option_groups:
@@ -365,7 +348,6 @@ class configmanager(object):
         # (../etc from the server)
         # if the server is run by an unprivileged user, he has to specify location of a config file where he has the rights to write,
         # else he won't be able to save the configurations, or even to start the server...
-        # TODO use appdirs
         if os.name == 'nt':
             rcfilepath = os.path.join(os.path.abspath(os.path.dirname(sys.argv[0])), 'openerp-server.conf')
         else:
@@ -376,6 +358,7 @@ class configmanager(object):
                 or os.environ.get('OPENERP_SERVER') or rcfilepath)
         self.load()
 
+
         # Verify that we want to log or not, if not the output will go to stdout
         if self.options['logfile'] in ('None', 'False'):
             self.options['logfile'] = False
@@ -392,7 +375,7 @@ class configmanager(object):
                 'xmlrpc', 'syslog', 'without_demo', 'timezone',
                 'xmlrpcs_interface', 'xmlrpcs_port', 'xmlrpcs',
                 'static_http_enable', 'static_http_document_root', 'static_http_url_prefix',
-                'secure_cert_file', 'secure_pkey_file', 'dbfilter', 'log_handler', 'log_level', 'log_db'
+                'secure_cert_file', 'secure_pkey_file', 'dbfilter', 'log_handler', 'log_level'
                 ]
 
         for arg in keys:
@@ -404,6 +387,7 @@ class configmanager(object):
             elif isinstance(self.options[arg], basestring) and self.casts[arg].type in optparse.Option.TYPE_CHECKER:
                 self.options[arg] = optparse.Option.TYPE_CHECKER[self.casts[arg].type](self.casts[arg], arg, self.options[arg])
 
+
         if isinstance(self.options['log_handler'], basestring):
             self.options['log_handler'] = self.options['log_handler'].split(',')
 
@@ -415,22 +399,11 @@ class configmanager(object):
             'list_db', 'xmlrpcs', 'proxy_mode',
             'test_file', 'test_enable', 'test_commit', 'test_report_directory',
             'osv_memory_count_limit', 'osv_memory_age_limit', 'max_cron_threads', 'unaccent',
-            'data_dir',
+            'workers', 'limit_memory_hard', 'limit_memory_soft', 'limit_time_cpu', 'limit_time_real', 'limit_request', 'auto_reload'
         ]
 
-        posix_keys = [
-            'auto_reload', 'workers',
-            'limit_memory_hard', 'limit_memory_soft',
-            'limit_time_cpu', 'limit_time_real', 'limit_request',
-        ]
-
-        if os.name == 'posix':
-            keys += posix_keys
-        else:
-            self.options.update(dict.fromkeys(posix_keys, None))
-
-        # Copy the command-line arguments...
         for arg in keys:
+            # Copy the command-line argument...
             if getattr(opt, arg) is not None:
                 self.options[arg] = getattr(opt, arg)
             # ... or keep, but cast, the config file value.
@@ -644,24 +617,6 @@ class configmanager(object):
     def __getitem__(self, key):
         return self.options[key]
 
-    @property
-    def addons_data_dir(self):
-        d = os.path.join(self['data_dir'], 'addons', release.series)
-        if not os.path.exists(d):
-            os.makedirs(d, 0700)
-        else:
-            os.chmod(d, 0700)
-        return d
-
-    @property
-    def session_dir(self):
-        d = os.path.join(self['data_dir'], 'sessions', release.series)
-        if not os.path.exists(d):
-            os.makedirs(d, 0700)
-        else:
-            os.chmod(d, 0700)
-        return d
-
 config = configmanager()
 
 
diff --git a/openerp/tools/debugger.py b/openerp/tools/debugger.py
deleted file mode 100644 (file)
index 293d405..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-# -*- coding: utf-8 -*-
-# Copyright: 2014 - OpenERP S.A. <http://openerp.com>
-import types
-
-def post_mortem(config, info):
-    if config['debug_mode'] and isinstance(info[2], types.TracebackType):
-        import pdb
-        pdb.post_mortem(info[2])
index 08c2fd9..196ace2 100644 (file)
@@ -32,7 +32,7 @@ from random import randint
 # Image resizing
 # ----------------------------------------
 
-def image_resize_image(base64_source, size=(1024, 1024), encoding='base64', filetype=None, avoid_if_small=False):
+def image_resize_image(base64_source, size=(1024, 1024), encoding='base64', filetype='PNG', avoid_if_small=False):
     """ Function to resize an image. The image will be resized to the given
         size, while keeping the aspect ratios, and holes in the image will be
         filled with transparent background. The image will not be stretched if
@@ -58,8 +58,7 @@ def image_resize_image(base64_source, size=(1024, 1024), encoding='base64', file
             height mean an automatically computed value based respectivelly
             on height or width of the source image.
         :param encoding: the output encoding
-        :param filetype: the output filetype, by default the source image's
-        :type filetype: str, any PIL image format (supported for creation)
+        :param filetype: the output filetype
         :param avoid_if_small: do not resize if image height and width
             are smaller than the expected size.
     """
@@ -69,8 +68,6 @@ def image_resize_image(base64_source, size=(1024, 1024), encoding='base64', file
         return base64_source
     image_stream = StringIO.StringIO(base64_source.decode(encoding))
     image = Image.open(image_stream)
-    # store filetype here, as Image.new below will lose image.format
-    filetype = filetype or image.format
 
     asked_width, asked_height = size
     if asked_width is None:
@@ -98,21 +95,21 @@ def image_resize_image(base64_source, size=(1024, 1024), encoding='base64', file
     image.save(background_stream, filetype)
     return background_stream.getvalue().encode(encoding)
 
-def image_resize_image_big(base64_source, size=(1204, 1024), encoding='base64', filetype=None, avoid_if_small=True):
+def image_resize_image_big(base64_source, size=(1204, 1204), encoding='base64', filetype='PNG', avoid_if_small=True):
     """ Wrapper on image_resize_image, to resize images larger than the standard
         'big' image size: 1024x1024px.
         :param size, encoding, filetype, avoid_if_small: refer to image_resize_image
     """
     return image_resize_image(base64_source, size, encoding, filetype, avoid_if_small)
 
-def image_resize_image_medium(base64_source, size=(128, 128), encoding='base64', filetype=None, avoid_if_small=False):
+def image_resize_image_medium(base64_source, size=(128, 128), encoding='base64', filetype='PNG', avoid_if_small=False):
     """ Wrapper on image_resize_image, to resize to the standard 'medium'
         image size: 180x180.
         :param size, encoding, filetype, avoid_if_small: refer to image_resize_image
     """
     return image_resize_image(base64_source, size, encoding, filetype, avoid_if_small)
 
-def image_resize_image_small(base64_source, size=(64, 64), encoding='base64', filetype=None, avoid_if_small=False):
+def image_resize_image_small(base64_source, size=(64, 64), encoding='base64', filetype='PNG', avoid_if_small=False):
     """ Wrapper on image_resize_image, to resize to the standard 'small' image
         size: 50x50.
         :param size, encoding, filetype, avoid_if_small: refer to image_resize_image
index 94684d3..b5cff6b 100644 (file)
 Some functions related to the os and os.path module
 """
 
-from contextlib import contextmanager
 import os
 from os.path import join as opj
-import shutil
-import tempfile
-import zipfile
 
 if os.name == 'nt':
     import ctypes
@@ -65,30 +61,6 @@ def walksymlinks(top, topdown=True, onerror=None):
         if not topdown:
             yield dirpath, dirnames, filenames
 
-@contextmanager
-def tempdir():
-    tmpdir = tempfile.mkdtemp()
-    try:
-        yield tmpdir
-    finally:
-        shutil.rmtree(tmpdir)
-
-def zip_dir(path, stream, include_dir=True):      # TODO add ignore list
-    path = os.path.normpath(path)
-    len_prefix = len(os.path.dirname(path)) if include_dir else len(path)
-    if len_prefix:
-        len_prefix += 1
-
-    with zipfile.ZipFile(stream, 'w', compression=zipfile.ZIP_DEFLATED, allowZip64=True) as zipf:
-        for dirpath, dirnames, filenames in os.walk(path):
-            for fname in filenames:
-                bname, ext = os.path.splitext(fname)
-                ext = ext or bname
-                if ext not in ['.pyc', '.pyo', '.swp', '.DS_Store']:
-                    path = os.path.normpath(os.path.join(dirpath, fname))
-                    if os.path.isfile(path):
-                        zipf.write(path, path[len_prefix:])
-
 
 if os.name != 'nt':
     getppid = os.getppid
index 508a072..b64b401 100644 (file)
@@ -1,6 +1,6 @@
 # -*- coding: utf-8 -*-
 ##############################################################################
-#    Copyright (C) 2004-2014 OpenERP s.a. (<http://www.openerp.com>).
+#    Copyright (C) 2004-2012 OpenERP s.a. (<http://www.openerp.com>).
 #
 #    This program is free software: you can redistribute it and/or modify
 #    it under the terms of the GNU Affero General Public License as
@@ -225,14 +225,9 @@ def safe_eval(expr, globals_dict=None, locals_dict=None, mode="eval", nocopy=Fal
             'False': False,
             'None': None,
             'str': str,
-            'unicode': unicode,
             'globals': locals,
             'locals': locals,
             'bool': bool,
-            'int': int,
-            'float': float,
-            'long': long,
-            'enumerate': enumerate,
             'dict': dict,
             'list': list,
             'tuple': tuple,
@@ -240,23 +235,15 @@ def safe_eval(expr, globals_dict=None, locals_dict=None, mode="eval", nocopy=Fal
             'abs': abs,
             'min': min,
             'max': max,
-            'sum': sum,
             'reduce': reduce,
             'filter': filter,
             'round': round,
             'len': len,
-            'repr': repr,
             'set': set,
-            'all': all,
-            'any': any,
-            'ord': ord,
-            'chr': chr,
-            'cmp': cmp,
-            'divmod': divmod,
-            'isinstance': isinstance,
+            'repr': repr,
+            'int': int,
+            'float': float,
             'range': range,
-            'xrange': xrange,
-            'zip': zip,
         }
     )
     if locals_builtins:
index b795405..58eefc9 100644 (file)
@@ -458,7 +458,7 @@ def trans_export(lang, modules, buffer, format, cr):
                 row.setdefault('tnrs', []).append((type, name, res_id))
                 row.setdefault('comments', set()).update(comments)
 
-            for src, row in sorted(grouped_rows.items()):
+            for src, row in grouped_rows.items():
                 if not lang:
                     # translation template, so no translation value
                     row['translation'] = ''
@@ -778,32 +778,49 @@ def trans_generate(lang, modules, cr):
         if model_obj._sql_constraints:
             push_local_constraints(module, model_obj, 'sql_constraints')
 
+    def get_module_from_path(path, mod_paths=None):
+        if not mod_paths:
+            # First, construct a list of possible paths
+            def_path = os.path.abspath(os.path.join(config.config['root_path'], 'addons'))     # default addons path (base)
+            ad_paths= map(lambda m: os.path.abspath(m.strip()),config.config['addons_path'].split(','))
+            mod_paths=[def_path]
+            for adp in ad_paths:
+                mod_paths.append(adp)
+                if not os.path.isabs(adp):
+                    mod_paths.append(adp)
+                elif adp.startswith(def_path):
+                    mod_paths.append(adp[len(def_path)+1:])
+        for mp in mod_paths:
+            if path.startswith(mp) and (os.path.dirname(path) != mp):
+                path = path[len(mp)+1:]
+                return path.split(os.path.sep)[0]
+        return 'base'   # files that are not in a module are considered as being in 'base' module
 
     modobj = registry['ir.module.module']
     installed_modids = modobj.search(cr, uid, [('state', '=', 'installed')])
     installed_modules = map(lambda m: m['name'], modobj.read(cr, uid, installed_modids, ['name']))
 
-    path_list = list(openerp.modules.module.ad_paths)
+    root_path = os.path.join(config.config['root_path'], 'addons')
+
+    apaths = map(os.path.abspath, map(str.strip, config.config['addons_path'].split(',')))
+    if root_path in apaths:
+        path_list = apaths
+    else :
+        path_list = [root_path,] + apaths
+
     # Also scan these non-addon paths
     for bin_path in ['osv', 'report' ]:
         path_list.append(os.path.join(config.config['root_path'], bin_path))
 
     _logger.debug("Scanning modules at paths: ", path_list)
 
-    mod_paths = list(path_list)
-
-    def get_module_from_path(path):
-        for mp in mod_paths:
-            if path.startswith(mp) and (os.path.dirname(path) != mp):
-                path = path[len(mp)+1:]
-                return path.split(os.path.sep)[0]
-        return 'base'   # files that are not in a module are considered as being in 'base' module
+    mod_paths = []
 
     def verified_module_filepaths(fname, path, root):
         fabsolutepath = join(root, fname)
         frelativepath = fabsolutepath[len(path):]
         display_path = "addons%s" % frelativepath
-        module = get_module_from_path(fabsolutepath)
+        module = get_module_from_path(fabsolutepath, mod_paths=mod_paths)
         if ('all' in modules or module in modules) and module in installed_modules:
             return module, fabsolutepath, frelativepath, display_path
         return None, None, None, None
index a44e26f..05178fb 100644 (file)
--- a/setup.py
+++ b/setup.py
@@ -75,7 +75,7 @@ def py2exe_options():
                     "skip_archive": 1,
                     "optimize": 0, # keep the assert running, because the integrated tests rely on them.
                     "dist_dir": 'dist',
-                    "packages": ["HTMLParser", "PIL", "asynchat", "asyncore", "commands", "dateutil", "decimal", "docutils", "email", "encodings", "imaplib", "jinja2", "lxml", "lxml._elementpath", "lxml.builder", "lxml.etree", "lxml.objectify", "mako", "openerp", "poplib", "pychart", "pydot", "pyparsing", "pytz", "reportlab", "select", "simplejson", "smtplib", "uuid", "vatnumber", "vobject", "xml", "xml.dom", "yaml", ],
+                    "packages": [ "DAV", "HTMLParser", "PIL", "asynchat", "asyncore", "commands", "dateutil", "decimal", "docutils", "email", "encodings", "imaplib", "jinja2", "lxml", "lxml._elementpath", "lxml.builder", "lxml.etree", "lxml.objectify", "mako", "openerp", "poplib", "pychart", "pydot", "pyparsing", "pytz", "reportlab", "select", "simplejson", "smtplib", "uuid", "vatnumber", "vobject", "xml", "xml.dom", "yaml", ],
                     "excludes" : ["Tkconstants","Tkinter","tcl"],
                 }
             }