novelWriter 2.5.1__py3-none-any.whl → 2.6b1__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.
Files changed (64) hide show
  1. {novelWriter-2.5.1.dist-info → novelWriter-2.6b1.dist-info}/METADATA +2 -1
  2. {novelWriter-2.5.1.dist-info → novelWriter-2.6b1.dist-info}/RECORD +61 -56
  3. {novelWriter-2.5.1.dist-info → novelWriter-2.6b1.dist-info}/WHEEL +1 -1
  4. novelwriter/__init__.py +3 -3
  5. novelwriter/assets/i18n/project_en_GB.json +1 -0
  6. novelwriter/assets/icons/typicons_dark/icons.conf +1 -0
  7. novelwriter/assets/icons/typicons_dark/mixed_copy.svg +4 -0
  8. novelwriter/assets/icons/typicons_light/icons.conf +1 -0
  9. novelwriter/assets/icons/typicons_light/mixed_copy.svg +4 -0
  10. novelwriter/assets/manual.pdf +0 -0
  11. novelwriter/assets/sample.zip +0 -0
  12. novelwriter/assets/themes/default_light.conf +2 -2
  13. novelwriter/common.py +63 -0
  14. novelwriter/config.py +10 -3
  15. novelwriter/constants.py +153 -60
  16. novelwriter/core/buildsettings.py +66 -39
  17. novelwriter/core/coretools.py +34 -22
  18. novelwriter/core/docbuild.py +130 -169
  19. novelwriter/core/index.py +29 -18
  20. novelwriter/core/item.py +2 -2
  21. novelwriter/core/options.py +4 -1
  22. novelwriter/core/spellcheck.py +9 -14
  23. novelwriter/dialogs/preferences.py +45 -32
  24. novelwriter/dialogs/projectsettings.py +3 -3
  25. novelwriter/enum.py +29 -23
  26. novelwriter/extensions/configlayout.py +24 -11
  27. novelwriter/extensions/modified.py +13 -1
  28. novelwriter/extensions/pagedsidebar.py +5 -5
  29. novelwriter/formats/shared.py +155 -0
  30. novelwriter/formats/todocx.py +1195 -0
  31. novelwriter/formats/tohtml.py +452 -0
  32. novelwriter/{core → formats}/tokenizer.py +483 -485
  33. novelwriter/formats/tomarkdown.py +217 -0
  34. novelwriter/{core → formats}/toodt.py +270 -320
  35. novelwriter/formats/toqdoc.py +436 -0
  36. novelwriter/formats/toraw.py +91 -0
  37. novelwriter/gui/doceditor.py +240 -193
  38. novelwriter/gui/dochighlight.py +96 -84
  39. novelwriter/gui/docviewer.py +56 -30
  40. novelwriter/gui/docviewerpanel.py +3 -3
  41. novelwriter/gui/editordocument.py +17 -2
  42. novelwriter/gui/itemdetails.py +8 -4
  43. novelwriter/gui/mainmenu.py +121 -60
  44. novelwriter/gui/noveltree.py +35 -37
  45. novelwriter/gui/outline.py +186 -238
  46. novelwriter/gui/projtree.py +142 -131
  47. novelwriter/gui/sidebar.py +7 -6
  48. novelwriter/gui/theme.py +5 -4
  49. novelwriter/guimain.py +43 -155
  50. novelwriter/shared.py +14 -4
  51. novelwriter/text/counting.py +2 -0
  52. novelwriter/text/patterns.py +155 -59
  53. novelwriter/tools/manusbuild.py +1 -1
  54. novelwriter/tools/manuscript.py +121 -78
  55. novelwriter/tools/manussettings.py +403 -260
  56. novelwriter/tools/welcome.py +4 -4
  57. novelwriter/tools/writingstats.py +3 -3
  58. novelwriter/types.py +16 -6
  59. novelwriter/core/tohtml.py +0 -530
  60. novelwriter/core/tomarkdown.py +0 -252
  61. novelwriter/core/toqdoc.py +0 -419
  62. {novelWriter-2.5.1.dist-info → novelWriter-2.6b1.dist-info}/LICENSE.md +0 -0
  63. {novelWriter-2.5.1.dist-info → novelWriter-2.6b1.dist-info}/entry_points.txt +0 -0
  64. {novelWriter-2.5.1.dist-info → novelWriter-2.6b1.dist-info}/top_level.txt +0 -0
@@ -37,8 +37,8 @@ from PyQt5.QtWidgets import (
37
37
  )
38
38
 
39
39
  from novelwriter import CONFIG, SHARED
40
- from novelwriter.common import describeFont
41
- from novelwriter.constants import nwHeadFmt, nwKeyWords, nwLabels, trConst
40
+ from novelwriter.common import describeFont, qtLambda
41
+ from novelwriter.constants import nwHeadFmt, nwKeyWords, nwLabels, nwStyles, trConst
42
42
  from novelwriter.core.buildsettings import BuildSettings, FilterMode
