2025-10-10 09:46:41 +02:00

159 lines
4.7 KiB
Python

#!/usr/bin/env python
#coding:utf-8
# Purpose: ODF styles.xml document management
# Created: 28.12.2010
# Copyright (C) 2010, Manfred Moitzi
# License: MIT license
from __future__ import unicode_literals, print_function, division
__author__ = "mozman <mozman@gmx.at>"
from .const import STYLES_NSMAP
from .xmlns import XMLMixin, subelement, etree, CN, register_class, wrap
from .base import GenericWrapper
## file 'styles.xml'
@register_class
class OfficeDocumentStyles(XMLMixin):
TAG = CN('office:document-styles')
def __init__(self, xmlnode=None):
if xmlnode is None:
self.xmlnode = etree.Element(self.TAG, nsmap=STYLES_NSMAP)
elif xmlnode.tag == self.TAG:
self.xmlnode = xmlnode
else:
raise ValueError("Unexpected root node: %s" % content.tag)
self._setup()
def _setup(self):
self.fonts = wrap(subelement(self.xmlnode, CN('office:font-face-decls')))
self.styles = wrap(subelement(self.xmlnode, CN('office:styles')))
self.automatic_styles = wrap(subelement(self.xmlnode, CN('office:automatic-styles')))
self.master_styles = wrap(subelement(self.xmlnode, CN('office:master-styles')))
## style container
class Container(object):
def __init__(self, xmlnode):
assert xmlnode.tag == self.TAG
self.xmlnode = xmlnode
self._cache = {}
def __getitem__(self, key):
style = self._find(key) # by style:name attribute
if style is not None:
return wrap(style)
else:
raise KeyError(key)
def __setitem__(self, key, value):
style = self._find(key)
if style is None:
self.xmlnode.append(value.xmlnode)
else:
self.xmlnode.replace(style, value.xmlnode)
self._cache[key] = value
def _find(self, name):
try:
return self._cache[name]
except KeyError:
for style in self.xmlnode.iterchildren():
stylename = style.get(CN('style:name'))
if stylename == name:
self._cache[name] = style
return style
return None
@register_class
class OfficeFontFaceDecls(Container):
TAG = CN('office:font-face-decls')
@register_class
class OfficeStyles(Container):
TAG = CN('office:styles')
@register_class
class OfficeAutomaticStyles(Container):
TAG = CN('office:automatic-styles')
@register_class
class OfficeMasterStyles(Container):
TAG = CN('office:master-styles')
## style objects
class BaseStyle:
ATTRIBUTEMAP = {}
def __init__(self, xmlnode):
self.xmlnode = xmlnode
def __getitem__(self, key):
""" Get style attribute 'key'. """
return self.xmlnode.get(self.ATTRIBUTEMAP[key])
def __setitem__(self, key, value):
""" Set style attribute 'key' to 'value'. """
def _properties(self, key, property_factory, new=True):
""" Get or create a properties element. """
element = subelement(self.xmlnode, key , new)
if element is None:
raise KeyError(key)
propertiesname = key + '-properties'
properties = element.find(propertiesname)
if properties is None:
properties = etree.SubElement(element, propertiesname)
return property_factory(properties)
class Properties(BaseStyle):
ATTRIBUTEMAP = {} # should contain all possible property names
pass
HeaderProperties = Properties
@register_class
class Style(BaseStyle):
TAG = CN('style:style')
ATTRIBUTEMAP = {
'name': CN('style:name'),
'display-name': CN('style:display-name'),
'family': CN('style:family'),
'parent-style-name': CN('style:parent-style-name'),
'next-style-name': CN('style:next-style-name'),
'list-style-name': CN('style:list-style-name'),
'master-page-name': CN('style:master-page-name'),
'auto-update': CN('style:auto-update'), # 'true' or 'false'
'data-style-name': CN('style:data-style-name'),
'class': CN('style:class'),
'default-outline-level': CN('style:default-outline-level'),
}
@register_class
class DefaultStyle(BaseStyle):
TAG = CN('style:default-style')
ATTRIBUTEMAP = {
'family': CN('style:family'),
}
@register_class
class PageLayout(BaseStyle):
TAG = CN('style:page-layout')
ATTRIBUTEMAP = {
'name': CN('style:name'),
'page-usage': CN('style:page-usage'), # all | left | right | mirrored
}
def __init__(self, xmlelement):
super(PageLayout, self).__init__(xmlelement)
self.header = self._properties(CN('style:header-style'), HeaderProperties)
self.footer = self._properties(CN('style:footer-style'), HeaderProperties)
@register_class
class FontFace(BaseStyle):
TAG = CN('style:font-face')