diff --git a/tryton/tryton/gui/window/view_form/model/field.py b/tryton/tryton/gui/window/view_form/model/field.py index 6b53cc7532..7b3fd26a16 100644 --- a/tryton/tryton/gui/window/view_form/model/field.py +++ b/tryton/tryton/gui/window/view_form/model/field.py @@ -9,6 +9,7 @@ import os import tempfile from decimal import Decimal from itertools import chain +from pathlib import Path import tryton.common as common from tryton.common import ( @@ -1048,26 +1049,56 @@ class ReferenceField(Field): class _FileCache(object): - def __init__(self, path): - self.path = path + def __init__(self, data=None): + _, filename = tempfile.mkstemp(prefix='tryton_') + self.path = Path(filename) + self.suffixes = {} + if data: + with open(self.path, 'wb') as fp: + fp.write(data) + + @property + def data(self): + with open(self.path, 'rb') as fp: + return fp.read() def __del__(self): try: os.remove(self.path) except IOError: pass + for path in self.suffixes.values(): + try: + os.remove(path) + except IOError: + pass + + def with_suffix(self, suffix): + if suffix in self.suffixes: + return self.suffixes[suffix] + _, filename = tempfile.mkstemp(prefix='tryton_', suffix=suffix) + self.suffixes[suffix] = path = Path(filename) + with open(path, 'wb') as fp: + fp.write(self.data) + return path class BinaryField(Field): _default = None + def _set_file_cache(self, record, data): + if isinstance(data, str): + data = data.encode('utf-8') + file_cache = _FileCache(data) + self.set(record, file_cache) + return file_cache + def get(self, record): result = record.value.get(self.name, self._default) if isinstance(result, _FileCache): try: - with open(result.path, 'rb') as fp: - result = fp.read() + result = result.data except IOError: result = self.get_data(record) return result @@ -1076,13 +1107,7 @@ class BinaryField(Field): return self.get(record) def set_client(self, record, value, force_change=False): - _, filename = tempfile.mkstemp(prefix='tryton_') - data = value or b'' - if isinstance(data, str): - data = data.encode('utf-8') - with open(filename, 'wb') as fp: - fp.write(data) - self.set(record, _FileCache(filename)) + self._set_file_cache(record, value or b'') self.sig_changed(record) record.validate(softvalidation=True) record.set_modified(self.name) @@ -1106,15 +1131,20 @@ class BinaryField(Field): [record.id], [self.name], context=context) except RPCException: return b'' - _, filename = tempfile.mkstemp(prefix='tryton_') - data = values[self.name] or b'' - if isinstance(data, str): - data = data.encode('utf-8') - with open(filename, 'wb') as fp: - fp.write(data) - self.set(record, _FileCache(filename)) + self._set_file_cache(record, values[self.name] or b'') return self.get(record) + def get_filename(self, record, suffix=None): + data = self.get_data(record) + file_cache = record.value.get(self.name) + if not isinstance(file_cache, _FileCache): + file_cache = self._set_file_cache(record, data) + if suffix: + filename = file_cache.with_suffix(suffix) + else: + filename = file_cache.path + return filename + class DictField(Field): diff --git a/tryton/tryton/gui/window/view_form/view/form_gtk/document.py b/tryton/tryton/gui/window/view_form/view/form_gtk/document.py index 5ba988cff1..4a1ea2bb1b 100644 --- a/tryton/tryton/gui/window/view_form/view/form_gtk/document.py +++ b/tryton/tryton/gui/window/view_form/view/form_gtk/document.py @@ -1,7 +1,6 @@ # This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. from pathlib import Path -from tempfile import NamedTemporaryFile from gi.repository import Gdk, GLib, Gtk @@ -76,17 +75,17 @@ class Document(BinaryMixin, Widget): self.image.hide() if self.evince_view: self.evince_scroll.show() + suffix = None if self.filename_field: - suffix = self.filename_field.get(self.record) - else: - suffix = None + filename = self.filename_field.get(self.record) + if filename: + suffix = Path(filename).suffix + filename = Path(self.field.get_filename(self.record, suffix)) try: - with NamedTemporaryFile(suffix=suffix) as fp: - fp.write(data) - path = Path(fp.name) - document = ( - EvinceDocument.Document.factory_get_document( - path.as_uri())) + document = ( + EvinceDocument.Document.factory_get_document_full( + filename.as_uri(), + EvinceDocument.DocumentLoadFlags.NONE)) model = EvinceView.DocumentModel() model.set_document(document) self.evince_view.set_model(model)