Implement setMetadata for odt files

1841506
This commit is contained in:
Alexis Piéplu 2019-09-10 14:06:17 -04:00
parent d1248f8260
commit 10cd485766
2 changed files with 43 additions and 8 deletions

View File

@ -578,12 +578,21 @@ class TXTZMetadataWriter(MetadataWriterPlugin):
from calibre.ebooks.metadata.extz import set_metadata from calibre.ebooks.metadata.extz import set_metadata
set_metadata(stream, mi) set_metadata(stream, mi)
class ODTMetadataWriter(MetadataWriterPlugin):
name = 'Set ODT metadata'
file_types = {'odt'}
description = _('Set metadata from %s files')%'ODT'
def set_metadata(self, stream, mi, type):
from calibre.ebooks.metadata.odt import set_metadata
return set_metadata(stream, mi)
class DocXMetadataWriter(MetadataWriterPlugin): class DocXMetadataWriter(MetadataWriterPlugin):
name = 'Set DOCX metadata' name = 'Set DOCX metadata'
file_types = {'docx'} file_types = {'docx'}
description = _('Read metadata from %s files')%'DOCX' description = _('Set metadata from %s files')%'DOCX'
def set_metadata(self, stream, mi, type): def set_metadata(self, stream, mi, type):
from calibre.ebooks.metadata.docx import set_metadata from calibre.ebooks.metadata.docx import set_metadata

View File

@ -20,17 +20,18 @@
# #
from __future__ import absolute_import, division, print_function, unicode_literals from __future__ import absolute_import, division, print_function, unicode_literals
import zipfile, re, io import zipfile, re, io, os
import xml.sax.saxutils import xml.sax.saxutils
from odf.namespaces import OFFICENS, DCNS, METANS from odf.namespaces import OFFICENS, DCNS, METANS
from odf.opendocument import load as odLoad from odf.opendocument import load as odLoad
from odf.draw import Image as odImage, Frame as odFrame from odf.draw import Image as odImage, Frame as odFrame
from calibre.ebooks.metadata import MetaInformation, string_to_authors, check_isbn from calibre.ebooks.metadata import MetaInformation, string_to_authors, check_isbn, authors_to_string
from calibre.utils.imghdr import identify from calibre.utils.imghdr import identify
from calibre.utils.date import parse_date from calibre.utils.date import parse_date
from calibre.utils.localization import canonicalize_lang from calibre.utils.localization import canonicalize_lang, lang_as_iso639_1
from polyglot.builtins import string_or_bytes from polyglot.builtins import string_or_bytes
whitespace = re.compile(r'\s+') whitespace = re.compile(r'\s+')
@ -157,16 +158,19 @@ class odfmetaparser(xml.sax.saxutils.XMLGenerator):
def data(self): def data(self):
return normalize(''.join(self._data)) return normalize(''.join(self._data))
def get_odf_meta_parsed(stream, mode = 'r', deletefields={}, yieldfields={}, addfields={}):
def get_metadata(stream, extract_cover=True): zin = zipfile.ZipFile(stream, mode)
zin = zipfile.ZipFile(stream, 'r') odfs = odfmetaparser(deletefields, yieldfields, addfields)
odfs = odfmetaparser()
parser = xml.sax.make_parser() parser = xml.sax.make_parser()
parser.setFeature(xml.sax.handler.feature_namespaces, True) parser.setFeature(xml.sax.handler.feature_namespaces, True)
parser.setFeature(xml.sax.handler.feature_external_ges, False) parser.setFeature(xml.sax.handler.feature_external_ges, False)
parser.setContentHandler(odfs) parser.setContentHandler(odfs)
content = zin.read('meta.xml') content = zin.read('meta.xml')
parser.parse(io.BytesIO(content)) parser.parse(io.BytesIO(content))
return (zin, odfs)
def get_metadata(stream, extract_cover=True):
zin, odfs = get_odf_meta_parsed(stream)
data = odfs.seenfields data = odfs.seenfields
mi = MetaInformation(None, []) mi = MetaInformation(None, [])
if 'title' in data: if 'title' in data:
@ -220,6 +224,28 @@ def get_metadata(stream, extract_cover=True):
return mi return mi
def get_meta_doc_props(mi):
metaFields = {}
metaFields[fields.get('title')] = mi.title
metaFields[fields.get('creator')] = authors_to_string(mi.authors)
if mi.tags:
metaFields[fields.get('keyword')] = ', '.join(mi.tags)
if mi.comments:
metaFields[fields.get('description')] = mi.comments
if mi.languages:
l = canonicalize_lang(mi.languages[0])
metaFields[fields.get('language')] = lang_as_iso639_1(l) or l
return metaFields
def set_metadata(stream, mi):
from calibre.utils.zipfile import safe_replace
metaFields = get_meta_doc_props(mi)
zin, odfs = get_odf_meta_parsed(stream, addfields=metaFields, deletefields=metaFields)
stream.seek(os.SEEK_SET)
safe_replace(stream, "meta.xml", io.BytesIO(str(odfs.meta())))
def read_cover(stream, zin, mi, opfmeta, extract_cover): def read_cover(stream, zin, mi, opfmeta, extract_cover):
# search for an draw:image in a draw:frame with the name 'opf.cover' # search for an draw:image in a draw:frame with the name 'opf.cover'