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.

132 lines
4.0 KiB

# encoding: utf-8
"""
Custom element classes related to the numbering part
"""
from . import OxmlElement
from .shared import CT_DecimalNumber
from .simpletypes import ST_DecimalNumber
from .xmlchemy import (
BaseOxmlElement, OneAndOnlyOne, RequiredAttribute, ZeroOrMore, ZeroOrOne
)
class CT_Num(BaseOxmlElement):
"""
``<w:num>`` element, which represents a concrete list definition
instance, having a required child <w:abstractNumId> that references an
abstract numbering definition that defines most of the formatting details.
"""
abstractNumId = OneAndOnlyOne('w:abstractNumId')
lvlOverride = ZeroOrMore('w:lvlOverride')
numId = RequiredAttribute('w:numId', ST_DecimalNumber)
def add_lvlOverride(self, ilvl):
"""
Return a newly added CT_NumLvl (<w:lvlOverride>) element having its
``ilvl`` attribute set to *ilvl*.
"""
return self._add_lvlOverride(ilvl=ilvl)
@classmethod
def new(cls, num_id, abstractNum_id):
"""
Return a new ``<w:num>`` element having numId of *num_id* and having
a ``<w:abstractNumId>`` child with val attribute set to
*abstractNum_id*.
"""
num = OxmlElement('w:num')
num.numId = num_id
abstractNumId = CT_DecimalNumber.new(
'w:abstractNumId', abstractNum_id
)
num.append(abstractNumId)
return num
class CT_NumLvl(BaseOxmlElement):
"""
``<w:lvlOverride>`` element, which identifies a level in a list
definition to override with settings it contains.
"""
startOverride = ZeroOrOne('w:startOverride', successors=('w:lvl',))
ilvl = RequiredAttribute('w:ilvl', ST_DecimalNumber)
def add_startOverride(self, val):
"""
Return a newly added CT_DecimalNumber element having tagname
``w:startOverride`` and ``val`` attribute set to *val*.
"""
return self._add_startOverride(val=val)
class CT_NumPr(BaseOxmlElement):
"""
A ``<w:numPr>`` element, a container for numbering properties applied to
a paragraph.
"""
ilvl = ZeroOrOne('w:ilvl', successors=(
'w:numId', 'w:numberingChange', 'w:ins'
))
numId = ZeroOrOne('w:numId', successors=('w:numberingChange', 'w:ins'))
# @ilvl.setter
# def _set_ilvl(self, val):
# """
# Get or add a <w:ilvl> child and set its ``w:val`` attribute to *val*.
# """
# ilvl = self.get_or_add_ilvl()
# ilvl.val = val
# @numId.setter
# def numId(self, val):
# """
# Get or add a <w:numId> child and set its ``w:val`` attribute to
# *val*.
# """
# numId = self.get_or_add_numId()
# numId.val = val
class CT_Numbering(BaseOxmlElement):
"""
``<w:numbering>`` element, the root element of a numbering part, i.e.
numbering.xml
"""
num = ZeroOrMore('w:num', successors=('w:numIdMacAtCleanup',))
def add_num(self, abstractNum_id):
"""
Return a newly added CT_Num (<w:num>) element referencing the
abstract numbering definition identified by *abstractNum_id*.
"""
next_num_id = self._next_numId
num = CT_Num.new(next_num_id, abstractNum_id)
return self._insert_num(num)
def num_having_numId(self, numId):
"""
Return the ``<w:num>`` child element having ``numId`` attribute
matching *numId*.
"""
xpath = './w:num[@w:numId="%d"]' % numId
try:
return self.xpath(xpath)[0]
except IndexError:
raise KeyError('no <w:num> element with numId %d' % numId)
@property
def _next_numId(self):
"""
The first ``numId`` unused by a ``<w:num>`` element, starting at
1 and filling any gaps in numbering between existing ``<w:num>``
elements.
"""
numId_strs = self.xpath('./w:num/@w:numId')
num_ids = [int(numId_str) for numId_str in numId_strs]
for num in range(1, len(num_ids)+2):
if num not in num_ids:
break
return num