Use file from the Binary field to display document
On Windows the file used to create the Evince document must be kept after the initialization. Also reusing the file cache mechanism of the Binary field, prevents to create temporary files on each call of display. Evince document needs to have the proper extension to be sure to load the proper backend. So the cache file must be retrieved with the requested extension. And finally we use Document.factory_get_document_full so if leading with the filename extension does not work, it will try to guess from the data. Closes #13307 (grafted from 34deeaf3c0215f793c3e673de3ee2e04971ebee4) --HG-- branch : 7.0
This commit is contained in:
@@ -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):
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user