diff --git a/addons/document/models/ir_attachment.py b/addons/document/models/ir_attachment.py index c10f5b1013e..efa244f0dfa 100644 --- a/addons/document/models/ir_attachment.py +++ b/addons/document/models/ir_attachment.py @@ -7,34 +7,105 @@ from StringIO import StringIO import pyPdf -import openerp -from openerp.osv import fields, osv +from openerp.osv import osv _logger = logging.getLogger(__name__) +FTYPES = ['docx', 'pptx', 'xlsx', 'opendoc', 'pdf'] + +# Keep function in case it is necessary to do toUnicode(buf.encode('ascii', 'replace')) +def toUnicode(s): + try: + return s.decode('utf-8') + except UnicodeError: + try: + return s.decode('latin') + except UnicodeError: + try: + return s.encode('ascii') + except UnicodeError: + return s + +def textToString(element): + buff = u"" + for node in element.childNodes: + if node.nodeType == xml.dom.Node.TEXT_NODE: + buff += node.nodeValue + elif node.nodeType == xml.dom.Node.ELEMENT_NODE: + buff += textToString(node) + return buff + class IrAttachment(osv.osv): _inherit = 'ir.attachment' - def _index_odt(self, bin_data): + def _index_docx(self, bin_data): + '''Index Microsoft .docx documents''' buf = u"" f = StringIO(bin_data) if zipfile.is_zipfile(f): try: zf = zipfile.ZipFile(f) - self.content = xml.dom.minidom.parseString(zf.read("content.xml")) + content = xml.dom.minidom.parseString(zf.read("word/document.xml")) + for val in ["w:p", "w:h", "text:list"]: + for element in content.getElementsByTagName(val): + buf += textToString(element) + "\n" + except Exception: + pass + return buf + + def _index_pptx(self, bin_data): + '''Index Microsoft .pptx documents''' + + buf = u"" + f = StringIO(bin_data) + if zipfile.is_zipfile(f): + try: + zf = zipfile.ZipFile(f) + zf_filelist = [x for x in zf.namelist() if x.startswith('ppt/slides/slide')] + for i in range(1, len(zf_filelist) + 1): + content = xml.dom.minidom.parseString(zf.read('ppt/slides/slide%s.xml' % i)) + for val in ["a:t"]: + for element in content.getElementsByTagName(val): + buf += textToString(element) + "\n" + except Exception: + pass + return buf + + def _index_xlsx(self, bin_data): + '''Index Microsoft .xlsx documents''' + + buf = u"" + f = StringIO(bin_data) + if zipfile.is_zipfile(f): + try: + zf = zipfile.ZipFile(f) + content = xml.dom.minidom.parseString(zf.read("xl/sharedStrings.xml")) + for val in ["t"]: + for element in content.getElementsByTagName(val): + buf += textToString(element) + "\n" + except Exception: + pass + return buf + + def _index_opendoc(self, bin_data): + '''Index OpenDocument documents (.odt, .ods...)''' + + buf = u"" + f = StringIO(bin_data) + if zipfile.is_zipfile(f): + try: + zf = zipfile.ZipFile(f) + content = xml.dom.minidom.parseString(zf.read("content.xml")) for val in ["text:p", "text:h", "text:list"]: - for element in self.content.getElementsByTagName(val) : - for node in element.childNodes : - if node.nodeType == xml.dom.Node.TEXT_NODE : - buf += node.nodeValue - elif node.nodeType == xml.dom.Node.ELEMENT_NODE : - buf += self.textToString(node) - buf += "\n" + for element in content.getElementsByTagName(val): + buf += textToString(element) + "\n" except Exception: pass return buf def _index_pdf(self, bin_data): + '''Index PDF documents''' + buf = u"" if bin_data.startswith('%PDF-'): f = StringIO(bin_data) @@ -47,14 +118,9 @@ class IrAttachment(osv.osv): return buf def _index(self, cr, uid, bin_data, datas_fname, mimetype): - # try to index odt content - buf = self._index_odt(bin_data) - if buf: - return buf - # try to index pdf content - buf = self._index_pdf(bin_data) - if buf: - return buf + for ftype in FTYPES: + buf = getattr(self, '_index_%s' % ftype)(bin_data) + if buf: + return buf return super(IrAttachment, self)._index(cr, uid, bin_data, datas_fname, mimetype) - diff --git a/addons/web_kanban/static/src/js/kanban_column.js b/addons/web_kanban/static/src/js/kanban_column.js index 7718991b10f..0094ad01743 100644 --- a/addons/web_kanban/static/src/js/kanban_column.js +++ b/addons/web_kanban/static/src/js/kanban_column.js @@ -91,7 +91,7 @@ var KanbanColumn = Widget.extend({ connectWith: '.o_kanban_group', revert: 0, delay: 0, - items: '> .o_kanban_record', + items: '> .o_kanban_record:not(.o_updating)', helper: 'clone', cursor: 'move', over: function () { @@ -117,6 +117,7 @@ var KanbanColumn = Widget.extend({ // adding record to this column self.records.push(record); record.setParent(self); + ui.item.addClass('o_updating'); self.trigger_up('kanban_column_add_record', {record: record}); } self.update_column(); diff --git a/addons/website/static/src/js/website.snippets.animation.js b/addons/website/static/src/js/website.snippets.animation.js index 87b7e6dce46..a278ed1196e 100644 --- a/addons/website/static/src/js/website.snippets.animation.js +++ b/addons/website/static/src/js/website.snippets.animation.js @@ -99,12 +99,19 @@ animation.registry.parallax = animation.Class.extend({ animation.registry.share = animation.Class.extend({ selector: ".oe_share", start: function () { + var url_regex = /(\?(?:|.*&)(?:u|url|body)=)(.*?)(&|#|$)/; + var title_regex = /(\?(?:|.*&)(?:title|text|subject)=)(.*?)(&|#|$)/; var url = encodeURIComponent(window.location.href); var title = encodeURIComponent($("title").text()); this.$("a").each(function () { var $a = $(this); - var url_regex = /\{url\}|%7Burl%7D/, title_regex = /\{title\}|%7Btitle%7D/; - $a.attr("href", $(this).attr("href").replace(url_regex, url).replace(title_regex, title)); + $a.attr("href", function(i, href) { + return href.replace(url_regex, function (match, a, b, c) { + return a + url + c; + }).replace(title_regex, function (match, a, b, c) { + return a + title + c; + }); + }); if ($a.attr("target") && $a.attr("target").match(/_blank/i) && !$a.closest('.o_editable').length) { $a.on('click', function () { window.open(this.href,'','menubar=no,toolbar=no,resizable=yes,scrollbars=yes,height=550,width=600'); diff --git a/openerp/fields.py b/openerp/fields.py index eb76529ebb5..2eba4e39c79 100644 --- a/openerp/fields.py +++ b/openerp/fields.py @@ -1031,7 +1031,7 @@ class Field(object): target = records - computed elif path and env.in_onchange: target = (target.browse(env.cache[field]) - computed).filtered( - lambda rec: rec._mapped_cache(path) & records + lambda rec: rec if path == 'id' else rec._mapped_cache(path) & records ) else: target = target.browse(env.cache[field]) - computed diff --git a/setup.cfg b/setup.cfg index cccec6c615c..cc4ff5c2171 100644 --- a/setup.cfg +++ b/setup.cfg @@ -27,6 +27,7 @@ requires = python-requests python-vobject python-werkzeug + python-xlwt python-yaml pytz diff --git a/setup/package.dfcentos b/setup/package.dfcentos index 31adfcf307e..6b09ae64daf 100644 --- a/setup/package.dfcentos +++ b/setup/package.dfcentos @@ -31,6 +31,7 @@ RUN yum install -d 0 -e 0 epel-release -y && \ python-requests \ python-vobject \ python-werkzeug \ + python-xlwt \ python-yaml \ pytz \ postgresql \