novelWriter 2.3rc1__py3-none-any.whl → 2.4__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {novelWriter-2.3rc1.dist-info → novelWriter-2.4.dist-info}/METADATA +5 -6
- {novelWriter-2.3rc1.dist-info → novelWriter-2.4.dist-info}/RECORD +119 -109
- {novelWriter-2.3rc1.dist-info → novelWriter-2.4.dist-info}/WHEEL +1 -1
- novelWriter-2.4.dist-info/entry_points.txt +2 -0
- novelwriter/__init__.py +17 -10
- novelwriter/assets/i18n/nw_de_DE.qm +0 -0
- novelwriter/assets/i18n/nw_en_US.qm +0 -0
- novelwriter/assets/i18n/nw_es_419.qm +0 -0
- novelwriter/assets/i18n/nw_fr_FR.qm +0 -0
- novelwriter/assets/i18n/nw_it_IT.qm +0 -0
- novelwriter/assets/i18n/nw_ja_JP.qm +0 -0
- novelwriter/assets/i18n/nw_nb_NO.qm +0 -0
- novelwriter/assets/i18n/nw_nl_NL.qm +0 -0
- novelwriter/assets/i18n/nw_pt_BR.qm +0 -0
- novelwriter/assets/i18n/nw_zh_CN.qm +0 -0
- novelwriter/assets/i18n/project_nl_NL.json +11 -0
- novelwriter/assets/i18n/project_pt_BR.json +11 -0
- novelwriter/assets/icons/none.svg +4 -0
- novelwriter/assets/icons/typicons_dark/icons.conf +4 -0
- novelwriter/assets/icons/typicons_dark/nw_tb-mark.svg +7 -0
- novelwriter/assets/icons/typicons_dark/typ_refresh-flipped.svg +1 -1
- novelwriter/assets/icons/typicons_dark/typ_refresh.svg +1 -1
- novelwriter/assets/icons/typicons_dark/typ_search-grey.svg +4 -0
- novelwriter/assets/icons/typicons_dark/typ_times.svg +1 -1
- novelwriter/assets/icons/typicons_dark/typ_unfold-hidden.svg +4 -0
- novelwriter/assets/icons/typicons_dark/typ_unfold-visible.svg +4 -0
- novelwriter/assets/icons/typicons_light/icons.conf +4 -0
- novelwriter/assets/icons/typicons_light/nw_tb-mark.svg +7 -0
- novelwriter/assets/icons/typicons_light/typ_refresh-flipped.svg +1 -1
- novelwriter/assets/icons/typicons_light/typ_refresh.svg +1 -1
- novelwriter/assets/icons/typicons_light/typ_search-grey.svg +4 -0
- novelwriter/assets/icons/typicons_light/typ_times.svg +1 -1
- novelwriter/assets/icons/typicons_light/typ_unfold-hidden.svg +4 -0
- novelwriter/assets/icons/typicons_light/typ_unfold-visible.svg +4 -0
- novelwriter/assets/manual.pdf +0 -0
- novelwriter/assets/sample.zip +0 -0
- novelwriter/assets/syntax/cyberpunk_night.conf +26 -0
- novelwriter/assets/syntax/default_dark.conf +1 -0
- novelwriter/assets/syntax/default_light.conf +1 -0
- novelwriter/assets/syntax/grey_dark.conf +1 -0
- novelwriter/assets/syntax/grey_light.conf +1 -0
- novelwriter/assets/syntax/light_owl.conf +1 -0
- novelwriter/assets/syntax/night_owl.conf +1 -0
- novelwriter/assets/syntax/solarized_dark.conf +1 -0
- novelwriter/assets/syntax/solarized_light.conf +1 -0
- novelwriter/assets/syntax/tango.conf +23 -0
- novelwriter/assets/syntax/tomorrow.conf +1 -0
- novelwriter/assets/syntax/tomorrow_night.conf +1 -0
- novelwriter/assets/syntax/tomorrow_night_blue.conf +1 -0
- novelwriter/assets/syntax/tomorrow_night_bright.conf +1 -0
- novelwriter/assets/syntax/tomorrow_night_eighties.conf +1 -0
- novelwriter/assets/text/credits_en.htm +25 -23
- novelwriter/assets/themes/cyberpunk_night.conf +29 -0
- novelwriter/common.py +12 -4
- novelwriter/config.py +47 -16
- novelwriter/constants.py +5 -6
- novelwriter/core/buildsettings.py +64 -44
- novelwriter/core/coretools.py +97 -13
- novelwriter/core/docbuild.py +74 -7
- novelwriter/core/document.py +24 -3
- novelwriter/core/index.py +31 -112
- novelwriter/core/project.py +11 -15
- novelwriter/core/projectxml.py +3 -2
- novelwriter/core/sessions.py +2 -2
- novelwriter/core/spellcheck.py +3 -3
- novelwriter/core/status.py +6 -5
- novelwriter/core/storage.py +16 -6
- novelwriter/core/tohtml.py +22 -25
- novelwriter/core/tokenizer.py +417 -237
- novelwriter/core/tomd.py +17 -8
- novelwriter/core/toodt.py +386 -351
- novelwriter/core/tree.py +8 -8
- novelwriter/dialogs/about.py +10 -12
- novelwriter/dialogs/docmerge.py +17 -14
- novelwriter/dialogs/docsplit.py +20 -19
- novelwriter/dialogs/editlabel.py +5 -4
- novelwriter/dialogs/preferences.py +32 -40
- novelwriter/dialogs/projectsettings.py +31 -28
- novelwriter/dialogs/quotes.py +10 -9
- novelwriter/dialogs/wordlist.py +18 -15
- novelwriter/enum.py +17 -14
- novelwriter/error.py +14 -12
- novelwriter/extensions/circularprogress.py +12 -8
- novelwriter/extensions/configlayout.py +23 -3
- novelwriter/extensions/modified.py +51 -2
- novelwriter/extensions/pagedsidebar.py +16 -14
- novelwriter/extensions/simpleprogress.py +3 -1
- novelwriter/extensions/statusled.py +3 -1
- novelwriter/extensions/switch.py +10 -9
- novelwriter/extensions/switchbox.py +14 -13
- novelwriter/extensions/versioninfo.py +1 -1
- novelwriter/gui/doceditor.py +433 -496
- novelwriter/gui/dochighlight.py +54 -33
- novelwriter/gui/docviewer.py +162 -175
- novelwriter/gui/docviewerpanel.py +20 -37
- novelwriter/gui/editordocument.py +15 -4
- novelwriter/gui/itemdetails.py +51 -54
- novelwriter/gui/mainmenu.py +37 -17
- novelwriter/gui/noveltree.py +31 -37
- novelwriter/gui/outline.py +120 -98
- novelwriter/gui/projtree.py +114 -112
- novelwriter/gui/search.py +362 -0
- novelwriter/gui/sidebar.py +36 -45
- novelwriter/gui/statusbar.py +14 -14
- novelwriter/gui/theme.py +116 -34
- novelwriter/guimain.py +216 -207
- novelwriter/shared.py +31 -6
- novelwriter/text/counting.py +138 -0
- novelwriter/tools/dictionaries.py +15 -14
- novelwriter/tools/lipsum.py +20 -17
- novelwriter/tools/manusbuild.py +43 -35
- novelwriter/tools/manuscript.py +381 -104
- novelwriter/tools/manussettings.py +263 -125
- novelwriter/tools/noveldetails.py +21 -19
- novelwriter/tools/welcome.py +59 -57
- novelwriter/tools/writingstats.py +61 -55
- novelwriter/types.py +90 -0
- novelWriter-2.3rc1.dist-info/entry_points.txt +0 -5
- novelwriter/core/__init__.py +0 -3
- novelwriter/dialogs/__init__.py +0 -3
- novelwriter/extensions/__init__.py +0 -3
- novelwriter/gui/__init__.py +0 -3
- novelwriter/tools/__init__.py +0 -3
- {novelWriter-2.3rc1.dist-info → novelWriter-2.4.dist-info}/LICENSE.md +0 -0
- {novelWriter-2.3rc1.dist-info → novelWriter-2.4.dist-info}/top_level.txt +0 -0
novelwriter/core/toodt.py
CHANGED
@@ -60,8 +60,7 @@ for ns, uri in XML_NS.items():
|
|
60
60
|
|
61
61
|
def _mkTag(ns: str, tag: str) -> str:
|
62
62
|
"""Assemble namespace and tag name."""
|
63
|
-
uri
|
64
|
-
if uri:
|
63
|
+
if uri := XML_NS.get(ns, ""):
|
65
64
|
return f"{{{uri}}}{tag}"
|
66
65
|
logger.warning("Missing xml namespace '%s'", ns)
|
67
66
|
return tag
|
@@ -84,14 +83,16 @@ X_BLD = 0x01 # Bold format
|
|
84
83
|
X_ITA = 0x02 # Italic format
|
85
84
|
X_DEL = 0x04 # Strikethrough format
|
86
85
|
X_UND = 0x08 # Underline format
|
87
|
-
|
88
|
-
|
86
|
+
X_MRK = 0x10 # Marked format
|
87
|
+
X_SUP = 0x20 # Superscript
|
88
|
+
X_SUB = 0x40 # Subscript
|
89
89
|
|
90
90
|
# Formatting Masks
|
91
91
|
M_BLD = ~X_BLD
|
92
92
|
M_ITA = ~X_ITA
|
93
93
|
M_DEL = ~X_DEL
|
94
94
|
M_UND = ~X_UND
|
95
|
+
M_MRK = ~X_MRK
|
95
96
|
M_SUP = ~X_SUP
|
96
97
|
M_SUB = ~X_SUB
|
97
98
|
|
@@ -125,9 +126,9 @@ class ToOdt(Tokenizer):
|
|
125
126
|
self._xBody = ET.Element("") # Office body root
|
126
127
|
self._xText = ET.Element("") # Office text root
|
127
128
|
|
128
|
-
self._mainPara = {} # User-accessible paragraph styles
|
129
|
-
self._autoPara = {} # Auto-generated paragraph styles
|
130
|
-
self._autoText = {}
|
129
|
+
self._mainPara: dict[str, ODTParagraphStyle] = {} # User-accessible paragraph styles
|
130
|
+
self._autoPara: dict[str, ODTParagraphStyle] = {} # Auto-generated paragraph styles
|
131
|
+
self._autoText: dict[int, ODTTextStyle] = {} # Auto-generated text styles
|
131
132
|
|
132
133
|
self._errData = [] # List of errors encountered
|
133
134
|
|
@@ -136,6 +137,7 @@ class ToOdt(Tokenizer):
|
|
136
137
|
self._textSize = 12
|
137
138
|
self._textFixed = False
|
138
139
|
self._colourHead = False
|
140
|
+
self._firstIndent = False
|
139
141
|
self._headerFormat = ""
|
140
142
|
self._pageOffset = 0
|
141
143
|
|
@@ -151,6 +153,7 @@ class ToOdt(Tokenizer):
|
|
151
153
|
self._fSizeText = "12pt"
|
152
154
|
self._fLineHeight = "115%"
|
153
155
|
self._fBlockIndent = "1.693cm"
|
156
|
+
self._fTextIndent = "0.499cm"
|
154
157
|
self._textAlign = "left"
|
155
158
|
self._dLanguage = "en"
|
156
159
|
self._dCountry = "GB"
|
@@ -189,6 +192,7 @@ class ToOdt(Tokenizer):
|
|
189
192
|
self._opaHead34 = None
|
190
193
|
self._colMetaTx = None
|
191
194
|
self._opaMetaTx = None
|
195
|
+
self._markText = "#ffffa6"
|
192
196
|
|
193
197
|
return
|
194
198
|
|
@@ -199,10 +203,9 @@ class ToOdt(Tokenizer):
|
|
199
203
|
def setLanguage(self, language: str | None) -> None:
|
200
204
|
"""Set language for the document."""
|
201
205
|
if language:
|
202
|
-
|
203
|
-
self._dLanguage =
|
204
|
-
|
205
|
-
self._dCountry = langBits[1]
|
206
|
+
lang, _, country = language.partition("_")
|
207
|
+
self._dLanguage = lang or self._dLanguage
|
208
|
+
self._dCountry = country or self._dCountry
|
206
209
|
return
|
207
210
|
|
208
211
|
def setColourHeaders(self, state: bool) -> None:
|
@@ -229,6 +232,11 @@ class ToOdt(Tokenizer):
|
|
229
232
|
self._pageOffset = offset
|
230
233
|
return
|
231
234
|
|
235
|
+
def setFirstLineIndent(self, state: bool) -> None:
|
236
|
+
"""Enable or disable first line indent."""
|
237
|
+
self._firstIndent = state
|
238
|
+
return
|
239
|
+
|
232
240
|
##
|
233
241
|
# Class Methods
|
234
242
|
##
|
@@ -394,10 +402,11 @@ class ToOdt(Tokenizer):
|
|
394
402
|
pFmt = []
|
395
403
|
pText = []
|
396
404
|
pStyle = None
|
405
|
+
pIndent = True
|
397
406
|
for tType, _, tText, tFormat, tStyle in self._tokens:
|
398
407
|
|
399
408
|
# Styles
|
400
|
-
oStyle = ODTParagraphStyle()
|
409
|
+
oStyle = ODTParagraphStyle("New")
|
401
410
|
if tStyle is not None:
|
402
411
|
if tStyle & self.A_LEFT:
|
403
412
|
oStyle.setTextAlign("left")
|
@@ -424,6 +433,9 @@ class ToOdt(Tokenizer):
|
|
424
433
|
if tStyle & self.A_IND_R:
|
425
434
|
oStyle.setMarginRight(self._fBlockIndent)
|
426
435
|
|
436
|
+
if tType not in (self.T_EMPTY, self.T_TEXT):
|
437
|
+
pIndent = False
|
438
|
+
|
427
439
|
# Process Text Types
|
428
440
|
if tType == self.T_EMPTY:
|
429
441
|
if len(pText) > 1 and pStyle is not None:
|
@@ -437,7 +449,14 @@ class ToOdt(Tokenizer):
|
|
437
449
|
tLen = len(tTxt)
|
438
450
|
tTxt += f"{nText}\n"
|
439
451
|
tFmt.extend((p+tLen, fmt) for p, fmt in nFmt)
|
440
|
-
|
452
|
+
|
453
|
+
# Don't indent a paragraph if it has alignment set
|
454
|
+
tIndent = self._firstIndent and pIndent and pStyle.isUnaligned()
|
455
|
+
self._addTextPar(
|
456
|
+
"First_20_line_20_indent" if tIndent else "Text_20_body",
|
457
|
+
pStyle, tTxt.rstrip(), tFmt=tFmt
|
458
|
+
)
|
459
|
+
pIndent = True
|
441
460
|
|
442
461
|
pFmt = []
|
443
462
|
pText = []
|
@@ -447,10 +466,6 @@ class ToOdt(Tokenizer):
|
|
447
466
|
tHead = tText.replace(nwHeadFmt.BR, "\n")
|
448
467
|
self._addTextPar("Title", oStyle, tHead, isHead=False) # Title must be text:p
|
449
468
|
|
450
|
-
elif tType == self.T_UNNUM:
|
451
|
-
tHead = tText.replace(nwHeadFmt.BR, "\n")
|
452
|
-
self._addTextPar("Heading_20_2", oStyle, tHead, isHead=True, oLevel="2")
|
453
|
-
|
454
469
|
elif tType == self.T_HEAD1:
|
455
470
|
tHead = tText.replace(nwHeadFmt.BR, "\n")
|
456
471
|
self._addTextPar("Heading_20_1", oStyle, tHead, isHead=True, oLevel="1")
|
@@ -498,12 +513,11 @@ class ToOdt(Tokenizer):
|
|
498
513
|
return
|
499
514
|
|
500
515
|
def closeDocument(self) -> None:
|
501
|
-
"""Pack the styles of the XML document."""
|
502
|
-
|
503
|
-
|
504
|
-
|
505
|
-
|
506
|
-
styleObj.packXML(self._xAuto, styleName)
|
516
|
+
"""Pack the automatic styles of the XML document."""
|
517
|
+
for style in self._autoPara.values():
|
518
|
+
style.packXML(self._xAuto)
|
519
|
+
for style in self._autoText.values():
|
520
|
+
style.packXML(self._xAuto)
|
507
521
|
return
|
508
522
|
|
509
523
|
def saveFlatXML(self, path: str | Path) -> None:
|
@@ -534,7 +548,7 @@ class ToOdt(Tokenizer):
|
|
534
548
|
oVers = _mkTag("office", "version")
|
535
549
|
xSett = ET.Element(oRoot, attrib={oVers: X_VERS})
|
536
550
|
|
537
|
-
def putInZip(name, xObj, zipObj):
|
551
|
+
def putInZip(name: str, xObj: ET.Element, zipObj: ZipFile) -> None:
|
538
552
|
with zipObj.open(name, mode="w") as fObj:
|
539
553
|
xml = ET.ElementTree(xObj)
|
540
554
|
xml.write(fObj, encoding="utf-8", xml_declaration=True)
|
@@ -557,10 +571,7 @@ class ToOdt(Tokenizer):
|
|
557
571
|
|
558
572
|
def _formatSynopsis(self, text: str, synopsis: bool) -> tuple[str, list[tuple[int, int]]]:
|
559
573
|
"""Apply formatting to synopsis lines."""
|
560
|
-
if synopsis
|
561
|
-
name = self._localLookup("Synopsis")
|
562
|
-
else:
|
563
|
-
name = self._localLookup("Short Description")
|
574
|
+
name = self._localLookup("Synopsis" if synopsis else "Short Description")
|
564
575
|
rTxt = f"{name}: {text}"
|
565
576
|
rFmt = [(0, self.FMT_B_B), (len(name) + 1, self.FMT_B_E)]
|
566
577
|
return rTxt, rFmt
|
@@ -593,8 +604,7 @@ class ToOdt(Tokenizer):
|
|
593
604
|
tFmt: Sequence[tuple[int, int]] = [], isHead: bool = False, oLevel: str | None = None
|
594
605
|
) -> None:
|
595
606
|
"""Add a text paragraph to the text XML element."""
|
596
|
-
tAttr = {}
|
597
|
-
tAttr[_mkTag("text", "style-name")] = self._paraStyle(styleName, oStyle)
|
607
|
+
tAttr = {_mkTag("text", "style-name"): self._paraStyle(styleName, oStyle)}
|
598
608
|
if oLevel is not None:
|
599
609
|
tAttr[_mkTag("text", "outline-level")] = oLevel
|
600
610
|
|
@@ -643,6 +653,10 @@ class ToOdt(Tokenizer):
|
|
643
653
|
xFmt |= X_UND
|
644
654
|
elif fFmt == self.FMT_U_E:
|
645
655
|
xFmt &= M_UND
|
656
|
+
elif fFmt == self.FMT_M_B:
|
657
|
+
xFmt |= X_MRK
|
658
|
+
elif fFmt == self.FMT_M_E:
|
659
|
+
xFmt &= M_MRK
|
646
660
|
elif fFmt == self.FMT_SUP_B:
|
647
661
|
xFmt |= X_SUP
|
648
662
|
elif fFmt == self.FMT_SUP_E:
|
@@ -672,52 +686,54 @@ class ToOdt(Tokenizer):
|
|
672
686
|
|
673
687
|
return
|
674
688
|
|
675
|
-
def _paraStyle(self,
|
689
|
+
def _paraStyle(self, mainName: str, modStyle: ODTParagraphStyle) -> str:
|
676
690
|
"""Return a name for a style object."""
|
677
|
-
refStyle
|
678
|
-
|
679
|
-
logger.error("Unknown paragraph style '%s'", parName)
|
691
|
+
if not (refStyle := self._mainPara.get(mainName)):
|
692
|
+
logger.error("Unknown main paragraph style '%s'", mainName)
|
680
693
|
return "Standard"
|
681
694
|
|
682
|
-
if not refStyle.checkNew(
|
683
|
-
return
|
695
|
+
if not refStyle.checkNew(modStyle):
|
696
|
+
# The style is unmodified, so we return the main style
|
697
|
+
return mainName
|
684
698
|
|
685
|
-
|
686
|
-
|
687
|
-
|
688
|
-
|
699
|
+
# The style is modified, so we check if there already is an
|
700
|
+
# identical style with the same parent we can use instead
|
701
|
+
modStyle.setParentStyleName(mainName)
|
702
|
+
if (pID := modStyle.getID()) in self._autoPara:
|
703
|
+
return self._autoPara[pID].name
|
689
704
|
|
690
|
-
|
691
|
-
self._autoPara
|
705
|
+
# If neither of the above hold, we store it as a new style
|
706
|
+
modStyle.setName(f"P{len(self._autoPara)+1:d}")
|
707
|
+
self._autoPara[pID] = modStyle
|
692
708
|
|
693
|
-
return
|
709
|
+
return modStyle.name
|
694
710
|
|
695
711
|
def _textStyle(self, hFmt: int) -> str:
|
696
712
|
"""Return a text style for a given style code."""
|
697
713
|
if hFmt in self._autoText:
|
698
|
-
return self._autoText[hFmt]
|
714
|
+
return self._autoText[hFmt].name
|
699
715
|
|
700
|
-
|
701
|
-
newStyle = ODTTextStyle()
|
716
|
+
style = ODTTextStyle(f"T{len(self._autoText)+1:d}")
|
702
717
|
if hFmt & X_BLD:
|
703
|
-
|
718
|
+
style.setFontWeight("bold")
|
704
719
|
if hFmt & X_ITA:
|
705
|
-
|
720
|
+
style.setFontStyle("italic")
|
706
721
|
if hFmt & X_DEL:
|
707
|
-
|
708
|
-
|
722
|
+
style.setStrikeStyle("solid")
|
723
|
+
style.setStrikeType("single")
|
709
724
|
if hFmt & X_UND:
|
710
|
-
|
711
|
-
|
712
|
-
|
725
|
+
style.setUnderlineStyle("solid")
|
726
|
+
style.setUnderlineWidth("auto")
|
727
|
+
style.setUnderlineColour("font-color")
|
728
|
+
if hFmt & X_MRK:
|
729
|
+
style.setBackgroundColour(self._markText)
|
713
730
|
if hFmt & X_SUP:
|
714
|
-
|
731
|
+
style.setTextPosition("super")
|
715
732
|
if hFmt & X_SUB:
|
716
|
-
|
733
|
+
style.setTextPosition("sub")
|
734
|
+
self._autoText[hFmt] = style
|
717
735
|
|
718
|
-
|
719
|
-
|
720
|
-
return newName
|
736
|
+
return style.name
|
721
737
|
|
722
738
|
def _emToCm(self, value: float) -> str:
|
723
739
|
"""Converts an em value to centimetres."""
|
@@ -729,286 +745,254 @@ class ToOdt(Tokenizer):
|
|
729
745
|
|
730
746
|
def _pageStyles(self) -> None:
|
731
747
|
"""Set the default page style."""
|
732
|
-
|
733
|
-
|
734
|
-
|
735
|
-
|
736
|
-
|
737
|
-
|
738
|
-
|
739
|
-
|
740
|
-
|
741
|
-
|
742
|
-
|
743
|
-
|
744
|
-
|
745
|
-
|
746
|
-
tAttr[_mkTag("fo", "print-orientation")] = "portrait"
|
747
|
-
ET.SubElement(xPage, _mkTag("style", "page-layout-properties"), attrib=tAttr)
|
748
|
+
xPage = ET.SubElement(
|
749
|
+
self._xAuto if self._isFlat else self._xAut2,
|
750
|
+
_mkTag("style", "page-layout"),
|
751
|
+
attrib={_mkTag("style", "name"): "PM1"}
|
752
|
+
)
|
753
|
+
ET.SubElement(xPage, _mkTag("style", "page-layout-properties"), attrib={
|
754
|
+
_mkTag("fo", "page-width"): self._mDocWidth,
|
755
|
+
_mkTag("fo", "page-height"): self._mDocHeight,
|
756
|
+
_mkTag("fo", "margin-top"): self._mDocTop,
|
757
|
+
_mkTag("fo", "margin-bottom"): self._mDocBtm,
|
758
|
+
_mkTag("fo", "margin-left"): self._mDocLeft,
|
759
|
+
_mkTag("fo", "margin-right"): self._mDocRight,
|
760
|
+
_mkTag("fo", "print-orientation"): "portrait",
|
761
|
+
})
|
748
762
|
|
749
763
|
xHead = ET.SubElement(xPage, _mkTag("style", "header-style"))
|
750
|
-
|
751
|
-
|
752
|
-
|
753
|
-
|
754
|
-
|
755
|
-
|
756
|
-
ET.SubElement(xHead, _mkTag("style", "header-footer-properties"), attrib=tAttr)
|
764
|
+
ET.SubElement(xHead, _mkTag("style", "header-footer-properties"), attrib={
|
765
|
+
_mkTag("fo", "min-height"): "0.600cm",
|
766
|
+
_mkTag("fo", "margin-left"): "0.000cm",
|
767
|
+
_mkTag("fo", "margin-right"): "0.000cm",
|
768
|
+
_mkTag("fo", "margin-bottom"): "0.500cm",
|
769
|
+
})
|
757
770
|
|
758
771
|
return
|
759
772
|
|
760
773
|
def _defaultStyles(self) -> None:
|
761
774
|
"""Set the default styles."""
|
762
775
|
# Add Paragraph Family Style
|
763
|
-
|
764
|
-
|
765
|
-
|
766
|
-
|
767
|
-
|
768
|
-
|
769
|
-
|
770
|
-
|
771
|
-
|
772
|
-
|
773
|
-
|
774
|
-
|
775
|
-
|
776
|
-
|
777
|
-
|
778
|
-
tAttr[_mkTag("fo", "font-size")] = self._fSizeText
|
779
|
-
tAttr[_mkTag("fo", "language")] = self._dLanguage
|
780
|
-
tAttr[_mkTag("fo", "country")] = self._dCountry
|
781
|
-
ET.SubElement(xStyl, _mkTag("style", "text-properties"), attrib=tAttr)
|
776
|
+
xStyl = ET.SubElement(self._xStyl, _mkTag("style", "default-style"), attrib={
|
777
|
+
_mkTag("style", "family"): "paragraph",
|
778
|
+
})
|
779
|
+
ET.SubElement(xStyl, _mkTag("style", "paragraph-properties"), attrib={
|
780
|
+
_mkTag("style", "line-break"): "strict",
|
781
|
+
_mkTag("style", "tab-stop-distance"): "1.251cm",
|
782
|
+
_mkTag("style", "writing-mode"): "page",
|
783
|
+
})
|
784
|
+
ET.SubElement(xStyl, _mkTag("style", "text-properties"), attrib={
|
785
|
+
_mkTag("style", "font-name"): self._textFont,
|
786
|
+
_mkTag("fo", "font-family"): self._fontFamily,
|
787
|
+
_mkTag("fo", "font-size"): self._fSizeText,
|
788
|
+
_mkTag("fo", "language"): self._dLanguage,
|
789
|
+
_mkTag("fo", "country"): self._dCountry,
|
790
|
+
})
|
782
791
|
|
783
792
|
# Add Standard Paragraph Style
|
784
|
-
|
785
|
-
|
786
|
-
|
787
|
-
|
788
|
-
|
789
|
-
|
790
|
-
|
791
|
-
|
792
|
-
|
793
|
-
|
794
|
-
tAttr[_mkTag("fo", "font-family")] = self._fontFamily
|
795
|
-
tAttr[_mkTag("fo", "font-size")] = self._fSizeText
|
796
|
-
ET.SubElement(xStyl, _mkTag("style", "text-properties"), attrib=tAttr)
|
793
|
+
xStyl = ET.SubElement(self._xStyl, _mkTag("style", "style"), attrib={
|
794
|
+
_mkTag("style", "name"): "Standard",
|
795
|
+
_mkTag("style", "family"): "paragraph",
|
796
|
+
_mkTag("style", "class"): "text",
|
797
|
+
})
|
798
|
+
ET.SubElement(xStyl, _mkTag("style", "text-properties"), attrib={
|
799
|
+
_mkTag("style", "font-name"): self._textFont,
|
800
|
+
_mkTag("fo", "font-family"): self._fontFamily,
|
801
|
+
_mkTag("fo", "font-size"): self._fSizeText,
|
802
|
+
})
|
797
803
|
|
798
804
|
# Add Default Heading Style
|
799
|
-
|
800
|
-
|
801
|
-
|
802
|
-
|
803
|
-
|
804
|
-
|
805
|
-
|
806
|
-
|
807
|
-
|
808
|
-
|
809
|
-
|
810
|
-
|
811
|
-
|
812
|
-
|
813
|
-
|
814
|
-
|
815
|
-
|
816
|
-
tAttr[_mkTag("style", "font-name")] = self._textFont
|
817
|
-
tAttr[_mkTag("fo", "font-family")] = self._fontFamily
|
818
|
-
tAttr[_mkTag("fo", "font-size")] = self._fSizeHead
|
819
|
-
ET.SubElement(xStyl, _mkTag("style", "text-properties"), attrib=tAttr)
|
805
|
+
xStyl = ET.SubElement(self._xStyl, _mkTag("style", "style"), attrib={
|
806
|
+
_mkTag("style", "name"): "Heading",
|
807
|
+
_mkTag("style", "family"): "paragraph",
|
808
|
+
_mkTag("style", "parent-style-name"): "Standard",
|
809
|
+
_mkTag("style", "next-style-name"): "Text_20_body",
|
810
|
+
_mkTag("style", "class"): "text",
|
811
|
+
})
|
812
|
+
ET.SubElement(xStyl, _mkTag("style", "paragraph-properties"), attrib={
|
813
|
+
_mkTag("fo", "margin-top"): self._mTopHead,
|
814
|
+
_mkTag("fo", "margin-bottom"): self._mBotHead,
|
815
|
+
_mkTag("fo", "keep-with-next"): "always",
|
816
|
+
})
|
817
|
+
ET.SubElement(xStyl, _mkTag("style", "text-properties"), attrib={
|
818
|
+
_mkTag("style", "font-name"): self._textFont,
|
819
|
+
_mkTag("fo", "font-family"): self._fontFamily,
|
820
|
+
_mkTag("fo", "font-size"): self._fSizeHead,
|
821
|
+
})
|
820
822
|
|
821
823
|
# Add Header and Footer Styles
|
822
|
-
|
823
|
-
|
824
|
-
|
825
|
-
|
826
|
-
|
827
|
-
|
828
|
-
|
829
|
-
ET.SubElement(self._xStyl, _mkTag("style", "style"), attrib=tAttr)
|
824
|
+
ET.SubElement(self._xStyl, _mkTag("style", "style"), attrib={
|
825
|
+
_mkTag("style", "name"): "Header_20_and_20_Footer",
|
826
|
+
_mkTag("style", "display-name"): "Header and Footer",
|
827
|
+
_mkTag("style", "family"): "paragraph",
|
828
|
+
_mkTag("style", "parent-style-name"): "Standard",
|
829
|
+
_mkTag("style", "class"): "extra",
|
830
|
+
})
|
830
831
|
|
831
832
|
return
|
832
833
|
|
833
834
|
def _useableStyles(self) -> None:
|
834
835
|
"""Set the usable styles."""
|
835
836
|
# Add Text Body Style
|
836
|
-
|
837
|
-
|
838
|
-
|
839
|
-
|
840
|
-
|
841
|
-
|
842
|
-
|
843
|
-
|
844
|
-
|
845
|
-
|
846
|
-
|
847
|
-
|
848
|
-
|
849
|
-
|
850
|
-
|
851
|
-
|
837
|
+
style = ODTParagraphStyle("Text_20_body")
|
838
|
+
style.setDisplayName("Text body")
|
839
|
+
style.setParentStyleName("Standard")
|
840
|
+
style.setClass("text")
|
841
|
+
style.setMarginTop(self._mTopText)
|
842
|
+
style.setMarginBottom(self._mBotText)
|
843
|
+
style.setLineHeight(self._fLineHeight)
|
844
|
+
style.setTextAlign(self._textAlign)
|
845
|
+
style.setFontName(self._textFont)
|
846
|
+
style.setFontFamily(self._fontFamily)
|
847
|
+
style.setFontSize(self._fSizeText)
|
848
|
+
style.packXML(self._xStyl)
|
849
|
+
self._mainPara[style.name] = style
|
850
|
+
|
851
|
+
# Add First Line Indent Style
|
852
|
+
style = ODTParagraphStyle("First_20_line_20_indent")
|
853
|
+
style.setDisplayName("First line indent")
|
854
|
+
style.setParentStyleName("Text_20_body")
|
855
|
+
style.setClass("text")
|
856
|
+
style.setTextIndent(self._fTextIndent)
|
857
|
+
style.packXML(self._xStyl)
|
858
|
+
self._mainPara[style.name] = style
|
852
859
|
|
853
860
|
# Add Text Meta Style
|
854
|
-
|
855
|
-
|
856
|
-
|
857
|
-
|
858
|
-
|
859
|
-
|
860
|
-
|
861
|
-
|
862
|
-
|
863
|
-
|
864
|
-
|
865
|
-
|
866
|
-
|
867
|
-
|
868
|
-
oStyle.packXML(self._xStyl, "Text_20_Meta")
|
869
|
-
|
870
|
-
self._mainPara["Text_20_Meta"] = oStyle
|
861
|
+
style = ODTParagraphStyle("Text_20_Meta")
|
862
|
+
style.setDisplayName("Text Meta")
|
863
|
+
style.setParentStyleName("Standard")
|
864
|
+
style.setClass("text")
|
865
|
+
style.setMarginTop(self._mTopMeta)
|
866
|
+
style.setMarginBottom(self._mBotMeta)
|
867
|
+
style.setLineHeight(self._fLineHeight)
|
868
|
+
style.setFontName(self._textFont)
|
869
|
+
style.setFontFamily(self._fontFamily)
|
870
|
+
style.setFontSize(self._fSizeText)
|
871
|
+
style.setColour(self._colMetaTx)
|
872
|
+
style.setOpacity(self._opaMetaTx)
|
873
|
+
style.packXML(self._xStyl)
|
874
|
+
self._mainPara[style.name] = style
|
871
875
|
|
872
876
|
# Add Title Style
|
873
|
-
|
874
|
-
|
875
|
-
|
876
|
-
|
877
|
-
|
878
|
-
|
879
|
-
|
880
|
-
|
881
|
-
|
882
|
-
|
883
|
-
|
884
|
-
|
885
|
-
|
886
|
-
|
887
|
-
oStyle.packXML(self._xStyl, "Title")
|
888
|
-
|
889
|
-
self._mainPara["Title"] = oStyle
|
877
|
+
style = ODTParagraphStyle("Title")
|
878
|
+
style.setDisplayName("Title")
|
879
|
+
style.setParentStyleName("Heading")
|
880
|
+
style.setNextStyleName("Text_20_body")
|
881
|
+
style.setClass("chapter")
|
882
|
+
style.setMarginTop(self._mTopTitle)
|
883
|
+
style.setMarginBottom(self._mBotTitle)
|
884
|
+
style.setTextAlign("center")
|
885
|
+
style.setFontName(self._textFont)
|
886
|
+
style.setFontFamily(self._fontFamily)
|
887
|
+
style.setFontSize(self._fSizeTitle)
|
888
|
+
style.setFontWeight("bold")
|
889
|
+
style.packXML(self._xStyl)
|
890
|
+
self._mainPara[style.name] = style
|
890
891
|
|
891
892
|
# Add Separator Style
|
892
|
-
|
893
|
-
|
894
|
-
|
895
|
-
|
896
|
-
|
897
|
-
|
898
|
-
|
899
|
-
|
900
|
-
|
901
|
-
|
902
|
-
|
903
|
-
|
904
|
-
|
905
|
-
|
906
|
-
oStyle.packXML(self._xStyl, "Separator")
|
907
|
-
|
908
|
-
self._mainPara["Separator"] = oStyle
|
893
|
+
style = ODTParagraphStyle("Separator")
|
894
|
+
style.setDisplayName("Separator")
|
895
|
+
style.setParentStyleName("Standard")
|
896
|
+
style.setNextStyleName("Text_20_body")
|
897
|
+
style.setClass("text")
|
898
|
+
style.setMarginTop(self._mTopText)
|
899
|
+
style.setMarginBottom(self._mBotText)
|
900
|
+
style.setLineHeight(self._fLineHeight)
|
901
|
+
style.setTextAlign("center")
|
902
|
+
style.setFontName(self._textFont)
|
903
|
+
style.setFontFamily(self._fontFamily)
|
904
|
+
style.setFontSize(self._fSizeText)
|
905
|
+
style.packXML(self._xStyl)
|
906
|
+
self._mainPara[style.name] = style
|
909
907
|
|
910
908
|
# Add Heading 1 Style
|
911
|
-
|
912
|
-
|
913
|
-
|
914
|
-
|
915
|
-
|
916
|
-
|
917
|
-
|
918
|
-
|
919
|
-
|
920
|
-
|
921
|
-
|
922
|
-
|
923
|
-
|
924
|
-
|
925
|
-
|
926
|
-
|
927
|
-
oStyle.packXML(self._xStyl, "Heading_20_1")
|
928
|
-
|
929
|
-
self._mainPara["Heading_20_1"] = oStyle
|
909
|
+
style = ODTParagraphStyle("Heading_20_1")
|
910
|
+
style.setDisplayName("Heading 1")
|
911
|
+
style.setParentStyleName("Heading")
|
912
|
+
style.setNextStyleName("Text_20_body")
|
913
|
+
style.setOutlineLevel("1")
|
914
|
+
style.setClass("text")
|
915
|
+
style.setMarginTop(self._mTopHead1)
|
916
|
+
style.setMarginBottom(self._mBotHead1)
|
917
|
+
style.setFontName(self._textFont)
|
918
|
+
style.setFontFamily(self._fontFamily)
|
919
|
+
style.setFontSize(self._fSizeHead1)
|
920
|
+
style.setFontWeight("bold")
|
921
|
+
style.setColour(self._colHead12)
|
922
|
+
style.setOpacity(self._opaHead12)
|
923
|
+
style.packXML(self._xStyl)
|
924
|
+
self._mainPara[style.name] = style
|
930
925
|
|
931
926
|
# Add Heading 2 Style
|
932
|
-
|
933
|
-
|
934
|
-
|
935
|
-
|
936
|
-
|
937
|
-
|
938
|
-
|
939
|
-
|
940
|
-
|
941
|
-
|
942
|
-
|
943
|
-
|
944
|
-
|
945
|
-
|
946
|
-
|
947
|
-
|
948
|
-
oStyle.packXML(self._xStyl, "Heading_20_2")
|
949
|
-
|
950
|
-
self._mainPara["Heading_20_2"] = oStyle
|
927
|
+
style = ODTParagraphStyle("Heading_20_2")
|
928
|
+
style.setDisplayName("Heading 2")
|
929
|
+
style.setParentStyleName("Heading")
|
930
|
+
style.setNextStyleName("Text_20_body")
|
931
|
+
style.setOutlineLevel("2")
|
932
|
+
style.setClass("text")
|
933
|
+
style.setMarginTop(self._mTopHead2)
|
934
|
+
style.setMarginBottom(self._mBotHead2)
|
935
|
+
style.setFontName(self._textFont)
|
936
|
+
style.setFontFamily(self._fontFamily)
|
937
|
+
style.setFontSize(self._fSizeHead2)
|
938
|
+
style.setFontWeight("bold")
|
939
|
+
style.setColour(self._colHead12)
|
940
|
+
style.setOpacity(self._opaHead12)
|
941
|
+
style.packXML(self._xStyl)
|
942
|
+
self._mainPara[style.name] = style
|
951
943
|
|
952
944
|
# Add Heading 3 Style
|
953
|
-
|
954
|
-
|
955
|
-
|
956
|
-
|
957
|
-
|
958
|
-
|
959
|
-
|
960
|
-
|
961
|
-
|
962
|
-
|
963
|
-
|
964
|
-
|
965
|
-
|
966
|
-
|
967
|
-
|
968
|
-
|
969
|
-
oStyle.packXML(self._xStyl, "Heading_20_3")
|
970
|
-
|
971
|
-
self._mainPara["Heading_20_3"] = oStyle
|
945
|
+
style = ODTParagraphStyle("Heading_20_3")
|
946
|
+
style.setDisplayName("Heading 3")
|
947
|
+
style.setParentStyleName("Heading")
|
948
|
+
style.setNextStyleName("Text_20_body")
|
949
|
+
style.setOutlineLevel("3")
|
950
|
+
style.setClass("text")
|
951
|
+
style.setMarginTop(self._mTopHead3)
|
952
|
+
style.setMarginBottom(self._mBotHead3)
|
953
|
+
style.setFontName(self._textFont)
|
954
|
+
style.setFontFamily(self._fontFamily)
|
955
|
+
style.setFontSize(self._fSizeHead3)
|
956
|
+
style.setFontWeight("bold")
|
957
|
+
style.setColour(self._colHead34)
|
958
|
+
style.setOpacity(self._opaHead34)
|
959
|
+
style.packXML(self._xStyl)
|
960
|
+
self._mainPara[style.name] = style
|
972
961
|
|
973
962
|
# Add Heading 4 Style
|
974
|
-
|
975
|
-
|
976
|
-
|
977
|
-
|
978
|
-
|
979
|
-
|
980
|
-
|
981
|
-
|
982
|
-
|
983
|
-
|
984
|
-
|
985
|
-
|
986
|
-
|
987
|
-
|
988
|
-
|
989
|
-
|
990
|
-
oStyle.packXML(self._xStyl, "Heading_20_4")
|
991
|
-
|
992
|
-
self._mainPara["Heading_20_4"] = oStyle
|
963
|
+
style = ODTParagraphStyle("Heading_20_4")
|
964
|
+
style.setDisplayName("Heading 4")
|
965
|
+
style.setParentStyleName("Heading")
|
966
|
+
style.setNextStyleName("Text_20_body")
|
967
|
+
style.setOutlineLevel("4")
|
968
|
+
style.setClass("text")
|
969
|
+
style.setMarginTop(self._mTopHead4)
|
970
|
+
style.setMarginBottom(self._mBotHead4)
|
971
|
+
style.setFontName(self._textFont)
|
972
|
+
style.setFontFamily(self._fontFamily)
|
973
|
+
style.setFontSize(self._fSizeHead4)
|
974
|
+
style.setFontWeight("bold")
|
975
|
+
style.setColour(self._colHead34)
|
976
|
+
style.setOpacity(self._opaHead34)
|
977
|
+
style.packXML(self._xStyl)
|
978
|
+
self._mainPara[style.name] = style
|
993
979
|
|
994
980
|
# Add Header Style
|
995
|
-
|
996
|
-
|
997
|
-
|
998
|
-
|
999
|
-
|
1000
|
-
|
1001
|
-
|
1002
|
-
self._mainPara["Header"] = oStyle
|
981
|
+
style = ODTParagraphStyle("Header")
|
982
|
+
style.setDisplayName("Header")
|
983
|
+
style.setParentStyleName("Header_20_and_20_Footer")
|
984
|
+
style.setTextAlign("right")
|
985
|
+
style.packXML(self._xStyl)
|
986
|
+
self._mainPara[style.name] = style
|
1003
987
|
|
1004
988
|
return
|
1005
989
|
|
1006
990
|
def _writeHeader(self) -> None:
|
1007
991
|
"""Write the header elements."""
|
1008
|
-
|
1009
|
-
|
1010
|
-
|
1011
|
-
|
992
|
+
xPage = ET.SubElement(self._xMast, _mkTag("style", "master-page"), attrib={
|
993
|
+
_mkTag("style", "name"): "Standard",
|
994
|
+
_mkTag("style", "page-layout-name"): "PM1",
|
995
|
+
})
|
1012
996
|
|
1013
997
|
# Standard Page Header
|
1014
998
|
if self._headerFormat:
|
@@ -1025,10 +1009,10 @@ class ToOdt(Tokenizer):
|
|
1025
1009
|
})
|
1026
1010
|
xPar.text = pre
|
1027
1011
|
if page:
|
1028
|
-
|
1012
|
+
attr = {_mkTag("text", "select-page"): "current"}
|
1029
1013
|
if self._pageOffset > 0:
|
1030
|
-
|
1031
|
-
xTail = ET.SubElement(xPar, _mkTag("text", "page-number"), attrib=
|
1014
|
+
attr = {_mkTag("text", "page-adjust"): str(0 - self._pageOffset)}
|
1015
|
+
xTail = ET.SubElement(xPar, _mkTag("text", "page-number"), attrib=attr)
|
1032
1016
|
xTail.text = "2"
|
1033
1017
|
xTail.tail = post
|
1034
1018
|
else:
|
@@ -1060,7 +1044,9 @@ class ODTParagraphStyle:
|
|
1060
1044
|
VALID_CLASS = ["text", "chapter"]
|
1061
1045
|
VALID_WEIGHT = ["normal", "inherit", "bold"]
|
1062
1046
|
|
1063
|
-
def __init__(self) -> None:
|
1047
|
+
def __init__(self, name: str) -> None:
|
1048
|
+
|
1049
|
+
self._name = name
|
1064
1050
|
|
1065
1051
|
# Attributes
|
1066
1052
|
self._mAttr = {
|
@@ -1077,6 +1063,7 @@ class ODTParagraphStyle:
|
|
1077
1063
|
"margin-bottom": ["fo", None],
|
1078
1064
|
"margin-left": ["fo", None],
|
1079
1065
|
"margin-right": ["fo", None],
|
1066
|
+
"text-indent": ["fo", None],
|
1080
1067
|
"line-height": ["fo", None],
|
1081
1068
|
"text-align": ["fo", None],
|
1082
1069
|
"break-before": ["fo", None],
|
@@ -1095,23 +1082,50 @@ class ODTParagraphStyle:
|
|
1095
1082
|
|
1096
1083
|
return
|
1097
1084
|
|
1085
|
+
@property
|
1086
|
+
def name(self) -> str:
|
1087
|
+
return self._name
|
1088
|
+
|
1089
|
+
##
|
1090
|
+
# Checkers
|
1091
|
+
##
|
1092
|
+
|
1093
|
+
def isUnaligned(self) -> bool:
|
1094
|
+
"""Check if paragraph has any sort of alignment or margins."""
|
1095
|
+
return all(
|
1096
|
+
self._pAttr[n][1] is None for n in ["text-align", "margin-left", "margin-right"]
|
1097
|
+
)
|
1098
|
+
|
1099
|
+
##
|
1100
|
+
# Setters
|
1101
|
+
##
|
1102
|
+
|
1103
|
+
def setName(self, name: str) -> None:
|
1104
|
+
"""Set the paragraph style name."""
|
1105
|
+
self._name = name
|
1106
|
+
return
|
1107
|
+
|
1098
1108
|
##
|
1099
1109
|
# Attribute Setters
|
1100
1110
|
##
|
1101
1111
|
|
1102
1112
|
def setDisplayName(self, value: str | None) -> None:
|
1113
|
+
"""Set style display name."""
|
1103
1114
|
self._mAttr["display-name"][1] = value
|
1104
1115
|
return
|
1105
1116
|
|
1106
1117
|
def setParentStyleName(self, value: str | None) -> None:
|
1118
|
+
"""Set parent style name."""
|
1107
1119
|
self._mAttr["parent-style-name"][1] = value
|
1108
1120
|
return
|
1109
1121
|
|
1110
1122
|
def setNextStyleName(self, value: str | None) -> None:
|
1123
|
+
"""Set next style name."""
|
1111
1124
|
self._mAttr["next-style-name"][1] = value
|
1112
1125
|
return
|
1113
1126
|
|
1114
1127
|
def setOutlineLevel(self, value: str | None) -> None:
|
1128
|
+
"""Set paragraph outline level."""
|
1115
1129
|
if value in self.VALID_LEVEL:
|
1116
1130
|
self._mAttr["default-outline-level"][1] = value
|
1117
1131
|
else:
|
@@ -1119,6 +1133,7 @@ class ODTParagraphStyle:
|
|
1119
1133
|
return
|
1120
1134
|
|
1121
1135
|
def setClass(self, value: str | None) -> None:
|
1136
|
+
"""Set paragraph class."""
|
1122
1137
|
if value in self.VALID_CLASS:
|
1123
1138
|
self._mAttr["class"][1] = value
|
1124
1139
|
else:
|
@@ -1130,26 +1145,37 @@ class ODTParagraphStyle:
|
|
1130
1145
|
##
|
1131
1146
|
|
1132
1147
|
def setMarginTop(self, value: str | None) -> None:
|
1148
|
+
"""Set paragraph top margin."""
|
1133
1149
|
self._pAttr["margin-top"][1] = value
|
1134
1150
|
return
|
1135
1151
|
|
1136
1152
|
def setMarginBottom(self, value: str | None) -> None:
|
1153
|
+
"""Set paragraph bottom margin."""
|
1137
1154
|
self._pAttr["margin-bottom"][1] = value
|
1138
1155
|
return
|
1139
1156
|
|
1140
1157
|
def setMarginLeft(self, value: str | None) -> None:
|
1158
|
+
"""Set paragraph left margin."""
|
1141
1159
|
self._pAttr["margin-left"][1] = value
|
1142
1160
|
return
|
1143
1161
|
|
1144
1162
|
def setMarginRight(self, value: str | None) -> None:
|
1163
|
+
"""Set paragraph right margin."""
|
1145
1164
|
self._pAttr["margin-right"][1] = value
|
1146
1165
|
return
|
1147
1166
|
|
1167
|
+
def setTextIndent(self, value: str | None) -> None:
|
1168
|
+
"""Set text indentation."""
|
1169
|
+
self._pAttr["text-indent"][1] = value
|
1170
|
+
return
|
1171
|
+
|
1148
1172
|
def setLineHeight(self, value: str | None) -> None:
|
1173
|
+
"""Set line height."""
|
1149
1174
|
self._pAttr["line-height"][1] = value
|
1150
1175
|
return
|
1151
1176
|
|
1152
1177
|
def setTextAlign(self, value: str | None) -> None:
|
1178
|
+
"""Set paragraph text alignment."""
|
1153
1179
|
if value in self.VALID_ALIGN:
|
1154
1180
|
self._pAttr["text-align"][1] = value
|
1155
1181
|
else:
|
@@ -1157,6 +1183,7 @@ class ODTParagraphStyle:
|
|
1157
1183
|
return
|
1158
1184
|
|
1159
1185
|
def setBreakBefore(self, value: str | None) -> None:
|
1186
|
+
"""Set page break before policy."""
|
1160
1187
|
if value in self.VALID_BREAK:
|
1161
1188
|
self._pAttr["break-before"][1] = value
|
1162
1189
|
else:
|
@@ -1164,6 +1191,7 @@ class ODTParagraphStyle:
|
|
1164
1191
|
return
|
1165
1192
|
|
1166
1193
|
def setBreakAfter(self, value: str | None) -> None:
|
1194
|
+
"""Set page break after policy."""
|
1167
1195
|
if value in self.VALID_BREAK:
|
1168
1196
|
self._pAttr["break-after"][1] = value
|
1169
1197
|
else:
|
@@ -1175,29 +1203,35 @@ class ODTParagraphStyle:
|
|
1175
1203
|
##
|
1176
1204
|
|
1177
1205
|
def setFontName(self, value: str | None) -> None:
|
1206
|
+
"""Set font name."""
|
1178
1207
|
self._tAttr["font-name"][1] = value
|
1179
1208
|
return
|
1180
1209
|
|
1181
1210
|
def setFontFamily(self, value: str | None) -> None:
|
1211
|
+
"""Set font family."""
|
1182
1212
|
self._tAttr["font-family"][1] = value
|
1183
1213
|
return
|
1184
1214
|
|
1185
1215
|
def setFontSize(self, value: str | None) -> None:
|
1216
|
+
"""Set font size."""
|
1186
1217
|
self._tAttr["font-size"][1] = value
|
1187
1218
|
return
|
1188
1219
|
|
1189
1220
|
def setFontWeight(self, value: str | None) -> None:
|
1221
|
+
"""Set font weight."""
|
1190
1222
|
if value in self.VALID_WEIGHT:
|
1191
1223
|
self._tAttr["font-weight"][1] = value
|
1192
1224
|
else:
|
1193
1225
|
self._tAttr["font-weight"][1] = None
|
1194
1226
|
return
|
1195
1227
|
|
1196
|
-
def
|
1228
|
+
def setColour(self, value: str | None) -> None:
|
1229
|
+
"""Set text colour."""
|
1197
1230
|
self._tAttr["color"][1] = value
|
1198
1231
|
return
|
1199
1232
|
|
1200
1233
|
def setOpacity(self, value: str | None) -> None:
|
1234
|
+
"""Set text opacity."""
|
1201
1235
|
self._tAttr["opacity"][1] = value
|
1202
1236
|
return
|
1203
1237
|
|
@@ -1206,54 +1240,41 @@ class ODTParagraphStyle:
|
|
1206
1240
|
##
|
1207
1241
|
|
1208
1242
|
def checkNew(self, style: ODTParagraphStyle) -> bool:
|
1209
|
-
"""Check if there are new settings in
|
1210
|
-
those in
|
1243
|
+
"""Check if there are new settings in style that differ from
|
1244
|
+
those in this object. Unset styles are ignored as they can be
|
1245
|
+
inherited from the parent style.
|
1211
1246
|
"""
|
1212
|
-
for
|
1213
|
-
|
1214
|
-
|
1215
|
-
|
1216
|
-
|
1217
|
-
|
1218
|
-
for name, (_, aVal) in style._tAttr.items():
|
1219
|
-
if aVal is not None and aVal != self._tAttr[name][1]:
|
1220
|
-
return True
|
1247
|
+
if any(v and v != self._mAttr[m][1] for m, (_, v) in style._mAttr.items()):
|
1248
|
+
return True
|
1249
|
+
if any(v and v != self._pAttr[m][1] for m, (_, v) in style._pAttr.items()):
|
1250
|
+
return True
|
1251
|
+
if any(v and v != self._tAttr[m][1] for m, (_, v) in style._tAttr.items()):
|
1252
|
+
return True
|
1221
1253
|
return False
|
1222
1254
|
|
1223
1255
|
def getID(self) -> str:
|
1224
1256
|
"""Generate a unique ID from the settings."""
|
1225
|
-
|
1257
|
+
return sha256((
|
1226
1258
|
f"Paragraph:Main:{str(self._mAttr)}:"
|
1227
1259
|
f"Paragraph:Para:{str(self._pAttr)}:"
|
1228
1260
|
f"Paragraph:Text:{str(self._tAttr)}:"
|
1229
|
-
)
|
1230
|
-
return sha256(string.encode()).hexdigest()
|
1261
|
+
).encode()).hexdigest()
|
1231
1262
|
|
1232
|
-
def packXML(self, xParent: ET.Element
|
1263
|
+
def packXML(self, xParent: ET.Element) -> None:
|
1233
1264
|
"""Pack the content into an xml element."""
|
1234
|
-
attr = {
|
1235
|
-
|
1236
|
-
|
1237
|
-
|
1238
|
-
|
1239
|
-
|
1240
|
-
|
1265
|
+
attr = {
|
1266
|
+
_mkTag("style", "name"): self._name,
|
1267
|
+
_mkTag("style", "family"): "paragraph",
|
1268
|
+
}
|
1269
|
+
attr.update(
|
1270
|
+
{_mkTag(n, m): v for m, (n, v) in self._mAttr.items() if v}
|
1271
|
+
)
|
1241
1272
|
xEntry = ET.SubElement(xParent, _mkTag("style", "style"), attrib=attr)
|
1242
1273
|
|
1243
|
-
attr
|
1244
|
-
for aName, (aNm, aVal) in self._pAttr.items():
|
1245
|
-
if aVal is not None:
|
1246
|
-
attr[_mkTag(aNm, aName)] = aVal
|
1247
|
-
|
1248
|
-
if attr:
|
1274
|
+
if attr := {_mkTag(n, m): v for m, (n, v) in self._pAttr.items() if v}:
|
1249
1275
|
ET.SubElement(xEntry, _mkTag("style", "paragraph-properties"), attrib=attr)
|
1250
1276
|
|
1251
|
-
attr
|
1252
|
-
for aName, (aNm, aVal) in self._tAttr.items():
|
1253
|
-
if aVal is not None:
|
1254
|
-
attr[_mkTag(aNm, aName)] = aVal
|
1255
|
-
|
1256
|
-
if attr:
|
1277
|
+
if attr := {_mkTag(n, m): v for m, (n, v) in self._tAttr.items() if v}:
|
1257
1278
|
ET.SubElement(xEntry, _mkTag("style", "text-properties"), attrib=attr)
|
1258
1279
|
|
1259
1280
|
return
|
@@ -1274,11 +1295,12 @@ class ODTTextStyle:
|
|
1274
1295
|
VALID_LWIDTH = ["auto"]
|
1275
1296
|
VALID_LCOL = ["font-color"]
|
1276
1297
|
|
1277
|
-
def __init__(self) -> None:
|
1278
|
-
|
1298
|
+
def __init__(self, name: str) -> None:
|
1299
|
+
self._name = name
|
1279
1300
|
self._tAttr = {
|
1280
1301
|
"font-weight": ["fo", None],
|
1281
1302
|
"font-style": ["fo", None],
|
1303
|
+
"background-color": ["fo", None],
|
1282
1304
|
"text-position": ["style", None],
|
1283
1305
|
"text-line-through-style": ["style", None],
|
1284
1306
|
"text-line-through-type": ["style", None],
|
@@ -1288,11 +1310,16 @@ class ODTTextStyle:
|
|
1288
1310
|
}
|
1289
1311
|
return
|
1290
1312
|
|
1313
|
+
@property
|
1314
|
+
def name(self) -> str:
|
1315
|
+
return self._name
|
1316
|
+
|
1291
1317
|
##
|
1292
1318
|
# Setters
|
1293
1319
|
##
|
1294
1320
|
|
1295
1321
|
def setFontWeight(self, value: str | None) -> None:
|
1322
|
+
"""Set text font weight."""
|
1296
1323
|
if value in self.VALID_WEIGHT:
|
1297
1324
|
self._tAttr["font-weight"][1] = value
|
1298
1325
|
else:
|
@@ -1300,13 +1327,23 @@ class ODTTextStyle:
|
|
1300
1327
|
return
|
1301
1328
|
|
1302
1329
|
def setFontStyle(self, value: str | None) -> None:
|
1330
|
+
"""Set text font style."""
|
1303
1331
|
if value in self.VALID_STYLE:
|
1304
1332
|
self._tAttr["font-style"][1] = value
|
1305
1333
|
else:
|
1306
1334
|
self._tAttr["font-style"][1] = None
|
1307
1335
|
return
|
1308
1336
|
|
1337
|
+
def setBackgroundColour(self, value: str | None) -> None:
|
1338
|
+
"""Set text background colour."""
|
1339
|
+
if value and len(value) == 7 and value[0] == "#":
|
1340
|
+
self._tAttr["background-color"][1] = value
|
1341
|
+
else:
|
1342
|
+
self._tAttr["background-color"][1] = None
|
1343
|
+
return
|
1344
|
+
|
1309
1345
|
def setTextPosition(self, value: str | None) -> None:
|
1346
|
+
"""Set text vertical position."""
|
1310
1347
|
if value in self.VALID_POS:
|
1311
1348
|
self._tAttr["text-position"][1] = f"{value} 58%"
|
1312
1349
|
else:
|
@@ -1314,6 +1351,7 @@ class ODTTextStyle:
|
|
1314
1351
|
return
|
1315
1352
|
|
1316
1353
|
def setStrikeStyle(self, value: str | None) -> None:
|
1354
|
+
"""Set text line-trough style."""
|
1317
1355
|
if value in self.VALID_LSTYLE:
|
1318
1356
|
self._tAttr["text-line-through-style"][1] = value
|
1319
1357
|
else:
|
@@ -1321,6 +1359,7 @@ class ODTTextStyle:
|
|
1321
1359
|
return
|
1322
1360
|
|
1323
1361
|
def setStrikeType(self, value: str | None) -> None:
|
1362
|
+
"""Set text line-through type."""
|
1324
1363
|
if value in self.VALID_LTYPE:
|
1325
1364
|
self._tAttr["text-line-through-type"][1] = value
|
1326
1365
|
else:
|
@@ -1328,6 +1367,7 @@ class ODTTextStyle:
|
|
1328
1367
|
return
|
1329
1368
|
|
1330
1369
|
def setUnderlineStyle(self, value: str | None) -> None:
|
1370
|
+
"""Set text underline style."""
|
1331
1371
|
if value in self.VALID_LSTYLE:
|
1332
1372
|
self._tAttr["text-underline-style"][1] = value
|
1333
1373
|
else:
|
@@ -1335,6 +1375,7 @@ class ODTTextStyle:
|
|
1335
1375
|
return
|
1336
1376
|
|
1337
1377
|
def setUnderlineWidth(self, value: str | None) -> None:
|
1378
|
+
"""Set text underline width."""
|
1338
1379
|
if value in self.VALID_LWIDTH:
|
1339
1380
|
self._tAttr["text-underline-width"][1] = value
|
1340
1381
|
else:
|
@@ -1342,6 +1383,7 @@ class ODTTextStyle:
|
|
1342
1383
|
return
|
1343
1384
|
|
1344
1385
|
def setUnderlineColour(self, value: str | None) -> None:
|
1386
|
+
"""Set text underline colour."""
|
1345
1387
|
if value in self.VALID_LCOL:
|
1346
1388
|
self._tAttr["text-underline-color"][1] = value
|
1347
1389
|
else:
|
@@ -1352,21 +1394,14 @@ class ODTTextStyle:
|
|
1352
1394
|
# Methods
|
1353
1395
|
##
|
1354
1396
|
|
1355
|
-
def packXML(self, xParent: ET.Element
|
1397
|
+
def packXML(self, xParent: ET.Element) -> None:
|
1356
1398
|
"""Pack the content into an xml element."""
|
1357
|
-
|
1358
|
-
|
1359
|
-
|
1360
|
-
|
1361
|
-
|
1362
|
-
attr = {}
|
1363
|
-
for aName, (aNm, aVal) in self._tAttr.items():
|
1364
|
-
if aVal is not None:
|
1365
|
-
attr[_mkTag(aNm, aName)] = aVal
|
1366
|
-
|
1367
|
-
if attr:
|
1399
|
+
xEntry = ET.SubElement(xParent, _mkTag("style", "style"), attrib={
|
1400
|
+
_mkTag("style", "name"): self._name,
|
1401
|
+
_mkTag("style", "family"): "text",
|
1402
|
+
})
|
1403
|
+
if attr := {_mkTag(n, m): v for m, (n, v) in self._tAttr.items() if v}:
|
1368
1404
|
ET.SubElement(xEntry, _mkTag("style", "text-properties"), attrib=attr)
|
1369
|
-
|
1370
1405
|
return
|
1371
1406
|
|
1372
1407
|
# END Class ODTTextStyle
|