43
43
  from novelwriter.extensions.configlayout import (
44
44
  NColourLabel, NFixedPage, NScrollableForm, NScrollablePage
@@ -50,8 +50,8 @@ from novelwriter.extensions.pagedsidebar import NPagedSideBar
50
50
  from novelwriter.extensions.switch import NSwitch
51
51
  from novelwriter.extensions.switchbox import NSwitchBox
52
52
  from novelwriter.types import (
53
- QtAlignLeft, QtDialogApply, QtDialogClose, QtDialogSave, QtRoleAccept,
54
- QtRoleApply, QtRoleReject, QtUserRole
53
+ QtAlignCenter, QtAlignLeft, QtDialogApply, QtDialogClose, QtDialogSave,
54
+ QtRoleAccept, QtRoleApply, QtRoleReject, QtUserRole
55
55
  )
56
56
 
57
57
  if TYPE_CHECKING: # pragma: no cover
@@ -67,11 +67,9 @@ class GuiBuildSettings(NToolDialog):
67
67
  editing JSON build definitions, wrapped as a BuildSettings object.
68
68
  """
69
69
 
70
- OPT_FILTERS = 1
71
- OPT_HEADINGS = 2
72
- OPT_CONTENT = 3
73
- OPT_FORMAT = 4
74
- OPT_OUTPUT = 5
70
+ OPT_FILTERS = 1
71
+ OPT_HEADINGS = 2
72
+ OPT_FORMATTING = 10
75
73
 
76
74
  newSettingsReady = pyqtSignal(BuildSettings)
77
75
 
@@ -86,7 +84,6 @@ class GuiBuildSettings(NToolDialog):
86
84
  self.setWindowTitle(self.tr("Manuscript Build Settings"))
87
85
  self.setMinimumSize(CONFIG.pxInt(700), CONFIG.pxInt(400))
88
86
 
89
- mPx = CONFIG.pxInt(150)
90
87
  wWin = CONFIG.pxInt(750)
91
88
  hWin = CONFIG.pxInt(550)
92
89
 
@@ -108,31 +105,24 @@ class GuiBuildSettings(NToolDialog):
108
105
 
109
106
  # SideBar
110
107
  self.sidebar = NPagedSideBar(self)
111
- self.sidebar.setMinimumWidth(mPx)
112
- self.sidebar.setMaximumWidth(mPx)
113
108
  self.sidebar.setLabelColor(SHARED.theme.helpText)
114
109
 
110
+ self.sidebar.addLabel(self.tr("General"))
115
111
  self.sidebar.addButton(self.tr("Selection"), self.OPT_FILTERS)
116
112
  self.sidebar.addButton(self.tr("Headings"), self.OPT_HEADINGS)
117
- self.sidebar.addButton(self.tr("Content"), self.OPT_CONTENT)
118
- self.sidebar.addButton(self.tr("Format"), self.OPT_FORMAT)
119
- self.sidebar.addButton(self.tr("Output"), self.OPT_OUTPUT)
113
+ self.sidebar.addLabel(self.tr("Formatting"))
120
114
 
121
115
  self.sidebar.buttonClicked.connect(self._stackPageSelected)
122
116
 
123
117
  # Content
124
118
  self.optTabSelect = _FilterTab(self, self._build)
125
119
  self.optTabHeadings = _HeadingsTab(self, self._build)
126
- self.optTabContent = _ContentTab(self, self._build)
127
- self.optTabFormat = _FormatTab(self, self._build)
128
- self.optTabOutput = _OutputTab(self, self._build)
120
+ self.optTabFormatting = _FormattingTab(self, self._build, self.sidebar)
129
121
 
130
122
  self.toolStack = QStackedWidget(self)
131
123
  self.toolStack.addWidget(self.optTabSelect)
132
124
  self.toolStack.addWidget(self.optTabHeadings)
133
- self.toolStack.addWidget(self.optTabFormat)
134
- self.toolStack.addWidget(self.optTabContent)
135
- self.toolStack.addWidget(self.optTabOutput)
125
+ self.toolStack.addWidget(self.optTabFormatting)
136
126
 
137
127
  # Buttons
138
128
  self.buttonBox = QDialogButtonBox(QtDialogApply | QtDialogSave | QtDialogClose, self)
@@ -174,9 +164,7 @@ class GuiBuildSettings(NToolDialog):
174
164
  self.editBuildName.setText(self._build.name)
175
165
  self.optTabSelect.loadContent()
176
166
  self.optTabHeadings.loadContent()
177
- self.optTabContent.loadContent()
178
- self.optTabFormat.loadContent()
179
- self.optTabOutput.loadContent()
167
+ self.optTabFormatting.loadContent()
180
168
  return
181
169
 
182
170
  ##
@@ -214,12 +202,9 @@ class GuiBuildSettings(NToolDialog):
214
202
  self.toolStack.setCurrentWidget(self.optTabSelect)
215
203
  elif pageId == self.OPT_HEADINGS:
216
204
  self.toolStack.setCurrentWidget(self.optTabHeadings)
217
- elif pageId == self.OPT_CONTENT:
218
- self.toolStack.setCurrentWidget(self.optTabContent)
219
- elif pageId == self.OPT_FORMAT:
220
- self.toolStack.setCurrentWidget(self.optTabFormat)
221
- elif pageId == self.OPT_OUTPUT:
222
- self.toolStack.setCurrentWidget(self.optTabOutput)
205
+ elif pageId >= self.OPT_FORMATTING:
206
+ self.toolStack.setCurrentWidget(self.optTabFormatting)
207
+ self.optTabFormatting.scrollToSection(pageId)
223
208
  return
224
209
 
225
210
  @pyqtSlot("QAbstractButton*")
@@ -272,9 +257,7 @@ class GuiBuildSettings(NToolDialog):
272
257
  """Assemble the build data and emit the signal."""
273
258
  self._build.setName(self.editBuildName.text())
274
259
  self.optTabHeadings.saveContent()
275
- self.optTabContent.saveContent()
276
- self.optTabFormat.saveContent()
277
- self.optTabOutput.saveContent()
260
+ self.optTabFormatting.saveContent()
278
261
  self.newSettingsReady.emit(self._build)
279
262
  self._build.resetChangedState()
280
263
  return
@@ -346,16 +329,16 @@ class _FilterTab(NFixedPage):
346
329
  self.includedButton = NIconToolButton(self, iSz)
347
330
  self.includedButton.setToolTip(self.tr("Always included"))
348
331
  self.includedButton.setIcon(self._statusFlags[self.F_INCLUDED])
349
- self.includedButton.clicked.connect(lambda: self._setSelectedMode(self.F_INCLUDED))
332
+ self.includedButton.clicked.connect(qtLambda(self._setSelectedMode, self.F_INCLUDED))
350
333
 
351
334
  self.excludedButton = NIconToolButton(self, iSz)
352
335
  self.excludedButton.setToolTip(self.tr("Always excluded"))
353
336
  self.excludedButton.setIcon(self._statusFlags[self.F_EXCLUDED])
354
- self.excludedButton.clicked.connect(lambda: self._setSelectedMode(self.F_EXCLUDED))
337
+ self.excludedButton.clicked.connect(qtLambda(self._setSelectedMode, self.F_EXCLUDED))
355
338
 
356
339
  self.resetButton = NIconToolButton(self, iSz, "revert")
357
340
  self.resetButton.setToolTip(self.tr("Reset to default"))
358
- self.resetButton.clicked.connect(lambda: self._setSelectedMode(self.F_FILTERED))
341
+ self.resetButton.clicked.connect(qtLambda(self._setSelectedMode, self.F_FILTERED))
359
342
 
360
343
  self.modeBox = QHBoxLayout()
361
344
  self.modeBox.addWidget(QLabel(self.tr("Mark selection as"), self))
@@ -602,27 +585,27 @@ class _HeadingsTab(NScrollablePage):
602
585
  self.formatBox.setHorizontalSpacing(bSp)
603
586
 
604
587
  # Title Heading
605
- self.lblTitle = QLabel(self._build.getLabel("headings.fmtTitle"), self)
606
- self.fmtTitle = QLineEdit("", self)
607
- self.fmtTitle.setReadOnly(True)
608
- self.btnTitle = NIconToolButton(self, iSz, "edit")
609
- self.btnTitle.clicked.connect(lambda: self._editHeading(self.EDIT_TITLE))
610
- self.hdeTitle = QLabel(trHide, self)
611
- self.hdeTitle.setIndent(bSp)
612
- self.swtTitle = NSwitch(self, height=iPx)
613
-
614
- self.formatBox.addWidget(self.lblTitle, 0, 0)
615
- self.formatBox.addWidget(self.fmtTitle, 0, 1)
616
- self.formatBox.addWidget(self.btnTitle, 0, 2)
617
- self.formatBox.addWidget(self.hdeTitle, 0, 3)
618
- self.formatBox.addWidget(self.swtTitle, 0, 4)
588
+ self.lblPart = QLabel(self._build.getLabel("headings.fmtPart"), self)
589
+ self.fmtPart = QLineEdit("", self)
590
+ self.fmtPart.setReadOnly(True)
591
+ self.btnPart = NIconToolButton(self, iSz, "edit")
592
+ self.btnPart.clicked.connect(qtLambda(self._editHeading, self.EDIT_TITLE))
593
+ self.hdePart = QLabel(trHide, self)
594
+ self.hdePart.setIndent(bSp)
595
+ self.swtPart = NSwitch(self, height=iPx)
596
+
597
+ self.formatBox.addWidget(self.lblPart, 0, 0)
598
+ self.formatBox.addWidget(self.fmtPart, 0, 1)
599
+ self.formatBox.addWidget(self.btnPart, 0, 2)
600
+ self.formatBox.addWidget(self.hdePart, 0, 3)
601
+ self.formatBox.addWidget(self.swtPart, 0, 4)
619
602
 
620
603
  # Chapter Heading
621
604
  self.lblChapter = QLabel(self._build.getLabel("headings.fmtChapter"), self)
622
605
  self.fmtChapter = QLineEdit("", self)
623
606
  self.fmtChapter.setReadOnly(True)
624
607
  self.btnChapter = NIconToolButton(self, iSz, "edit")
625
- self.btnChapter.clicked.connect(lambda: self._editHeading(self.EDIT_CHAPTER))
608
+ self.btnChapter.clicked.connect(qtLambda(self._editHeading, self.EDIT_CHAPTER))
626
609
  self.hdeChapter = QLabel(trHide, self)
627
610
  self.hdeChapter.setIndent(bSp)
628
611
  self.swtChapter = NSwitch(self, height=iPx)
@@ -638,7 +621,7 @@ class _HeadingsTab(NScrollablePage):
638
621
  self.fmtUnnumbered = QLineEdit("", self)
639
622
  self.fmtUnnumbered.setReadOnly(True)
640
623
  self.btnUnnumbered = NIconToolButton(self, iSz, "edit")
641
- self.btnUnnumbered.clicked.connect(lambda: self._editHeading(self.EDIT_UNNUM))
624
+ self.btnUnnumbered.clicked.connect(qtLambda(self._editHeading, self.EDIT_UNNUM))
642
625
  self.hdeUnnumbered = QLabel(trHide, self)
643
626
  self.hdeUnnumbered.setIndent(bSp)
644
627
  self.swtUnnumbered = NSwitch(self, height=iPx)
@@ -654,7 +637,7 @@ class _HeadingsTab(NScrollablePage):
654
637
  self.fmtScene = QLineEdit("", self)
655
638
  self.fmtScene.setReadOnly(True)
656
639
  self.btnScene = NIconToolButton(self, iSz, "edit")
657
- self.btnScene.clicked.connect(lambda: self._editHeading(self.EDIT_SCENE))
640
+ self.btnScene.clicked.connect(qtLambda(self._editHeading, self.EDIT_SCENE))
658
641
  self.hdeScene = QLabel(trHide, self)
659
642
  self.hdeScene.setIndent(bSp)
660
643
  self.swtScene = NSwitch(self, height=iPx)
@@ -670,7 +653,7 @@ class _HeadingsTab(NScrollablePage):
670
653
  self.fmtAScene = QLineEdit("", self)
671
654
  self.fmtAScene.setReadOnly(True)
672
655
  self.btnAScene = NIconToolButton(self, iSz, "edit")
673
- self.btnAScene.clicked.connect(lambda: self._editHeading(self.EDIT_HSCENE))
656
+ self.btnAScene.clicked.connect(qtLambda(self._editHeading, self.EDIT_HSCENE))
674
657
  self.hdeAScene = QLabel(trHide, self)
675
658
  self.hdeAScene.setIndent(bSp)
676
659
  self.swtAScene = NSwitch(self, height=iPx)
@@ -686,7 +669,7 @@ class _HeadingsTab(NScrollablePage):
686
669
  self.fmtSection = QLineEdit("", self)
687
670
  self.fmtSection.setReadOnly(True)
688
671
  self.btnSection = NIconToolButton(self, iSz, "edit")
689
- self.btnSection.clicked.connect(lambda: self._editHeading(self.EDIT_SECTION))
672
+ self.btnSection.clicked.connect(qtLambda(self._editHeading, self.EDIT_SECTION))
690
673
  self.hdeSection = QLabel(trHide, self)
691
674
  self.hdeSection.setIndent(bSp)
692
675
  self.swtSection = NSwitch(self, height=iPx)
@@ -719,15 +702,15 @@ class _HeadingsTab(NScrollablePage):
719
702
  self.aInsCharPOV = self.menuInsert.addAction(self.tr("Point of View Character"))
720
703
  self.aInsCharFocus = self.menuInsert.addAction(self.tr("Focus Character"))
721
704
 
722
- self.aInsTitle.triggered.connect(lambda: self._insertIntoForm(nwHeadFmt.TITLE))
723
- self.aInsChNum.triggered.connect(lambda: self._insertIntoForm(nwHeadFmt.CH_NUM))
724
- self.aInsChWord.triggered.connect(lambda: self._insertIntoForm(nwHeadFmt.CH_WORD))
725
- self.aInsChRomU.triggered.connect(lambda: self._insertIntoForm(nwHeadFmt.CH_ROMU))
726
- self.aInsChRomL.triggered.connect(lambda: self._insertIntoForm(nwHeadFmt.CH_ROML))
727
- self.aInsScNum.triggered.connect(lambda: self._insertIntoForm(nwHeadFmt.SC_NUM))
728
- self.aInsScAbs.triggered.connect(lambda: self._insertIntoForm(nwHeadFmt.SC_ABS))
729
- self.aInsCharPOV.triggered.connect(lambda: self._insertIntoForm(nwHeadFmt.CHAR_POV))
730
- self.aInsCharFocus.triggered.connect(lambda: self._insertIntoForm(nwHeadFmt.CHAR_FOCUS))
705
+ self.aInsTitle.triggered.connect(qtLambda(self._insertIntoForm, nwHeadFmt.TITLE))
706
+ self.aInsChNum.triggered.connect(qtLambda(self._insertIntoForm, nwHeadFmt.CH_NUM))
707
+ self.aInsChWord.triggered.connect(qtLambda(self._insertIntoForm, nwHeadFmt.CH_WORD))
708
+ self.aInsChRomU.triggered.connect(qtLambda(self._insertIntoForm, nwHeadFmt.CH_ROMU))
709
+ self.aInsChRomL.triggered.connect(qtLambda(self._insertIntoForm, nwHeadFmt.CH_ROML))
710
+ self.aInsScNum.triggered.connect(qtLambda(self._insertIntoForm, nwHeadFmt.SC_NUM))
711
+ self.aInsScAbs.triggered.connect(qtLambda(self._insertIntoForm, nwHeadFmt.SC_ABS))
712
+ self.aInsCharPOV.triggered.connect(qtLambda(self._insertIntoForm, nwHeadFmt.CHAR_POV))
713
+ self.aInsCharFocus.triggered.connect(qtLambda(self._insertIntoForm, nwHeadFmt.CHAR_FOCUS))
731
714
 
732
715
  self.btnInsert = QPushButton(self.tr("Insert"), self)
733
716
  self.btnInsert.setMenu(self.menuInsert)
@@ -751,56 +734,46 @@ class _HeadingsTab(NScrollablePage):
751
734
  self.layoutMatrix.setVerticalSpacing(vSp)
752
735
  self.layoutMatrix.setHorizontalSpacing(vSp)
753
736
 
754
- # Heading
755
- self.layoutHeading = QLabel("<b>{0}</b>".format(self.tr("Additional Styling")), self)
756
- self.layoutMatrix.addWidget(self.layoutHeading, 0, 0, 1, 5)
737
+ self.layoutMatrix.addWidget(QLabel(self.tr("Centre"), self), 0, 1)
738
+ self.layoutMatrix.addWidget(QLabel(self.tr("Page Break"), self), 0, 2)
757
739
 
758
740
  # Title Layout
759
- self.mtxTitle = QLabel(self._build.getLabel("headings.fmtTitle"), self)
741
+ self.lblTitle = QLabel(self._build.getLabel("headings.styleTitle"), self)
760
742
  self.centerTitle = NSwitch(self, height=iPx)
761
743
  self.breakTitle = NSwitch(self, height=iPx)
762
- lblCenterT = QLabel(self.tr("Centre"), self)
763
- lblCenterT.setIndent(sSp)
764
- lblBreakT = QLabel(self.tr("Page Break"), self)
765
- lblBreakT.setIndent(sSp)
766
744
 
767
- self.layoutMatrix.addWidget(self.mtxTitle, 1, 0)
768
- self.layoutMatrix.addWidget(lblCenterT, 1, 1)
769
- self.layoutMatrix.addWidget(self.centerTitle, 1, 2)
770
- self.layoutMatrix.addWidget(lblBreakT, 1, 3)
771
- self.layoutMatrix.addWidget(self.breakTitle, 1, 4)
745
+ self.layoutMatrix.addWidget(self.lblTitle, 1, 0)
746
+ self.layoutMatrix.addWidget(self.centerTitle, 1, 1, QtAlignCenter)
747
+ self.layoutMatrix.addWidget(self.breakTitle, 1, 2, QtAlignCenter)
748
+
749
+ # Partition Layout
750
+ self.lblPart = QLabel(self._build.getLabel("headings.stylePart"), self)
751
+ self.centerPart = NSwitch(self, height=iPx)
752
+ self.breakPart = NSwitch(self, height=iPx)
753
+
754
+ self.layoutMatrix.addWidget(self.lblPart, 2, 0)
755
+ self.layoutMatrix.addWidget(self.centerPart, 2, 1, QtAlignCenter)
756
+ self.layoutMatrix.addWidget(self.breakPart, 2, 2, QtAlignCenter)
772
757
 
773
758
  # Chapter Layout
774
- self.mtxChapter = QLabel(self._build.getLabel("headings.fmtChapter"), self)
759
+ self.lblChapter = QLabel(self._build.getLabel("headings.styleChapter"), self)
775
760
  self.centerChapter = NSwitch(self, height=iPx)
776
761
  self.breakChapter = NSwitch(self, height=iPx)
777
- lblCenterC = QLabel(self.tr("Centre"), self)
778
- lblCenterC.setIndent(sSp)
779
- lblBreakC = QLabel(self.tr("Page Break"), self)
780
- lblBreakC.setIndent(sSp)
781
762
 
782
- self.layoutMatrix.addWidget(self.mtxChapter, 2, 0)
783
- self.layoutMatrix.addWidget(lblCenterC, 2, 1)
784
- self.layoutMatrix.addWidget(self.centerChapter, 2, 2)
785
- self.layoutMatrix.addWidget(lblBreakC, 2, 3)
786
- self.layoutMatrix.addWidget(self.breakChapter, 2, 4)
763
+ self.layoutMatrix.addWidget(self.lblChapter, 3, 0)
764
+ self.layoutMatrix.addWidget(self.centerChapter, 3, 1, QtAlignCenter)
765
+ self.layoutMatrix.addWidget(self.breakChapter, 3, 2, QtAlignCenter)
787
766
 
788
767
  # Scene Layout
789
- self.mtxScene = QLabel(self._build.getLabel("headings.fmtScene"), self)
768
+ self.lblScene = QLabel(self._build.getLabel("headings.styleScene"), self)
790
769
  self.centerScene = NSwitch(self, height=iPx)
791
770
  self.breakScene = NSwitch(self, height=iPx)
792
- lblCenterS = QLabel(self.tr("Centre"), self)
793
- lblCenterS.setIndent(sSp)
794
- lblBreakS = QLabel(self.tr("Page Break"), self)
795
- lblBreakS.setIndent(sSp)
796
771
 
797
- self.layoutMatrix.addWidget(self.mtxScene, 3, 0)
798
- self.layoutMatrix.addWidget(lblCenterS, 3, 1)
799
- self.layoutMatrix.addWidget(self.centerScene, 3, 2)
800
- self.layoutMatrix.addWidget(lblBreakS, 3, 3)
801
- self.layoutMatrix.addWidget(self.breakScene, 3, 4)
772
+ self.layoutMatrix.addWidget(self.lblScene, 4, 0)
773
+ self.layoutMatrix.addWidget(self.centerScene, 4, 1, QtAlignCenter)
774
+ self.layoutMatrix.addWidget(self.breakScene, 4, 2, QtAlignCenter)
802
775
 
803
- self.layoutMatrix.setColumnStretch(5, 1)
776
+ self.layoutMatrix.setColumnStretch(3, 1)
804
777
 
805
778
  # Assemble
806
779
  # ========
@@ -819,14 +792,14 @@ class _HeadingsTab(NScrollablePage):
819
792
 
820
793
  def loadContent(self) -> None:
821
794
  """Populate the widgets."""
822
- self.fmtTitle.setText(self._build.getStr("headings.fmtTitle"))
795
+ self.fmtPart.setText(self._build.getStr("headings.fmtPart"))
823
796
  self.fmtChapter.setText(self._build.getStr("headings.fmtChapter"))
824
797
  self.fmtUnnumbered.setText(self._build.getStr("headings.fmtUnnumbered"))
825
798
  self.fmtScene.setText(self._build.getStr("headings.fmtScene"))
826
799
  self.fmtAScene.setText(self._build.getStr("headings.fmtAltScene"))
827
800
  self.fmtSection.setText(self._build.getStr("headings.fmtSection"))
828
801
 
829
- self.swtTitle.setChecked(self._build.getBool("headings.hideTitle"))
802
+ self.swtPart.setChecked(self._build.getBool("headings.hidePart"))
830
803
  self.swtChapter.setChecked(self._build.getBool("headings.hideChapter"))
831
804
  self.swtUnnumbered.setChecked(self._build.getBool("headings.hideUnnumbered"))
832
805
  self.swtScene.setChecked(self._build.getBool("headings.hideScene"))
@@ -834,16 +807,19 @@ class _HeadingsTab(NScrollablePage):
834
807
  self.swtSection.setChecked(self._build.getBool("headings.hideSection"))
835
808
 
836
809
  self.centerTitle.setChecked(self._build.getBool("headings.centerTitle"))
810
+ self.centerPart.setChecked(self._build.getBool("headings.centerPart"))
837
811
  self.centerChapter.setChecked(self._build.getBool("headings.centerChapter"))
838
812
  self.centerScene.setChecked(self._build.getBool("headings.centerScene"))
813
+
839
814
  self.breakTitle.setChecked(self._build.getBool("headings.breakTitle"))
815
+ self.breakPart.setChecked(self._build.getBool("headings.breakPart"))
840
816
  self.breakChapter.setChecked(self._build.getBool("headings.breakChapter"))
841
817
  self.breakScene.setChecked(self._build.getBool("headings.breakScene"))
842
818
  return
843
819
 
844
820
  def saveContent(self) -> None:
845
821
  """Save choices back into build object."""
846
- self._build.setValue("headings.hideTitle", self.swtTitle.isChecked())
822
+ self._build.setValue("headings.hidePart", self.swtPart.isChecked())
847
823
  self._build.setValue("headings.hideChapter", self.swtChapter.isChecked())
848
824
  self._build.setValue("headings.hideUnnumbered", self.swtUnnumbered.isChecked())
849
825
  self._build.setValue("headings.hideScene", self.swtScene.isChecked())
@@ -851,9 +827,12 @@ class _HeadingsTab(NScrollablePage):
851
827
  self._build.setValue("headings.hideSection", self.swtSection.isChecked())
852
828
 
853
829
  self._build.setValue("headings.centerTitle", self.centerTitle.isChecked())
830
+ self._build.setValue("headings.centerPart", self.centerPart.isChecked())
854
831
  self._build.setValue("headings.centerChapter", self.centerChapter.isChecked())
855
832
  self._build.setValue("headings.centerScene", self.centerScene.isChecked())
833
+
856
834
  self._build.setValue("headings.breakTitle", self.breakTitle.isChecked())
835
+ self._build.setValue("headings.breakPart", self.breakPart.isChecked())
857
836
  self._build.setValue("headings.breakChapter", self.breakChapter.isChecked())
858
837
  self._build.setValue("headings.breakScene", self.breakScene.isChecked())
859
838
  return
@@ -875,8 +854,8 @@ class _HeadingsTab(NScrollablePage):
875
854
  self._editing = heading
876
855
  self.editTextBox.setEnabled(True)
877
856
  if heading == self.EDIT_TITLE:
878
- text = self.fmtTitle.text()
879
- label = self._build.getLabel("headings.fmtTitle")
857
+ text = self.fmtPart.text()
858
+ label = self._build.getLabel("headings.fmtPart")
880
859
  elif heading == self.EDIT_CHAPTER:
881
860
  text = self.fmtChapter.text()
882
861
  label = self._build.getLabel("headings.fmtChapter")
@@ -913,8 +892,8 @@ class _HeadingsTab(NScrollablePage):
913
892
  heading = self._editing
914
893
  text = self.editTextBox.toPlainText().strip().replace("\n", nwHeadFmt.BR)
915
894
  if heading == self.EDIT_TITLE:
916
- self.fmtTitle.setText(text)
917
- self._build.setValue("headings.fmtTitle", text)
895
+ self.fmtPart.setText(text)
896
+ self._build.setValue("headings.fmtPart", text)
918
897
  elif heading == self.EDIT_CHAPTER:
919
898
  self.fmtChapter.setText(text)
920
899
  self._build.setValue("headings.fmtChapter", text)
@@ -963,22 +942,57 @@ class _HeadingSyntaxHighlighter(QSyntaxHighlighter):
963
942
  return
964
943
 
965
944
 
966
- class _ContentTab(NScrollableForm):
945
+ class _FormattingTab(NScrollableForm):
967
946
 
968
- def __init__(self, parent: QWidget, build: BuildSettings) -> None:
947
+ def __init__(self, parent: QWidget, build: BuildSettings, sidebar: NPagedSideBar) -> None:
969
948
  super().__init__(parent=parent)
970
949
 
971
950
  self._build = build
951
+ self._sidebar = sidebar
952
+
953
+ self.setHelpTextStyle(SHARED.theme.helpText)
954
+ self.buildForm()
955
+
956
+ return
957
+
958
+ def buildForm(self) -> None:
959
+ """Build the formatting form."""
960
+ section = 10
972
961
 
973
962
  iPx = SHARED.theme.baseIconHeight
974
963
  iSz = SHARED.theme.baseIconSize
964
+ spW = 6*SHARED.theme.textNWidth
965
+ dbW = 8*SHARED.theme.textNWidth
966
+
967
+ # Common Translations
968
+
969
+ trW = self.tr("W:") # Width
970
+ trH = self.tr("H:") # Height
971
+ trT = self.tr("T:") # Top
972
+ trB = self.tr("B:") # Bottom
973
+ trL = self.tr("L:") # Left
974
+ trR = self.tr("R:") # Right
975
975
 
976
976
  # Text Content
977
+ # ============
978
+
979
+ title = self._build.getLabel("text.grpContent")
980
+ section += 1
981
+ self._sidebar.addButton(title, section)
982
+ self.addGroupLabel(title, section)
983
+
984
+ # Text Inclusion
977
985
  self.incBodyText = NSwitch(self, height=iPx)
978
986
  self.incSynopsis = NSwitch(self, height=iPx)
979
987
  self.incComments = NSwitch(self, height=iPx)
980
988
  self.incKeywords = NSwitch(self, height=iPx)
981
989
 
990
+ self.addRow(self._build.getLabel("text.includeBodyText"), self.incBodyText)
991
+ self.addRow(self._build.getLabel("text.includeSynopsis"), self.incSynopsis)
992
+ self.addRow(self._build.getLabel("text.includeComments"), self.incComments)
993
+ self.addRow(self._build.getLabel("text.includeKeywords"), self.incKeywords)
994
+
995
+ # Ignored Keywords
982
996
  self.ignoredKeywords = QLineEdit(self)
983
997
 
984
998
  self.mnKeywords = QMenu(self)
@@ -990,80 +1004,23 @@ class _ContentTab(NScrollableForm):
990
1004
 
991
1005
  self.ignoredKeywordsButton = NIconToolButton(self, iSz, "add")
992
1006
  self.ignoredKeywordsButton.setMenu(self.mnKeywords)
1007
+ self.addRow(
1008
+ self._build.getLabel("text.ignoredKeywords"), self.ignoredKeywords,
1009
+ button=self.ignoredKeywordsButton, stretch=(1, 1)
1010
+ )
993
1011
 
994
- self.addGroupLabel(self._build.getLabel("text.grpContent"))
995
- self.addRow(self._build.getLabel("text.includeBodyText"), self.incBodyText)
996
- self.addRow(self._build.getLabel("text.includeSynopsis"), self.incSynopsis)
997
- self.addRow(self._build.getLabel("text.includeComments"), self.incComments)
998
- self.addRow(self._build.getLabel("text.includeKeywords"), self.incKeywords)
999
- self.addRow(self._build.getLabel("text.ignoredKeywords"), self.ignoredKeywords,
1000
- button=self.ignoredKeywordsButton, stretch=(1, 1))
1001
-
1002
- # Insert Content
1012
+ # Note Headings
1003
1013
  self.addNoteHead = NSwitch(self, height=iPx)
1004
1014
 
1005
- self.addGroupLabel(self._build.getLabel("text.grpInsert"))
1006
1015
  self.addRow(self._build.getLabel("text.addNoteHeadings"), self.addNoteHead)
1007
1016
 
1008
- # Finalise
1009
- self.finalise()
1010
-
1011
- return
1012
-
1013
- def loadContent(self) -> None:
1014
- """Populate the widgets."""
1015
- self.incBodyText.setChecked(self._build.getBool("text.includeBodyText"))
1016
- self.incSynopsis.setChecked(self._build.getBool("text.includeSynopsis"))
1017
- self.incComments.setChecked(self._build.getBool("text.includeComments"))
1018
- self.incKeywords.setChecked(self._build.getBool("text.includeKeywords"))
1019
- self.ignoredKeywords.setText(self._build.getStr("text.ignoredKeywords"))
1020
- self.addNoteHead.setChecked(self._build.getBool("text.addNoteHeadings"))
1021
- self._updateIgnoredKeywords()
1022
- return
1023
-
1024
- def saveContent(self) -> None:
1025
- """Save choices back into build object."""
1026
- self._updateIgnoredKeywords()
1027
- self._build.setValue("text.includeBodyText", self.incBodyText.isChecked())
1028
- self._build.setValue("text.includeSynopsis", self.incSynopsis.isChecked())
1029
- self._build.setValue("text.includeComments", self.incComments.isChecked())
1030
- self._build.setValue("text.includeKeywords", self.incKeywords.isChecked())
1031
- self._build.setValue("text.ignoredKeywords", self.ignoredKeywords.text())
1032
- self._build.setValue("text.addNoteHeadings", self.addNoteHead.isChecked())
1033
- return
1034
-
1035
- ##
1036
- # Internal Functions
1037
- ##
1038
-
1039
- def _updateIgnoredKeywords(self, keyword: str | None = None) -> None:
1040
- """Update the ignored keywords list."""
1041
- current = [x.lower().strip() for x in self.ignoredKeywords.text().split(",")]
1042
- if keyword:
1043
- current.append(keyword)
1044
- verified = set(x for x in current if x in nwKeyWords.VALID_KEYS)
1045
- self.ignoredKeywords.setText(", ".join(verified))
1046
- return
1047
-
1048
-
1049
- class _FormatTab(NScrollableForm):
1050
-
1051
- def __init__(self, parent: QWidget, build: BuildSettings) -> None:
1052
- super().__init__(parent=parent)
1053
-
1054
- self._build = build
1055
- self._unitScale = 1.0
1056
- self._textFont = QFont(CONFIG.textFont)
1057
-
1058
- iPx = SHARED.theme.baseIconHeight
1059
- iSz = SHARED.theme.baseIconSize
1060
- spW = 6*SHARED.theme.textNWidth
1061
- dbW = 8*SHARED.theme.textNWidth
1062
-
1063
1017
  # Text Format
1064
1018
  # ===========
1065
1019
 
1066
- self.addGroupLabel(self._build.getLabel("format.grpFormat"))
1020
+ title = self._build.getLabel("format.grpFormat")
1021
+ section += 1
1022
+ self._sidebar.addButton(title, section)
1023
+ self.addGroupLabel(title, section)
1067
1024
 
1068
1025
  # Text Font
1069
1026
  self.textFont = QLineEdit(self)
@@ -1085,10 +1042,6 @@ class _FormatTab(NScrollableForm):
1085
1042
  self.addRow(self._build.getLabel("format.lineHeight"), self.lineHeight, unit="em")
1086
1043
 
1087
1044
  # Text Options
1088
- # ============
1089
-
1090
- self.addGroupLabel(self._build.getLabel("format.grpOptions"))
1091
-
1092
1045
  self.justifyText = NSwitch(self, height=iPx)
1093
1046
  self.stripUnicode = NSwitch(self, height=iPx)
1094
1047
  self.replaceTabs = NSwitch(self, height=iPx)
@@ -1104,7 +1057,10 @@ class _FormatTab(NScrollableForm):
1104
1057
  # First Line Indent
1105
1058
  # =================
1106
1059
 
1107
- self.addGroupLabel(self._build.getLabel("format.grpParIndent"))
1060
+ title = self._build.getLabel("format.grpParIndent")
1061
+ section += 1
1062
+ self._sidebar.addButton(title, section)
1063
+ self.addGroupLabel(title, section)
1108
1064
 
1109
1065
  self.firstIndent = NSwitch(self, height=iPx)
1110
1066
  self.indentFirstPar = NSwitch(self, height=iPx)
@@ -1120,29 +1076,132 @@ class _FormatTab(NScrollableForm):
1120
1076
  self.addRow(self._build.getLabel("format.firstIndentWidth"), self.indentWidth, unit="em")
1121
1077
  self.addRow(self._build.getLabel("format.indentFirstPar"), self.indentFirstPar)
1122
1078
 
1079
+ # Text Margins
1080
+ # ============
1081
+
1082
+ title = self._build.getLabel("format.grpMargins")
1083
+ section += 1
1084
+ self._sidebar.addButton(title, section)
1085
+ self.addGroupLabel(title, section)
1086
+
1087
+ # Title
1088
+ self.titleMarginT = NDoubleSpinBox(self)
1089
+ self.titleMarginT.setFixedWidth(dbW)
1090
+
1091
+ self.titleMarginB = NDoubleSpinBox(self)
1092
+ self.titleMarginB.setFixedWidth(dbW)
1093
+
1094
+ self.addRow(
1095
+ trConst(nwStyles.T_LABEL["H0"]),
1096
+ [trT, self.titleMarginT, 6, trB, self.titleMarginB],
1097
+ )
1098
+
1099
+ # Heading 1
1100
+ self.h1MarginT = NDoubleSpinBox(self)
1101
+ self.h1MarginT.setFixedWidth(dbW)
1102
+
1103
+ self.h1MarginB = NDoubleSpinBox(self)
1104
+ self.h1MarginB.setFixedWidth(dbW)
1105
+
1106
+ self.addRow(
1107
+ trConst(nwStyles.T_LABEL["H1"]),
1108
+ [trT, self.h1MarginT, 6, trB, self.h1MarginB],
1109
+ )
1110
+
1111
+ # Heading 2
1112
+ self.h2MarginT = NDoubleSpinBox(self)
1113
+ self.h2MarginT.setFixedWidth(dbW)
1114
+
1115
+ self.h2MarginB = NDoubleSpinBox(self)
1116
+ self.h2MarginB.setFixedWidth(dbW)
1117
+
1118
+ self.addRow(
1119
+ trConst(nwStyles.T_LABEL["H2"]),
1120
+ [trT, self.h2MarginT, 6, trB, self.h2MarginB],
1121
+ )
1122
+
1123
+ # Heading 3
1124
+ self.h3MarginT = NDoubleSpinBox(self)
1125
+ self.h3MarginT.setFixedWidth(dbW)
1126
+
1127
+ self.h3MarginB = NDoubleSpinBox(self)
1128
+ self.h3MarginB.setFixedWidth(dbW)
1129
+
1130
+ self.addRow(
1131
+ trConst(nwStyles.T_LABEL["H3"]),
1132
+ [trT, self.h3MarginT, 6, trB, self.h3MarginB],
1133
+ )
1134
+
1135
+ # Heading 4
1136
+ self.h4MarginT = NDoubleSpinBox(self)
1137
+ self.h4MarginT.setFixedWidth(dbW)
1138
+
1139
+ self.h4MarginB = NDoubleSpinBox(self)
1140
+ self.h4MarginB.setFixedWidth(dbW)
1141
+
1142
+ self.addRow(
1143
+ trConst(nwStyles.T_LABEL["H4"]),
1144
+ [trT, self.h4MarginT, 6, trB, self.h4MarginB],
1145
+ )
1146
+
1147
+ # Text
1148
+ self.textMarginT = NDoubleSpinBox(self)
1149
+ self.textMarginT.setFixedWidth(dbW)
1150
+
1151
+ self.textMarginB = NDoubleSpinBox(self)
1152
+ self.textMarginB.setFixedWidth(dbW)
1153
+
1154
+ self.addRow(
1155
+ trConst(nwStyles.T_LABEL["TT"]),
1156
+ [trT, self.textMarginT, 6, trB, self.textMarginB],
1157
+ )
1158
+
1159
+ # Separator
1160
+ self.sepMarginT = NDoubleSpinBox(self)
1161
+ self.sepMarginT.setFixedWidth(dbW)
1162
+
1163
+ self.sepMarginB = NDoubleSpinBox(self)
1164
+ self.sepMarginB.setFixedWidth(dbW)
1165
+
1166
+ self.addRow(
1167
+ trConst(nwStyles.T_LABEL["SP"]),
1168
+ [trT, self.sepMarginT, 6, trB, self.sepMarginB],
1169
+ )
1170
+
1123
1171
  # Page Layout
1124
1172
  # ===========
1125
1173
 
1126
- self.addGroupLabel(self._build.getLabel("format.grpPage"))
1174
+ title = self._build.getLabel("format.grpPage")
1175
+ section += 1
1176
+ self._sidebar.addButton(title, section)
1177
+ self.addGroupLabel(title, section)
1127
1178
 
1179
+ # Unit
1128
1180
  self.pageUnit = NComboBox(self)
1129
1181
  for key, name in nwLabels.UNIT_NAME.items():
1130
1182
  self.pageUnit.addItem(trConst(name), key)
1131
1183
 
1184
+ self.addRow(self._build.getLabel("format.pageUnit"), self.pageUnit)
1185
+
1186
+ # Page Size
1132
1187
  self.pageSize = NComboBox(self)
1133
1188
  for key, name in nwLabels.PAPER_NAME.items():
1134
1189
  self.pageSize.addItem(trConst(name), key)
1135
1190
 
1136
- self.pageWidth = NDoubleSpinBox(self)
1191
+ self.pageWidth = NDoubleSpinBox(self, max=500.0)
1137
1192
  self.pageWidth.setFixedWidth(dbW)
1138
- self.pageWidth.setMaximum(500.0)
1139
1193
  self.pageWidth.valueChanged.connect(self._pageSizeValueChanged)
1140
1194
 
1141
- self.pageHeight = NDoubleSpinBox(self)
1195
+ self.pageHeight = NDoubleSpinBox(self, max=500.0)
1142
1196
  self.pageHeight.setFixedWidth(dbW)
1143
- self.pageHeight.setMaximum(500.0)
1144
1197
  self.pageHeight.valueChanged.connect(self._pageSizeValueChanged)
1145
1198
 
1199
+ self.addRow(
1200
+ self._build.getLabel("format.pageSize"),
1201
+ [self.pageSize, 6, trW, self.pageWidth, 6, trH, self.pageHeight],
1202
+ )
1203
+
1204
+ # Page Margins
1146
1205
  self.topMargin = NDoubleSpinBox(self)
1147
1206
  self.topMargin.setFixedWidth(dbW)
1148
1207
 
@@ -1155,14 +1214,62 @@ class _FormatTab(NScrollableForm):
1155
1214
  self.rightMargin = NDoubleSpinBox(self)
1156
1215
  self.rightMargin.setFixedWidth(dbW)
1157
1216
 
1158
- self.addRow(self._build.getLabel("format.pageUnit"), self.pageUnit)
1159
- self.addRow(self._build.getLabel("format.pageSize"), self.pageSize)
1160
- self.addRow(self._build.getLabel("format.pageWidth"), self.pageWidth)
1161
- self.addRow(self._build.getLabel("format.pageHeight"), self.pageHeight)
1162
- self.addRow(self._build.getLabel("format.topMargin"), self.topMargin)
1163
- self.addRow(self._build.getLabel("format.bottomMargin"), self.bottomMargin)
1164
- self.addRow(self._build.getLabel("format.leftMargin"), self.leftMargin)
1165
- self.addRow(self._build.getLabel("format.rightMargin"), self.rightMargin)
1217
+ self.addRow(
1218
+ self._build.getLabel("format.pageMargins"),
1219
+ [trT, self.topMargin, 6, trB, self.bottomMargin],
1220
+ )
1221
+ self.addRow(
1222
+ "",
1223
+ [trL, self.leftMargin, 6, trR, self.rightMargin],
1224
+ )
1225
+
1226
+ # Open Document
1227
+ # =============
1228
+
1229
+ title = self._build.getLabel("doc")
1230
+ section += 1
1231
+ self._sidebar.addButton(title, section)
1232
+ self.addGroupLabel(title, section)
1233
+
1234
+ # Header
1235
+ self.odtPageHeader = QLineEdit(self)
1236
+ self.odtPageHeader.setMinimumWidth(CONFIG.pxInt(200))
1237
+ self.btnPageHeader = NIconToolButton(self, iSz, "revert")
1238
+ self.btnPageHeader.clicked.connect(self._resetPageHeader)
1239
+ self.addRow(
1240
+ self._build.getLabel("doc.pageHeader"), self.odtPageHeader,
1241
+ button=self.btnPageHeader, stretch=(1, 1)
1242
+ )
1243
+
1244
+ self.odtPageCountOffset = NSpinBox(self)
1245
+ self.odtPageCountOffset.setMinimum(0)
1246
+ self.odtPageCountOffset.setMaximum(999)
1247
+ self.odtPageCountOffset.setSingleStep(1)
1248
+ self.odtPageCountOffset.setMinimumWidth(spW)
1249
+ self.addRow(self._build.getLabel("doc.pageCountOffset"), self.odtPageCountOffset)
1250
+
1251
+ # Headings
1252
+ self.colorHeadings = NSwitch(self, height=iPx)
1253
+ self.scaleHeadings = NSwitch(self, height=iPx)
1254
+ self.boldHeadings = NSwitch(self, height=iPx)
1255
+
1256
+ self.addRow(self._build.getLabel("doc.colorHeadings"), self.colorHeadings)
1257
+ self.addRow(self._build.getLabel("doc.scaleHeadings"), self.scaleHeadings)
1258
+ self.addRow(self._build.getLabel("doc.boldHeadings"), self.boldHeadings)
1259
+
1260
+ # HTML Document
1261
+ # =============
1262
+
1263
+ title = self._build.getLabel("html")
1264
+ section += 1
1265
+ self._sidebar.addButton(title, section)
1266
+ self.addGroupLabel(title, section)
1267
+
1268
+ self.htmlAddStyles = NSwitch(self, height=iPx)
1269
+ self.addRow(self._build.getLabel("html.addStyles"), self.htmlAddStyles)
1270
+
1271
+ self.htmlPreserveTabs = NSwitch(self, height=iPx)
1272
+ self.addRow(self._build.getLabel("html.preserveTabs"), self.htmlPreserveTabs)
1166
1273
 
1167
1274
  # Finalise
1168
1275
  self.finalise()
@@ -1171,6 +1278,20 @@ class _FormatTab(NScrollableForm):
1171
1278
 
1172
1279
  def loadContent(self) -> None:
1173
1280
  """Populate the widgets."""
1281
+ # Text Content
1282
+ # ============
1283
+
1284
+ self.incBodyText.setChecked(self._build.getBool("text.includeBodyText"))
1285
+ self.incSynopsis.setChecked(self._build.getBool("text.includeSynopsis"))
1286
+ self.incComments.setChecked(self._build.getBool("text.includeComments"))
1287
+ self.incKeywords.setChecked(self._build.getBool("text.includeKeywords"))
1288
+ self.ignoredKeywords.setText(self._build.getStr("text.ignoredKeywords"))
1289
+ self.addNoteHead.setChecked(self._build.getBool("text.addNoteHeadings"))
1290
+ self._updateIgnoredKeywords()
1291
+
1292
+ # Text Format
1293
+ # ===========
1294
+
1174
1295
  self._textFont = QFont()
1175
1296
  self._textFont.fromString(self._build.getStr("format.textFont"))
1176
1297
 
@@ -1184,10 +1305,34 @@ class _FormatTab(NScrollableForm):
1184
1305
  self.keepBreaks.setChecked(self._build.getBool("format.keepBreaks"))
1185
1306
  self.showDialogue.setChecked(self._build.getBool("format.showDialogue"))
1186
1307
 
1308
+ # First Line Indent
1309
+ # =================
1310
+
1187
1311
  self.firstIndent.setChecked(self._build.getBool("format.firstLineIndent"))
1188
1312
  self.indentWidth.setValue(self._build.getFloat("format.firstIndentWidth"))
1189
1313
  self.indentFirstPar.setChecked(self._build.getBool("format.indentFirstPar"))
1190
1314
 
1315
+ # Text Margins
1316
+ # ============
1317
+
1318
+ self.titleMarginT.setValue(self._build.getFloat("format.titleMarginT"))
1319
+ self.titleMarginB.setValue(self._build.getFloat("format.titleMarginB"))
1320
+ self.h1MarginT.setValue(self._build.getFloat("format.h1MarginT"))
1321
+ self.h1MarginB.setValue(self._build.getFloat("format.h1MarginB"))
1322
+ self.h2MarginT.setValue(self._build.getFloat("format.h2MarginT"))
1323
+ self.h2MarginB.setValue(self._build.getFloat("format.h2MarginB"))
1324
+ self.h3MarginT.setValue(self._build.getFloat("format.h3MarginT"))
1325
+ self.h3MarginB.setValue(self._build.getFloat("format.h3MarginB"))
1326
+ self.h4MarginT.setValue(self._build.getFloat("format.h4MarginT"))
1327
+ self.h4MarginB.setValue(self._build.getFloat("format.h4MarginB"))
1328
+ self.textMarginT.setValue(self._build.getFloat("format.textMarginT"))
1329
+ self.textMarginB.setValue(self._build.getFloat("format.textMarginB"))
1330
+ self.sepMarginT.setValue(self._build.getFloat("format.sepMarginT"))
1331
+ self.sepMarginB.setValue(self._build.getFloat("format.sepMarginB"))
1332
+
1333
+ # Page Layout
1334
+ # ===========
1335
+
1191
1336
  pageUnit = self._build.getStr("format.pageUnit")
1192
1337
  index = self.pageUnit.findData(pageUnit)
1193
1338
  if index >= 0:
@@ -1211,10 +1356,36 @@ class _FormatTab(NScrollableForm):
1211
1356
  self.pageUnit.currentIndexChanged.connect(self._changeUnit)
1212
1357
  self.pageSize.currentIndexChanged.connect(self._changePageSize)
1213
1358
 
1359
+ # Document
1360
+ # ========
1361
+
1362
+ self.colorHeadings.setChecked(self._build.getBool("doc.colorHeadings"))
1363
+ self.scaleHeadings.setChecked(self._build.getBool("doc.scaleHeadings"))
1364
+ self.boldHeadings.setChecked(self._build.getBool("doc.boldHeadings"))
1365
+ self.odtPageHeader.setText(self._build.getStr("doc.pageHeader"))
1366
+ self.odtPageCountOffset.setValue(self._build.getInt("doc.pageCountOffset"))
1367
+ self.odtPageHeader.setCursorPosition(0)
1368
+
1369
+ # HTML Document
1370
+ # =============
1371
+
1372
+ self.htmlAddStyles.setChecked(self._build.getBool("html.addStyles"))
1373
+ self.htmlPreserveTabs.setChecked(self._build.getBool("html.preserveTabs"))
1374
+
1214
1375
  return
1215
1376
 
1216
1377
  def saveContent(self) -> None:
1217
1378
  """Save choices back into build object."""
1379
+ # Text Content
1380
+ self._updateIgnoredKeywords()
1381
+ self._build.setValue("text.includeBodyText", self.incBodyText.isChecked())
1382
+ self._build.setValue("text.includeSynopsis", self.incSynopsis.isChecked())
1383
+ self._build.setValue("text.includeComments", self.incComments.isChecked())
1384
+ self._build.setValue("text.includeKeywords", self.incKeywords.isChecked())
1385
+ self._build.setValue("text.ignoredKeywords", self.ignoredKeywords.text())
1386
+ self._build.setValue("text.addNoteHeadings", self.addNoteHead.isChecked())
1387
+
1388
+ # Text Format
1218
1389
  self._build.setValue("format.textFont", self._textFont.toString())
1219
1390
  self._build.setValue("format.lineHeight", self.lineHeight.value())
1220
1391
 
@@ -1224,10 +1395,28 @@ class _FormatTab(NScrollableForm):
1224
1395
  self._build.setValue("format.keepBreaks", self.keepBreaks.isChecked())
1225
1396
  self._build.setValue("format.showDialogue", self.showDialogue.isChecked())
1226
1397
 
1398
+ # First Line Indent
1227
1399
  self._build.setValue("format.firstLineIndent", self.firstIndent.isChecked())
1228
1400
  self._build.setValue("format.firstIndentWidth", self.indentWidth.value())
1229
1401
  self._build.setValue("format.indentFirstPar", self.indentFirstPar.isChecked())
1230
1402
 
1403
+ # Text Margins
1404
+ self._build.setValue("format.titleMarginT", self.titleMarginT.value())
1405
+ self._build.setValue("format.titleMarginB", self.titleMarginB.value())
1406
+ self._build.setValue("format.h1MarginT", self.h1MarginT.value())
1407
+ self._build.setValue("format.h1MarginB", self.h1MarginB.value())
1408
+ self._build.setValue("format.h2MarginT", self.h2MarginT.value())
1409
+ self._build.setValue("format.h2MarginB", self.h2MarginB.value())
1410
+ self._build.setValue("format.h3MarginT", self.h3MarginT.value())
1411
+ self._build.setValue("format.h3MarginB", self.h3MarginB.value())
1412
+ self._build.setValue("format.h4MarginT", self.h4MarginT.value())
1413
+ self._build.setValue("format.h4MarginB", self.h4MarginB.value())
1414
+ self._build.setValue("format.textMarginT", self.textMarginT.value())
1415
+ self._build.setValue("format.textMarginB", self.textMarginB.value())
1416
+ self._build.setValue("format.sepMarginT", self.sepMarginT.value())
1417
+ self._build.setValue("format.sepMarginB", self.sepMarginB.value())
1418
+
1419
+ # Page Layout
1231
1420
  self._build.setValue("format.pageUnit", str(self.pageUnit.currentData()))
1232
1421
  self._build.setValue("format.pageSize", str(self.pageSize.currentData()))
1233
1422
  self._build.setValue("format.pageWidth", self.pageWidth.value())
@@ -1236,6 +1425,18 @@ class _FormatTab(NScrollableForm):
1236
1425
  self._build.setValue("format.bottomMargin", self.bottomMargin.value())
1237
1426
  self._build.setValue("format.leftMargin", self.leftMargin.value())
1238
1427
  self._build.setValue("format.rightMargin", self.rightMargin.value())
1428
+
1429
+ # Documents
1430
+ self._build.setValue("doc.colorHeadings", self.colorHeadings.isChecked())
1431
+ self._build.setValue("doc.scaleHeadings", self.scaleHeadings.isChecked())
1432
+ self._build.setValue("doc.boldHeadings", self.boldHeadings.isChecked())
1433
+ self._build.setValue("doc.pageHeader", self.odtPageHeader.text())
1434
+ self._build.setValue("doc.pageCountOffset", self.odtPageCountOffset.value())
1435
+
1436
+ # HTML Document
1437
+ self._build.setValue("html.addStyles", self.htmlAddStyles.isChecked())
1438
+ self._build.setValue("html.preserveTabs", self.htmlPreserveTabs.isChecked())
1439
+
1239
1440
  return
1240
1441
 
1241
1442
  ##
@@ -1334,79 +1535,21 @@ class _FormatTab(NScrollableForm):
1334
1535
  self.pageSize.setCurrentIndex(index)
1335
1536
  return
1336
1537
 
1337
-
1338
- class _OutputTab(NScrollableForm):
1339
-
1340
- def __init__(self, parent: QWidget, build: BuildSettings) -> None:
1341
- super().__init__(parent=parent)
1342
-
1343
- self._build = build
1344
-
1345
- iPx = SHARED.theme.baseIconHeight
1346
- iSz = SHARED.theme.baseIconSize
1347
- spW = 6*SHARED.theme.textNWidth
1348
-
1349
- # Open Document
1350
- self.addGroupLabel(self._build.getLabel("odt"))
1351
-
1352
- self.odtAddColours = NSwitch(self, height=iPx)
1353
- self.addRow(self._build.getLabel("odt.addColours"), self.odtAddColours)
1354
-
1355
- self.odtPageHeader = QLineEdit(self)
1356
- self.odtPageHeader.setMinimumWidth(CONFIG.pxInt(200))
1357
- self.btnPageHeader = NIconToolButton(self, iSz, "revert")
1358
- self.btnPageHeader.clicked.connect(self._resetPageHeader)
1359
- self.addRow(
1360
- self._build.getLabel("odt.pageHeader"), self.odtPageHeader,
1361
- button=self.btnPageHeader, stretch=(1, 1)
1362
- )
1363
-
1364
- self.odtPageCountOffset = NSpinBox(self)
1365
- self.odtPageCountOffset.setMinimum(0)
1366
- self.odtPageCountOffset.setMaximum(999)
1367
- self.odtPageCountOffset.setSingleStep(1)
1368
- self.odtPageCountOffset.setMinimumWidth(spW)
1369
- self.addRow(self._build.getLabel("odt.pageCountOffset"), self.odtPageCountOffset)
1370
-
1371
- # HTML Document
1372
- self.addGroupLabel(self._build.getLabel("html"))
1373
-
1374
- self.htmlAddStyles = NSwitch(self, height=iPx)
1375
- self.addRow(self._build.getLabel("html.addStyles"), self.htmlAddStyles)
1376
-
1377
- self.htmlPreserveTabs = NSwitch(self, height=iPx)
1378
- self.addRow(self._build.getLabel("html.preserveTabs"), self.htmlPreserveTabs)
1379
-
1380
- # Finalise
1381
- self.finalise()
1382
-
1383
- return
1384
-
1385
- def loadContent(self) -> None:
1386
- """Populate the widgets."""
1387
- self.odtAddColours.setChecked(self._build.getBool("odt.addColours"))
1388
- self.odtPageHeader.setText(self._build.getStr("odt.pageHeader"))
1389
- self.odtPageCountOffset.setValue(self._build.getInt("odt.pageCountOffset"))
1390
- self.htmlAddStyles.setChecked(self._build.getBool("html.addStyles"))
1391
- self.htmlPreserveTabs.setChecked(self._build.getBool("html.preserveTabs"))
1538
+ def _resetPageHeader(self) -> None:
1539
+ """Reset the ODT header format to default."""
1540
+ self.odtPageHeader.setText(nwHeadFmt.DOC_AUTO)
1392
1541
  self.odtPageHeader.setCursorPosition(0)
1393
1542
  return
1394
1543
 
1395
- def saveContent(self) -> None:
1396
- """Save choices back into build object."""
1397
- self._build.setValue("odt.addColours", self.odtAddColours.isChecked())
1398
- self._build.setValue("odt.pageHeader", self.odtPageHeader.text())
1399
- self._build.setValue("odt.pageCountOffset", self.odtPageCountOffset.value())
1400
- self._build.setValue("html.addStyles", self.htmlAddStyles.isChecked())
1401
- self._build.setValue("html.preserveTabs", self.htmlPreserveTabs.isChecked())
1402
- return
1403
-
1404
1544
  ##
1405
- # Private Slots
1545
+ # Internal Functions
1406
1546
  ##
1407
1547
 
1408
- def _resetPageHeader(self) -> None:
1409
- """Reset the ODT header format to default."""
1410
- self.odtPageHeader.setText(nwHeadFmt.ODT_AUTO)
1411
- self.odtPageHeader.setCursorPosition(0)
1548
+ def _updateIgnoredKeywords(self, keyword: str | None = None) -> None:
1549
+ """Update the ignored keywords list."""
1550
+ current = [x.lower().strip() for x in self.ignoredKeywords.text().split(",")]
1551
+ if keyword:
1552
+ current.append(keyword)
1553
+ verified = set(x for x in current if x in nwKeyWords.VALID_KEYS)
1554
+ self.ignoredKeywords.setText(", ".join(verified))
1412
1555
  return