You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
154 lines
5.5 KiB
154 lines
5.5 KiB
# encoding: utf-8
|
|
|
|
"""Styles object, container for all objects in the styles part"""
|
|
|
|
from __future__ import absolute_import, division, print_function, unicode_literals
|
|
|
|
from warnings import warn
|
|
|
|
from docx.shared import ElementProxy
|
|
from docx.styles import BabelFish
|
|
from docx.styles.latent import LatentStyles
|
|
from docx.styles.style import BaseStyle, StyleFactory
|
|
|
|
|
|
class Styles(ElementProxy):
|
|
"""Provides access to the styles defined in a document.
|
|
|
|
Accessed using the :attr:`.Document.styles` property. Supports ``len()``, iteration,
|
|
and dictionary-style access by style name.
|
|
"""
|
|
|
|
__slots__ = ()
|
|
|
|
def __contains__(self, name):
|
|
"""
|
|
Enables `in` operator on style name.
|
|
"""
|
|
internal_name = BabelFish.ui2internal(name)
|
|
for style in self._element.style_lst:
|
|
if style.name_val == internal_name:
|
|
return True
|
|
return False
|
|
|
|
def __getitem__(self, key):
|
|
"""
|
|
Enables dictionary-style access by UI name. Lookup by style id is
|
|
deprecated, triggers a warning, and will be removed in a near-future
|
|
release.
|
|
"""
|
|
style_elm = self._element.get_by_name(BabelFish.ui2internal(key))
|
|
if style_elm is not None:
|
|
return StyleFactory(style_elm)
|
|
|
|
style_elm = self._element.get_by_id(key)
|
|
if style_elm is not None:
|
|
msg = (
|
|
'style lookup by style_id is deprecated. Use style name as '
|
|
'key instead.'
|
|
)
|
|
warn(msg, UserWarning, stacklevel=2)
|
|
return StyleFactory(style_elm)
|
|
|
|
raise KeyError("no style with name '%s'" % key)
|
|
|
|
def __iter__(self):
|
|
return (StyleFactory(style) for style in self._element.style_lst)
|
|
|
|
def __len__(self):
|
|
return len(self._element.style_lst)
|
|
|
|
def add_style(self, name, style_type, builtin=False):
|
|
"""
|
|
Return a newly added style object of *style_type* and identified
|
|
by *name*. A builtin style can be defined by passing True for the
|
|
optional *builtin* argument.
|
|
"""
|
|
style_name = BabelFish.ui2internal(name)
|
|
if style_name in self:
|
|
raise ValueError("document already contains style '%s'" % name)
|
|
style = self._element.add_style_of_type(
|
|
style_name, style_type, builtin
|
|
)
|
|
return StyleFactory(style)
|
|
|
|
def default(self, style_type):
|
|
"""
|
|
Return the default style for *style_type* or |None| if no default is
|
|
defined for that type (not common).
|
|
"""
|
|
style = self._element.default_for(style_type)
|
|
if style is None:
|
|
return None
|
|
return StyleFactory(style)
|
|
|
|
def get_by_id(self, style_id, style_type):
|
|
"""Return the style of *style_type* matching *style_id*.
|
|
|
|
Returns the default for *style_type* if *style_id* is not found or is |None|, or
|
|
if the style having *style_id* is not of *style_type*.
|
|
"""
|
|
if style_id is None:
|
|
return self.default(style_type)
|
|
return self._get_by_id(style_id, style_type)
|
|
|
|
def get_style_id(self, style_or_name, style_type):
|
|
"""
|
|
Return the id of the style corresponding to *style_or_name*, or
|
|
|None| if *style_or_name* is |None|. If *style_or_name* is not
|
|
a style object, the style is looked up using *style_or_name* as
|
|
a style name, raising |ValueError| if no style with that name is
|
|
defined. Raises |ValueError| if the target style is not of
|
|
*style_type*.
|
|
"""
|
|
if style_or_name is None:
|
|
return None
|
|
elif isinstance(style_or_name, BaseStyle):
|
|
return self._get_style_id_from_style(style_or_name, style_type)
|
|
else:
|
|
return self._get_style_id_from_name(style_or_name, style_type)
|
|
|
|
@property
|
|
def latent_styles(self):
|
|
"""
|
|
A |LatentStyles| object providing access to the default behaviors for
|
|
latent styles and the collection of |_LatentStyle| objects that
|
|
define overrides of those defaults for a particular named latent
|
|
style.
|
|
"""
|
|
return LatentStyles(self._element.get_or_add_latentStyles())
|
|
|
|
def _get_by_id(self, style_id, style_type):
|
|
"""
|
|
Return the style of *style_type* matching *style_id*. Returns the
|
|
default for *style_type* if *style_id* is not found or if the style
|
|
having *style_id* is not of *style_type*.
|
|
"""
|
|
style = self._element.get_by_id(style_id)
|
|
if style is None or style.type != style_type:
|
|
return self.default(style_type)
|
|
return StyleFactory(style)
|
|
|
|
def _get_style_id_from_name(self, style_name, style_type):
|
|
"""
|
|
Return the id of the style of *style_type* corresponding to
|
|
*style_name*. Returns |None| if that style is the default style for
|
|
*style_type*. Raises |ValueError| if the named style is not found in
|
|
the document or does not match *style_type*.
|
|
"""
|
|
return self._get_style_id_from_style(self[style_name], style_type)
|
|
|
|
def _get_style_id_from_style(self, style, style_type):
|
|
"""
|
|
Return the id of *style*, or |None| if it is the default style of
|
|
*style_type*. Raises |ValueError| if style is not of *style_type*.
|
|
"""
|
|
if style.type != style_type:
|
|
raise ValueError(
|
|
"assigned style is type %s, need type %s" %
|
|
(style.type, style_type)
|
|
)
|
|
if style == self.default(style_type):
|
|
return None
|
|
return style.style_id
|