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.
Files changed (125) hide show
  1. {novelWriter-2.3rc1.dist-info → novelWriter-2.4.dist-info}/METADATA +5 -6
  2. {novelWriter-2.3rc1.dist-info → novelWriter-2.4.dist-info}/RECORD +119 -109
  3. {novelWriter-2.3rc1.dist-info → novelWriter-2.4.dist-info}/WHEEL +1 -1
  4. novelWriter-2.4.dist-info/entry_points.txt +2 -0
  5. novelwriter/__init__.py +17 -10
  6. novelwriter/assets/i18n/nw_de_DE.qm +0 -0
  7. novelwriter/assets/i18n/nw_en_US.qm +0 -0
  8. novelwriter/assets/i18n/nw_es_419.qm +0 -0
  9. novelwriter/assets/i18n/nw_fr_FR.qm +0 -0
  10. novelwriter/assets/i18n/nw_it_IT.qm +0 -0
  11. novelwriter/assets/i18n/nw_ja_JP.qm +0 -0
  12. novelwriter/assets/i18n/nw_nb_NO.qm +0 -0
  13. novelwriter/assets/i18n/nw_nl_NL.qm +0 -0
  14. novelwriter/assets/i18n/nw_pt_BR.qm +0 -0
  15. novelwriter/assets/i18n/nw_zh_CN.qm +0 -0
  16. novelwriter/assets/i18n/project_nl_NL.json +11 -0
  17. novelwriter/assets/i18n/project_pt_BR.json +11 -0
  18. novelwriter/assets/icons/none.svg +4 -0
  19. novelwriter/assets/icons/typicons_dark/icons.conf +4 -0
  20. novelwriter/assets/icons/typicons_dark/nw_tb-mark.svg +7 -0
  21. novelwriter/assets/icons/typicons_dark/typ_refresh-flipped.svg +1 -1
  22. novelwriter/assets/icons/typicons_dark/typ_refresh.svg +1 -1
  23. novelwriter/assets/icons/typicons_dark/typ_search-grey.svg +4 -0
  24. novelwriter/assets/icons/typicons_dark/typ_times.svg +1 -1
  25. novelwriter/assets/icons/typicons_dark/typ_unfold-hidden.svg +4 -0
  26. novelwriter/assets/icons/typicons_dark/typ_unfold-visible.svg +4 -0
  27. novelwriter/assets/icons/typicons_light/icons.conf +4 -0
  28. novelwriter/assets/icons/typicons_light/nw_tb-mark.svg +7 -0
  29. novelwriter/assets/icons/typicons_light/typ_refresh-flipped.svg +1 -1
  30. novelwriter/assets/icons/typicons_light/typ_refresh.svg +1 -1
  31. novelwriter/assets/icons/typicons_light/typ_search-grey.svg +4 -0
  32. novelwriter/assets/icons/typicons_light/typ_times.svg +1 -1
  33. novelwriter/assets/icons/typicons_light/typ_unfold-hidden.svg +4 -0
  34. novelwriter/assets/icons/typicons_light/typ_unfold-visible.svg +4 -0
  35. novelwriter/assets/manual.pdf +0 -0
  36. novelwriter/assets/sample.zip +0 -0
  37. novelwriter/assets/syntax/cyberpunk_night.conf +26 -0
  38. novelwriter/assets/syntax/default_dark.conf +1 -0
  39. novelwriter/assets/syntax/default_light.conf +1 -0
  40. novelwriter/assets/syntax/grey_dark.conf +1 -0
  41. novelwriter/assets/syntax/grey_light.conf +1 -0
  42. novelwriter/assets/syntax/light_owl.conf +1 -0
  43. novelwriter/assets/syntax/night_owl.conf +1 -0
  44. novelwriter/assets/syntax/solarized_dark.conf +1 -0
  45. novelwriter/assets/syntax/solarized_light.conf +1 -0
  46. novelwriter/assets/syntax/tango.conf +23 -0
  47. novelwriter/assets/syntax/tomorrow.conf +1 -0
  48. novelwriter/assets/syntax/tomorrow_night.conf +1 -0
  49. novelwriter/assets/syntax/tomorrow_night_blue.conf +1 -0
  50. novelwriter/assets/syntax/tomorrow_night_bright.conf +1 -0
  51. novelwriter/assets/syntax/tomorrow_night_eighties.conf +1 -0
  52. novelwriter/assets/text/credits_en.htm +25 -23
  53. novelwriter/assets/themes/cyberpunk_night.conf +29 -0
  54. novelwriter/common.py +12 -4
  55. novelwriter/config.py +47 -16
  56. novelwriter/constants.py +5 -6
  57. novelwriter/core/buildsettings.py +64 -44
  58. novelwriter/core/coretools.py +97 -13
  59. novelwriter/core/docbuild.py +74 -7
  60. novelwriter/core/document.py +24 -3
  61. novelwriter/core/index.py +31 -112
  62. novelwriter/core/project.py +11 -15
  63. novelwriter/core/projectxml.py +3 -2
  64. novelwriter/core/sessions.py +2 -2
  65. novelwriter/core/spellcheck.py +3 -3
  66. novelwriter/core/status.py +6 -5
  67. novelwriter/core/storage.py +16 -6
  68. novelwriter/core/tohtml.py +22 -25
  69. novelwriter/core/tokenizer.py +417 -237
  70. novelwriter/core/tomd.py +17 -8
  71. novelwriter/core/toodt.py +386 -351
  72. novelwriter/core/tree.py +8 -8
  73. novelwriter/dialogs/about.py +10 -12
  74. novelwriter/dialogs/docmerge.py +17 -14
  75. novelwriter/dialogs/docsplit.py +20 -19
  76. novelwriter/dialogs/editlabel.py +5 -4
  77. novelwriter/dialogs/preferences.py +32 -40
  78. novelwriter/dialogs/projectsettings.py +31 -28
  79. novelwriter/dialogs/quotes.py +10 -9
  80. novelwriter/dialogs/wordlist.py +18 -15
  81. novelwriter/enum.py +17 -14
  82. novelwriter/error.py +14 -12
  83. novelwriter/extensions/circularprogress.py +12 -8
  84. novelwriter/extensions/configlayout.py +23 -3
  85. novelwriter/extensions/modified.py +51 -2
  86. novelwriter/extensions/pagedsidebar.py +16 -14
  87. novelwriter/extensions/simpleprogress.py +3 -1
  88. novelwriter/extensions/statusled.py +3 -1
  89. novelwriter/extensions/switch.py +10 -9
  90. novelwriter/extensions/switchbox.py +14 -13
  91. novelwriter/extensions/versioninfo.py +1 -1
  92. novelwriter/gui/doceditor.py +433 -496
  93. novelwriter/gui/dochighlight.py +54 -33
  94. novelwriter/gui/docviewer.py +162 -175
  95. novelwriter/gui/docviewerpanel.py +20 -37
  96. novelwriter/gui/editordocument.py +15 -4
  97. novelwriter/gui/itemdetails.py +51 -54
  98. novelwriter/gui/mainmenu.py +37 -17
  99. novelwriter/gui/noveltree.py +31 -37
  100. novelwriter/gui/outline.py +120 -98
  101. novelwriter/gui/projtree.py +114 -112
  102. novelwriter/gui/search.py +362 -0
  103. novelwriter/gui/sidebar.py +36 -45
  104. novelwriter/gui/statusbar.py +14 -14
  105. novelwriter/gui/theme.py +116 -34
  106. novelwriter/guimain.py +216 -207
  107. novelwriter/shared.py +31 -6
  108. novelwriter/text/counting.py +138 -0
  109. novelwriter/tools/dictionaries.py +15 -14
  110. novelwriter/tools/lipsum.py +20 -17
  111. novelwriter/tools/manusbuild.py +43 -35
  112. novelwriter/tools/manuscript.py +381 -104
  113. novelwriter/tools/manussettings.py +263 -125
  114. novelwriter/tools/noveldetails.py +21 -19
  115. novelwriter/tools/welcome.py +59 -57
  116. novelwriter/tools/writingstats.py +61 -55
  117. novelwriter/types.py +90 -0
  118. novelWriter-2.3rc1.dist-info/entry_points.txt +0 -5
  119. novelwriter/core/__init__.py +0 -3
  120. novelwriter/dialogs/__init__.py +0 -3
  121. novelwriter/extensions/__init__.py +0 -3
  122. novelwriter/gui/__init__.py +0 -3
  123. novelwriter/tools/__init__.py +0 -3
  124. {novelWriter-2.3rc1.dist-info → novelWriter-2.4.dist-info}/LICENSE.md +0 -0
  125. {novelWriter-2.3rc1.dist-info → novelWriter-2.4.dist-info}/top_level.txt +0 -0
@@ -28,24 +28,28 @@ import logging
28
28
  from typing import TYPE_CHECKING
29
29
 
30
30
  from PyQt5.QtGui import QFont, QIcon, QSyntaxHighlighter, QTextCharFormat, QTextDocument
31
- from PyQt5.QtCore import QEvent, QSize, Qt, pyqtSignal, pyqtSlot
31
+ from PyQt5.QtCore import QEvent, Qt, pyqtSignal, pyqtSlot
32
32
  from PyQt5.QtWidgets import (
33
33
  QAbstractButton, QAbstractItemView, QDialog, QDialogButtonBox,
34
34
  QFontDialog, QFrame, QGridLayout, QHBoxLayout, QHeaderView, QLabel,
35
35
  QLineEdit, QMenu, QPlainTextEdit, QPushButton, QSplitter, QStackedWidget,
36
- QToolButton, QTreeWidget, QTreeWidgetItem, QVBoxLayout, QWidget
36
+ QTreeWidget, QTreeWidgetItem, QVBoxLayout, QWidget
37
37
  )
38
38
 
39
39
  from novelwriter import CONFIG, SHARED
40
- from novelwriter.constants import nwHeadFmt, nwLabels, trConst
40
+ from novelwriter.constants import nwHeadFmt, nwKeyWords, nwLabels, trConst
41
41
  from novelwriter.core.buildsettings import BuildSettings, FilterMode
42
- from novelwriter.extensions.switch import NSwitch
43
- from novelwriter.extensions.modified import NComboBox, NDoubleSpinBox, NSpinBox
44
- from novelwriter.extensions.switchbox import NSwitchBox
45
42
  from novelwriter.extensions.configlayout import (
46
43
  NColourLabel, NFixedPage, NScrollableForm, NScrollablePage
47
44
  )
45
+ from novelwriter.extensions.modified import NComboBox, NDoubleSpinBox, NIconToolButton, NSpinBox
48
46
  from novelwriter.extensions.pagedsidebar import NPagedSideBar
47
+ from novelwriter.extensions.switch import NSwitch
48
+ from novelwriter.extensions.switchbox import NSwitchBox
49
+ from novelwriter.types import (
50
+ QtAlignLeft, QtDialogApply, QtDialogClose, QtDialogSave, QtRoleAccept,
51
+ QtRoleApply, QtRoleReject, QtUserRole
52
+ )
49
53
 
50
54
  if TYPE_CHECKING: # pragma: no cover
51
55
  from novelwriter.guimain import GuiMain
@@ -98,7 +102,7 @@ class GuiBuildSettings(QDialog):
98
102
  )
99
103
 
100
104
  # Settings Name
101
- self.lblBuildName = QLabel(self.tr("Name"))
105
+ self.lblBuildName = QLabel(self.tr("Name"), self)
102
106
  self.editBuildName = QLineEdit(self)
103
107
 
104
108
  # SideBar
@@ -130,11 +134,7 @@ class GuiBuildSettings(QDialog):
130
134
  self.toolStack.addWidget(self.optTabOutput)
131
135
 
132
136
  # Buttons
133
- self.buttonBox = QDialogButtonBox(
134
- QDialogButtonBox.StandardButton.Apply
135
- | QDialogButtonBox.StandardButton.Save
136
- | QDialogButtonBox.StandardButton.Close
137
- )
137
+ self.buttonBox = QDialogButtonBox(QtDialogApply | QtDialogSave | QtDialogClose, self)
138
138
  self.buttonBox.clicked.connect(self._dialogButtonClicked)
139
139
 
140
140
  # Assemble
@@ -225,12 +225,12 @@ class GuiBuildSettings(QDialog):
225
225
  def _dialogButtonClicked(self, button: QAbstractButton) -> None:
226
226
  """Handle button clicks from the dialog button box."""
227
227
  role = self.buttonBox.buttonRole(button)
228
- if role == QDialogButtonBox.ApplyRole:
228
+ if role == QtRoleApply:
229
229
  self._emitBuildData()
230
- elif role == QDialogButtonBox.AcceptRole:
230
+ elif role == QtRoleAccept:
231
231
  self._emitBuildData()
232
232
  self.close()
233
- elif role == QDialogButtonBox.RejectRole:
233
+ elif role == QtRoleReject:
234
234
  self.close()
235
235
  return
236
236
 
@@ -288,8 +288,8 @@ class _FilterTab(NFixedPage):
288
288
  C_ACTIVE = 1
289
289
  C_STATUS = 2
290
290
 
291
- D_HANDLE = Qt.ItemDataRole.UserRole
292
- D_FILE = Qt.ItemDataRole.UserRole + 1
291
+ D_HANDLE = QtUserRole
292
+ D_FILE = QtUserRole + 1
293
293
 
294
294
  F_NONE = 0
295
295
  F_FILTERED = 1
@@ -315,13 +315,13 @@ class _FilterTab(NFixedPage):
315
315
  # Project Tree
316
316
  # ============
317
317
 
318
- # Tree Settings
319
- iPx = SHARED.theme.baseIconSize
318
+ iSz = SHARED.theme.baseIconSize
319
+ iPx = SHARED.theme.baseIconHeight
320
320
  cMg = CONFIG.pxInt(6)
321
321
 
322
322
  # Tree Widget
323
323
  self.optTree = QTreeWidget(self)
324
- self.optTree.setIconSize(QSize(iPx, iPx))
324
+ self.optTree.setIconSize(iSz)
325
325
  self.optTree.setUniformRowHeights(True)
326
326
  self.optTree.setAllColumnsShowFocus(True)
327
327
  self.optTree.setHeaderHidden(True)
@@ -331,36 +331,35 @@ class _FilterTab(NFixedPage):
331
331
  treeHeader = self.optTree.header()
332
332
  treeHeader.setStretchLastSection(False)
333
333
  treeHeader.setMinimumSectionSize(iPx + cMg) # See Issue #1551
334
- treeHeader.setSectionResizeMode(self.C_NAME, QHeaderView.Stretch)
335
- treeHeader.setSectionResizeMode(self.C_ACTIVE, QHeaderView.Fixed)
336
- treeHeader.setSectionResizeMode(self.C_STATUS, QHeaderView.Fixed)
334
+ treeHeader.setSectionResizeMode(self.C_NAME, QHeaderView.ResizeMode.Stretch)
335
+ treeHeader.setSectionResizeMode(self.C_ACTIVE, QHeaderView.ResizeMode.Fixed)
336
+ treeHeader.setSectionResizeMode(self.C_STATUS, QHeaderView.ResizeMode.Fixed)
337
337
  treeHeader.resizeSection(self.C_ACTIVE, iPx + cMg)
338
338
  treeHeader.resizeSection(self.C_STATUS, iPx + cMg)
339
339
 
340
- self.optTree.setDragDropMode(QAbstractItemView.NoDragDrop)
341
- self.optTree.setSelectionMode(QAbstractItemView.ExtendedSelection)
342
- self.optTree.setSelectionBehavior(QAbstractItemView.SelectRows)
340
+ self.optTree.setDragDropMode(QAbstractItemView.DragDropMode.NoDragDrop)
341
+ self.optTree.setSelectionMode(QAbstractItemView.SelectionMode.ExtendedSelection)
342
+ self.optTree.setSelectionBehavior(QAbstractItemView.SelectionBehavior.SelectRows)
343
343
 
344
344
  # Filters
345
345
  # =======
346
346
 
347
- self.includedButton = QToolButton(self)
347
+ self.includedButton = NIconToolButton(self, iSz)
348
348
  self.includedButton.setToolTip(self.tr("Always included"))
349
349
  self.includedButton.setIcon(self._statusFlags[self.F_INCLUDED])
350
350
  self.includedButton.clicked.connect(lambda: self._setSelectedMode(self.F_INCLUDED))
351
351
 
352
- self.excludedButton = QToolButton(self)
352
+ self.excludedButton = NIconToolButton(self, iSz)
353
353
  self.excludedButton.setToolTip(self.tr("Always excluded"))
354
354
  self.excludedButton.setIcon(self._statusFlags[self.F_EXCLUDED])
355
355
  self.excludedButton.clicked.connect(lambda: self._setSelectedMode(self.F_EXCLUDED))
356
356
 
357
- self.resetButton = QToolButton(self)
357
+ self.resetButton = NIconToolButton(self, iSz, "revert")
358
358
  self.resetButton.setToolTip(self.tr("Reset to default"))
359
- self.resetButton.setIcon(SHARED.theme.getIcon("revert"))
360
359
  self.resetButton.clicked.connect(lambda: self._setSelectedMode(self.F_FILTERED))
361
360
 
362
361
  self.modeBox = QHBoxLayout()
363
- self.modeBox.addWidget(QLabel(self.tr("Mark selection as")))
362
+ self.modeBox.addWidget(QLabel(self.tr("Mark selection as"), self))
364
363
  self.modeBox.addStretch(1)
365
364
  self.modeBox.addWidget(self.includedButton)
366
365
  self.modeBox.addWidget(self.excludedButton)
@@ -370,7 +369,7 @@ class _FilterTab(NFixedPage):
370
369
  # Filer Options
371
370
  self.filterOpt = NSwitchBox(self, iPx)
372
371
  self.filterOpt.switchToggled.connect(self._applyFilterSwitch)
373
- self.filterOpt.setFrameStyle(QFrame.NoFrame)
372
+ self.filterOpt.setFrameStyle(QFrame.Shape.NoFrame)
374
373
 
375
374
  # Assemble GUI
376
375
  # ============
@@ -382,10 +381,10 @@ class _FilterTab(NFixedPage):
382
381
  self.selectionBox.addLayout(self.modeBox)
383
382
  self.selectionBox.setContentsMargins(0, 0, 0, 0)
384
383
 
385
- self.selectionWidget = QWidget()
384
+ self.selectionWidget = QWidget(self)
386
385
  self.selectionWidget.setLayout(self.selectionBox)
387
386
 
388
- self.mainSplit = QSplitter()
387
+ self.mainSplit = QSplitter(self)
389
388
  self.mainSplit.addWidget(self.selectionWidget)
390
389
  self.mainSplit.addWidget(self.filterOpt)
391
390
  self.mainSplit.setCollapsible(0, False)
@@ -469,7 +468,7 @@ class _FilterTab(NFixedPage):
469
468
  trItem.setData(self.C_DATA, self.D_FILE, isFile)
470
469
  trItem.setIcon(self.C_ACTIVE, SHARED.theme.getIcon(iconName))
471
470
 
472
- trItem.setTextAlignment(self.C_NAME, Qt.AlignLeft)
471
+ trItem.setTextAlignment(self.C_NAME, QtAlignLeft)
473
472
 
474
473
  if pHandle is None and nwItem.isRootType():
475
474
  self.optTree.addTopLevelItem(trItem)
@@ -584,7 +583,8 @@ class _HeadingsTab(NScrollablePage):
584
583
  EDIT_CHAPTER = 2
585
584
  EDIT_UNNUM = 3
586
585
  EDIT_SCENE = 4
587
- EDIT_SECTION = 5
586
+ EDIT_HSCENE = 5
587
+ EDIT_SECTION = 6
588
588
 
589
589
  def __init__(self, buildMain: GuiBuildSettings, build: BuildSettings) -> None:
590
590
  super().__init__(parent=buildMain)
@@ -592,123 +592,120 @@ class _HeadingsTab(NScrollablePage):
592
592
  self._build = build
593
593
  self._editing = 0
594
594
 
595
- iPx = SHARED.theme.baseIconSize
595
+ iPx = SHARED.theme.baseIconHeight
596
+ iSz = SHARED.theme.baseIconSize
597
+ sSp = CONFIG.pxInt(16)
596
598
  vSp = CONFIG.pxInt(12)
597
599
  bSp = CONFIG.pxInt(6)
600
+ trHide = self.tr("Hide")
598
601
 
599
602
  # Format Boxes
600
603
  # ============
601
604
  self.formatBox = QGridLayout()
602
- self.formatBox.setHorizontalSpacing(vSp)
605
+ self.formatBox.setHorizontalSpacing(bSp)
603
606
 
604
607
  # Title Heading
605
- self.lblTitle = QLabel(self._build.getLabel("headings.fmtTitle"))
608
+ self.lblTitle = QLabel(self._build.getLabel("headings.fmtTitle"), self)
606
609
  self.fmtTitle = QLineEdit("", self)
607
610
  self.fmtTitle.setReadOnly(True)
608
- self.btnTitle = QToolButton(self)
609
- self.btnTitle.setIcon(SHARED.theme.getIcon("edit"))
611
+ self.btnTitle = NIconToolButton(self, iSz, "edit")
610
612
  self.btnTitle.clicked.connect(lambda: self._editHeading(self.EDIT_TITLE))
613
+ self.hdeTitle = QLabel(trHide, self)
614
+ self.hdeTitle.setIndent(bSp)
615
+ self.swtTitle = NSwitch(self, height=iPx)
611
616
 
612
- wrapTitle = QHBoxLayout()
613
- wrapTitle.addWidget(self.fmtTitle)
614
- wrapTitle.addWidget(self.btnTitle)
615
- wrapTitle.setSpacing(bSp)
616
-
617
- self.formatBox.addWidget(self.lblTitle, 0, 0, Qt.AlignLeft)
618
- self.formatBox.addLayout(wrapTitle, 0, 1, Qt.AlignLeft)
617
+ self.formatBox.addWidget(self.lblTitle, 0, 0)
618
+ self.formatBox.addWidget(self.fmtTitle, 0, 1)
619
+ self.formatBox.addWidget(self.btnTitle, 0, 2)
620
+ self.formatBox.addWidget(self.hdeTitle, 0, 3)
621
+ self.formatBox.addWidget(self.swtTitle, 0, 4)
619
622
 
620
623
  # Chapter Heading
621
- self.lblChapter = QLabel(self._build.getLabel("headings.fmtChapter"))
624
+ self.lblChapter = QLabel(self._build.getLabel("headings.fmtChapter"), self)
622
625
  self.fmtChapter = QLineEdit("", self)
623
626
  self.fmtChapter.setReadOnly(True)
624
- self.btnChapter = QToolButton(self)
625
- self.btnChapter.setIcon(SHARED.theme.getIcon("edit"))
627
+ self.btnChapter = NIconToolButton(self, iSz, "edit")
626
628
  self.btnChapter.clicked.connect(lambda: self._editHeading(self.EDIT_CHAPTER))
629
+ self.hdeChapter = QLabel(trHide, self)
630
+ self.hdeChapter.setIndent(bSp)
631
+ self.swtChapter = NSwitch(self, height=iPx)
627
632
 
628
- wrapChapter = QHBoxLayout()
629
- wrapChapter.addWidget(self.fmtChapter)
630
- wrapChapter.addWidget(self.btnChapter)
631
- wrapChapter.setSpacing(bSp)
632
-
633
- self.formatBox.addWidget(self.lblChapter, 1, 0, Qt.AlignLeft)
634
- self.formatBox.addLayout(wrapChapter, 1, 1, Qt.AlignLeft)
633
+ self.formatBox.addWidget(self.lblChapter, 1, 0)
634
+ self.formatBox.addWidget(self.fmtChapter, 1, 1)
635
+ self.formatBox.addWidget(self.btnChapter, 1, 2)
636
+ self.formatBox.addWidget(self.hdeChapter, 1, 3)
637
+ self.formatBox.addWidget(self.swtChapter, 1, 4)
635
638
 
636
639
  # Unnumbered Chapter Heading
637
- self.lblUnnumbered = QLabel(self._build.getLabel("headings.fmtUnnumbered"))
640
+ self.lblUnnumbered = QLabel(self._build.getLabel("headings.fmtUnnumbered"), self)
638
641
  self.fmtUnnumbered = QLineEdit("", self)
639
642
  self.fmtUnnumbered.setReadOnly(True)
640
- self.btnUnnumbered = QToolButton(self)
641
- self.btnUnnumbered.setIcon(SHARED.theme.getIcon("edit"))
643
+ self.btnUnnumbered = NIconToolButton(self, iSz, "edit")
642
644
  self.btnUnnumbered.clicked.connect(lambda: self._editHeading(self.EDIT_UNNUM))
645
+ self.hdeUnnumbered = QLabel(trHide, self)
646
+ self.hdeUnnumbered.setIndent(bSp)
647
+ self.swtUnnumbered = NSwitch(self, height=iPx)
643
648
 
644
- wrapUnnumbered = QHBoxLayout()
645
- wrapUnnumbered.addWidget(self.fmtUnnumbered)
646
- wrapUnnumbered.addWidget(self.btnUnnumbered)
647
- wrapUnnumbered.setSpacing(bSp)
648
-
649
- self.formatBox.addWidget(self.lblUnnumbered, 2, 0, Qt.AlignLeft)
650
- self.formatBox.addLayout(wrapUnnumbered, 2, 1, Qt.AlignLeft)
649
+ self.formatBox.addWidget(self.lblUnnumbered, 2, 0)
650
+ self.formatBox.addWidget(self.fmtUnnumbered, 2, 1)
651
+ self.formatBox.addWidget(self.btnUnnumbered, 2, 2)
652
+ self.formatBox.addWidget(self.hdeUnnumbered, 2, 3)
653
+ self.formatBox.addWidget(self.swtUnnumbered, 2, 4)
651
654
 
652
655
  # Scene Heading
653
- sceneHideTip = self._build.getLabel("headings.hideScene")
654
- self.lblScene = QLabel(self._build.getLabel("headings.fmtScene"))
656
+ self.lblScene = QLabel(self._build.getLabel("headings.fmtScene"), self)
655
657
  self.fmtScene = QLineEdit("", self)
656
658
  self.fmtScene.setReadOnly(True)
657
- self.btnScene = QToolButton(self)
658
- self.btnScene.setIcon(SHARED.theme.getIcon("edit"))
659
+ self.btnScene = NIconToolButton(self, iSz, "edit")
659
660
  self.btnScene.clicked.connect(lambda: self._editHeading(self.EDIT_SCENE))
660
- self.hdeScene = QLabel(self.tr("Hide"))
661
- self.hdeScene.setToolTip(sceneHideTip)
661
+ self.hdeScene = QLabel(trHide, self)
662
+ self.hdeScene.setIndent(bSp)
662
663
  self.swtScene = NSwitch(self, height=iPx)
663
- self.swtScene.setToolTip(sceneHideTip)
664
-
665
- wrapScene = QHBoxLayout()
666
- wrapScene.addWidget(self.fmtScene)
667
- wrapScene.addWidget(self.btnScene)
668
- wrapScene.setSpacing(bSp)
669
664
 
670
- wrapSceneHide = QHBoxLayout()
671
- wrapSceneHide.addWidget(self.hdeScene)
672
- wrapSceneHide.addWidget(self.swtScene)
673
- wrapSceneHide.setSpacing(bSp)
674
-
675
- self.formatBox.addWidget(self.lblScene, 3, 0, Qt.AlignLeft)
676
- self.formatBox.addLayout(wrapScene, 3, 1, Qt.AlignLeft)
677
- self.formatBox.addLayout(wrapSceneHide, 3, 2, Qt.AlignLeft)
665
+ self.formatBox.addWidget(self.lblScene, 3, 0)
666
+ self.formatBox.addWidget(self.fmtScene, 3, 1)
667
+ self.formatBox.addWidget(self.btnScene, 3, 2)
668
+ self.formatBox.addWidget(self.hdeScene, 3, 3)
669
+ self.formatBox.addWidget(self.swtScene, 3, 4)
670
+
671
+ # Alt Scene Heading
672
+ self.lblAScene = QLabel(self._build.getLabel("headings.fmtAltScene"), self)
673
+ self.fmtAScene = QLineEdit("", self)
674
+ self.fmtAScene.setReadOnly(True)
675
+ self.btnAScene = NIconToolButton(self, iSz, "edit")
676
+ self.btnAScene.clicked.connect(lambda: self._editHeading(self.EDIT_HSCENE))
677
+ self.hdeAScene = QLabel(trHide, self)
678
+ self.hdeAScene.setIndent(bSp)
679
+ self.swtAScene = NSwitch(self, height=iPx)
680
+
681
+ self.formatBox.addWidget(self.lblAScene, 4, 0)
682
+ self.formatBox.addWidget(self.fmtAScene, 4, 1)
683
+ self.formatBox.addWidget(self.btnAScene, 4, 2)
684
+ self.formatBox.addWidget(self.hdeAScene, 4, 3)
685
+ self.formatBox.addWidget(self.swtAScene, 4, 4)
678
686
 
679
687
  # Section Heading
680
- sectionHideTip = self._build.getLabel("headings.hideSection")
681
- self.lblSection = QLabel(self._build.getLabel("headings.fmtSection"))
688
+ self.lblSection = QLabel(self._build.getLabel("headings.fmtSection"), self)
682
689
  self.fmtSection = QLineEdit("", self)
683
690
  self.fmtSection.setReadOnly(True)
684
- self.btnSection = QToolButton(self)
685
- self.btnSection.setIcon(SHARED.theme.getIcon("edit"))
691
+ self.btnSection = NIconToolButton(self, iSz, "edit")
686
692
  self.btnSection.clicked.connect(lambda: self._editHeading(self.EDIT_SECTION))
687
- self.hdeSection = QLabel(self.tr("Hide"))
688
- self.hdeSection.setToolTip(sectionHideTip)
693
+ self.hdeSection = QLabel(trHide, self)
694
+ self.hdeSection.setIndent(bSp)
689
695
  self.swtSection = NSwitch(self, height=iPx)
690
- self.swtSection.setToolTip(sectionHideTip)
691
-
692
- wrapSection = QHBoxLayout()
693
- wrapSection.addWidget(self.fmtSection)
694
- wrapSection.addWidget(self.btnSection)
695
- wrapSection.setSpacing(bSp)
696
-
697
- wrapSectionHide = QHBoxLayout()
698
- wrapSectionHide.addWidget(self.hdeSection)
699
- wrapSectionHide.addWidget(self.swtSection)
700
- wrapSectionHide.setSpacing(bSp)
701
696
 
702
- self.formatBox.addWidget(self.lblSection, 4, 0, Qt.AlignLeft)
703
- self.formatBox.addLayout(wrapSection, 4, 1, Qt.AlignLeft)
704
- self.formatBox.addLayout(wrapSectionHide, 4, 2, Qt.AlignLeft)
697
+ self.formatBox.addWidget(self.lblSection, 5, 0)
698
+ self.formatBox.addWidget(self.fmtSection, 5, 1)
699
+ self.formatBox.addWidget(self.btnSection, 5, 2)
700
+ self.formatBox.addWidget(self.hdeSection, 5, 3)
701
+ self.formatBox.addWidget(self.swtSection, 5, 4)
705
702
 
706
703
  # Edit Form
707
704
  # =========
708
705
 
709
- self.lblEditForm = QLabel(self.tr("Editing: {0}").format(self.tr("None")))
706
+ self.lblEditForm = QLabel(self.tr("Editing: {0}").format(self.tr("None")), self)
710
707
 
711
- self.editTextBox = QPlainTextEdit()
708
+ self.editTextBox = QPlainTextEdit(self)
712
709
  self.editTextBox.setFixedHeight(5*iPx)
713
710
  self.editTextBox.setEnabled(False)
714
711
 
@@ -735,10 +732,10 @@ class _HeadingsTab(NScrollablePage):
735
732
  self.aInsCharPOV.triggered.connect(lambda: self._insertIntoForm(nwHeadFmt.CHAR_POV))
736
733
  self.aInsCharFocus.triggered.connect(lambda: self._insertIntoForm(nwHeadFmt.CHAR_FOCUS))
737
734
 
738
- self.btnInsert = QPushButton(self.tr("Insert"))
735
+ self.btnInsert = QPushButton(self.tr("Insert"), self)
739
736
  self.btnInsert.setMenu(self.menuInsert)
740
737
 
741
- self.btnApply = QPushButton(self.tr("Apply"))
738
+ self.btnApply = QPushButton(self.tr("Apply"), self)
742
739
  self.btnApply.clicked.connect(self._saveFormat)
743
740
 
744
741
  self.formButtonBox = QHBoxLayout()
@@ -751,13 +748,72 @@ class _HeadingsTab(NScrollablePage):
751
748
  self.editFormBox.addWidget(self.editTextBox)
752
749
  self.editFormBox.addLayout(self.formButtonBox)
753
750
 
751
+ # Layout Matrix
752
+ # =============
753
+ self.layoutMatrix = QGridLayout()
754
+ self.layoutMatrix.setVerticalSpacing(vSp)
755
+ self.layoutMatrix.setHorizontalSpacing(vSp)
756
+
757
+ # Heading
758
+ self.layoutHeading = QLabel("<b>{0}</b>".format(self.tr("Additional Styling")), self)
759
+ self.layoutMatrix.addWidget(self.layoutHeading, 0, 0, 1, 5)
760
+
761
+ # Title Layout
762
+ self.mtxTitle = QLabel(self._build.getLabel("headings.fmtTitle"), self)
763
+ self.centerTitle = NSwitch(self, height=iPx)
764
+ self.breakTitle = NSwitch(self, height=iPx)
765
+ lblCenterT = QLabel(self.tr("Centre"), self)
766
+ lblCenterT.setIndent(sSp)
767
+ lblBreakT = QLabel(self.tr("Page Break"), self)
768
+ lblBreakT.setIndent(sSp)
769
+
770
+ self.layoutMatrix.addWidget(self.mtxTitle, 1, 0)
771
+ self.layoutMatrix.addWidget(lblCenterT, 1, 1)
772
+ self.layoutMatrix.addWidget(self.centerTitle, 1, 2)
773
+ self.layoutMatrix.addWidget(lblBreakT, 1, 3)
774
+ self.layoutMatrix.addWidget(self.breakTitle, 1, 4)
775
+
776
+ # Chapter Layout
777
+ self.mtxChapter = QLabel(self._build.getLabel("headings.fmtChapter"), self)
778
+ self.centerChapter = NSwitch(self, height=iPx)
779
+ self.breakChapter = NSwitch(self, height=iPx)
780
+ lblCenterC = QLabel(self.tr("Centre"), self)
781
+ lblCenterC.setIndent(sSp)
782
+ lblBreakC = QLabel(self.tr("Page Break"), self)
783
+ lblBreakC.setIndent(sSp)
784
+
785
+ self.layoutMatrix.addWidget(self.mtxChapter, 2, 0)
786
+ self.layoutMatrix.addWidget(lblCenterC, 2, 1)
787
+ self.layoutMatrix.addWidget(self.centerChapter, 2, 2)
788
+ self.layoutMatrix.addWidget(lblBreakC, 2, 3)
789
+ self.layoutMatrix.addWidget(self.breakChapter, 2, 4)
790
+
791
+ # Scene Layout
792
+ self.mtxScene = QLabel(self._build.getLabel("headings.fmtScene"), self)
793
+ self.centerScene = NSwitch(self, height=iPx)
794
+ self.breakScene = NSwitch(self, height=iPx)
795
+ lblCenterS = QLabel(self.tr("Centre"), self)
796
+ lblCenterS.setIndent(sSp)
797
+ lblBreakS = QLabel(self.tr("Page Break"), self)
798
+ lblBreakS.setIndent(sSp)
799
+
800
+ self.layoutMatrix.addWidget(self.mtxScene, 3, 0)
801
+ self.layoutMatrix.addWidget(lblCenterS, 3, 1)
802
+ self.layoutMatrix.addWidget(self.centerScene, 3, 2)
803
+ self.layoutMatrix.addWidget(lblBreakS, 3, 3)
804
+ self.layoutMatrix.addWidget(self.breakScene, 3, 4)
805
+
806
+ self.layoutMatrix.setColumnStretch(5, 1)
807
+
754
808
  # Assemble
755
809
  # ========
756
810
 
757
811
  self.outerBox = QVBoxLayout()
758
812
  self.outerBox.addLayout(self.formatBox)
759
- self.outerBox.addSpacing(CONFIG.pxInt(16))
813
+ self.outerBox.addSpacing(sSp)
760
814
  self.outerBox.addLayout(self.editFormBox)
815
+ self.outerBox.addSpacing(sSp)
816
+ self.outerBox.addLayout(self.layoutMatrix)
761
817
  self.outerBox.addStretch(1)
762
818
 
763
819
  self.setCentralLayout(self.outerBox)
@@ -770,15 +826,39 @@ class _HeadingsTab(NScrollablePage):
770
826
  self.fmtChapter.setText(self._build.getStr("headings.fmtChapter"))
771
827
  self.fmtUnnumbered.setText(self._build.getStr("headings.fmtUnnumbered"))
772
828
  self.fmtScene.setText(self._build.getStr("headings.fmtScene"))
829
+ self.fmtAScene.setText(self._build.getStr("headings.fmtAltScene"))
773
830
  self.fmtSection.setText(self._build.getStr("headings.fmtSection"))
831
+
832
+ self.swtTitle.setChecked(self._build.getBool("headings.hideTitle"))
833
+ self.swtChapter.setChecked(self._build.getBool("headings.hideChapter"))
834
+ self.swtUnnumbered.setChecked(self._build.getBool("headings.hideUnnumbered"))
774
835
  self.swtScene.setChecked(self._build.getBool("headings.hideScene"))
836
+ self.swtAScene.setChecked(self._build.getBool("headings.hideAltScene"))
775
837
  self.swtSection.setChecked(self._build.getBool("headings.hideSection"))
838
+
839
+ self.centerTitle.setChecked(self._build.getBool("headings.centerTitle"))
840
+ self.centerChapter.setChecked(self._build.getBool("headings.centerChapter"))
841
+ self.centerScene.setChecked(self._build.getBool("headings.centerScene"))
842
+ self.breakTitle.setChecked(self._build.getBool("headings.breakTitle"))
843
+ self.breakChapter.setChecked(self._build.getBool("headings.breakChapter"))
844
+ self.breakScene.setChecked(self._build.getBool("headings.breakScene"))
776
845
  return
777
846
 
778
847
  def saveContent(self) -> None:
779
848
  """Save choices back into build object."""
849
+ self._build.setValue("headings.hideTitle", self.swtTitle.isChecked())
850
+ self._build.setValue("headings.hideChapter", self.swtChapter.isChecked())
851
+ self._build.setValue("headings.hideUnnumbered", self.swtUnnumbered.isChecked())
780
852
  self._build.setValue("headings.hideScene", self.swtScene.isChecked())
853
+ self._build.setValue("headings.hideAltScene", self.swtAScene.isChecked())
781
854
  self._build.setValue("headings.hideSection", self.swtSection.isChecked())
855
+
856
+ self._build.setValue("headings.centerTitle", self.centerTitle.isChecked())
857
+ self._build.setValue("headings.centerChapter", self.centerChapter.isChecked())
858
+ self._build.setValue("headings.centerScene", self.centerScene.isChecked())
859
+ self._build.setValue("headings.breakTitle", self.breakTitle.isChecked())
860
+ self._build.setValue("headings.breakChapter", self.breakChapter.isChecked())
861
+ self._build.setValue("headings.breakScene", self.breakScene.isChecked())
782
862
  return
783
863
 
784
864
  ##
@@ -809,6 +889,9 @@ class _HeadingsTab(NScrollablePage):
809
889
  elif heading == self.EDIT_SCENE:
810
890
  text = self.fmtScene.text()
811
891
  label = self._build.getLabel("headings.fmtScene")
892
+ elif heading == self.EDIT_HSCENE:
893
+ text = self.fmtAScene.text()
894
+ label = self._build.getLabel("headings.fmtAltScene")
812
895
  elif heading == self.EDIT_SECTION:
813
896
  text = self.fmtSection.text()
814
897
  label = self._build.getLabel("headings.fmtSection")
@@ -844,6 +927,9 @@ class _HeadingsTab(NScrollablePage):
844
927
  elif heading == self.EDIT_SCENE:
845
928
  self.fmtScene.setText(text)
846
929
  self._build.setValue("headings.fmtScene", text)
930
+ elif heading == self.EDIT_HSCENE:
931
+ self.fmtAScene.setText(text)
932
+ self._build.setValue("headings.fmtAltScene", text)
847
933
  elif heading == self.EDIT_SECTION:
848
934
  self.fmtSection.setText(text)
849
935
  self._build.setValue("headings.fmtSection", text)
@@ -891,19 +977,34 @@ class _ContentTab(NScrollableForm):
891
977
 
892
978
  self._build = build
893
979
 
894
- iPx = SHARED.theme.baseIconSize
980
+ iPx = SHARED.theme.baseIconHeight
981
+ iSz = SHARED.theme.baseIconSize
895
982
 
896
983
  # Text Content
984
+ self.incBodyText = NSwitch(self, height=iPx)
897
985
  self.incSynopsis = NSwitch(self, height=iPx)
898
986
  self.incComments = NSwitch(self, height=iPx)
899
987
  self.incKeywords = NSwitch(self, height=iPx)
900
- self.incBodyText = NSwitch(self, height=iPx)
988
+
989
+ self.ignoredKeywords = QLineEdit(self)
990
+
991
+ self.mnKeywords = QMenu(self)
992
+ for keyword in nwKeyWords.VALID_KEYS:
993
+ self.mnKeywords.addAction(
994
+ trConst(nwLabels.KEY_NAME[keyword]),
995
+ lambda keyword=keyword: self._updateIgnoredKeywords(keyword)
996
+ )
997
+
998
+ self.ignoredKeywordsButton = NIconToolButton(self, iSz, "add")
999
+ self.ignoredKeywordsButton.setMenu(self.mnKeywords)
901
1000
 
902
1001
  self.addGroupLabel(self._build.getLabel("text.grpContent"))
1002
+ self.addRow(self._build.getLabel("text.includeBodyText"), self.incBodyText)
903
1003
  self.addRow(self._build.getLabel("text.includeSynopsis"), self.incSynopsis)
904
1004
  self.addRow(self._build.getLabel("text.includeComments"), self.incComments)
905
1005
  self.addRow(self._build.getLabel("text.includeKeywords"), self.incKeywords)
906
- self.addRow(self._build.getLabel("text.includeBodyText"), self.incBodyText)
1006
+ self.addRow(self._build.getLabel("text.ignoredKeywords"), self.ignoredKeywords,
1007
+ button=self.ignoredKeywordsButton, stretch=(1, 1))
907
1008
 
908
1009
  # Insert Content
909
1010
  self.addNoteHead = NSwitch(self, height=iPx)
@@ -918,22 +1019,39 @@ class _ContentTab(NScrollableForm):
918
1019
 
919
1020
  def loadContent(self) -> None:
920
1021
  """Populate the widgets."""
1022
+ self.incBodyText.setChecked(self._build.getBool("text.includeBodyText"))
921
1023
  self.incSynopsis.setChecked(self._build.getBool("text.includeSynopsis"))
922
1024
  self.incComments.setChecked(self._build.getBool("text.includeComments"))
923
1025
  self.incKeywords.setChecked(self._build.getBool("text.includeKeywords"))
924
- self.incBodyText.setChecked(self._build.getBool("text.includeBodyText"))
1026
+ self.ignoredKeywords.setText(self._build.getStr("text.ignoredKeywords"))
925
1027
  self.addNoteHead.setChecked(self._build.getBool("text.addNoteHeadings"))
1028
+ self._updateIgnoredKeywords()
926
1029
  return
927
1030
 
928
1031
  def saveContent(self) -> None:
929
1032
  """Save choices back into build object."""
1033
+ self._updateIgnoredKeywords()
1034
+ self._build.setValue("text.includeBodyText", self.incBodyText.isChecked())
930
1035
  self._build.setValue("text.includeSynopsis", self.incSynopsis.isChecked())
931
1036
  self._build.setValue("text.includeComments", self.incComments.isChecked())
932
1037
  self._build.setValue("text.includeKeywords", self.incKeywords.isChecked())
933
- self._build.setValue("text.includeBodyText", self.incBodyText.isChecked())
1038
+ self._build.setValue("text.ignoredKeywords", self.ignoredKeywords.text())
934
1039
  self._build.setValue("text.addNoteHeadings", self.addNoteHead.isChecked())
935
1040
  return
936
1041
 
1042
+ ##
1043
+ # Internal Functions
1044
+ ##
1045
+
1046
+ def _updateIgnoredKeywords(self, keyword: str | None = None) -> None:
1047
+ """Update the ignored keywords list."""
1048
+ current = [x.lower().strip() for x in self.ignoredKeywords.text().split(",")]
1049
+ if keyword:
1050
+ current.append(keyword)
1051
+ verified = set(x for x in current if x in nwKeyWords.VALID_KEYS)
1052
+ self.ignoredKeywords.setText(", ".join(verified))
1053
+ return
1054
+
937
1055
  # END Class _ContentTab
938
1056
 
939
1057
 
@@ -947,7 +1065,8 @@ class _FormatTab(NScrollableForm):
947
1065
  self._build = build
948
1066
  self._unitScale = 1.0
949
1067
 
950
- iPx = SHARED.theme.baseIconSize
1068
+ iPx = SHARED.theme.baseIconHeight
1069
+ iSz = SHARED.theme.baseIconSize
951
1070
  spW = 6*SHARED.theme.textNWidth
952
1071
  dbW = 8*SHARED.theme.textNWidth
953
1072
 
@@ -959,8 +1078,7 @@ class _FormatTab(NScrollableForm):
959
1078
  # Font Family
960
1079
  self.textFont = QLineEdit(self)
961
1080
  self.textFont.setReadOnly(True)
962
- self.btnTextFont = QPushButton("...")
963
- self.btnTextFont.setMaximumWidth(int(2.5*SHARED.theme.getTextWidth("...")))
1081
+ self.btnTextFont = NIconToolButton(self, iSz, "more")
964
1082
  self.btnTextFont.clicked.connect(self._selectFont)
965
1083
  self.addRow(
966
1084
  self._build.getLabel("format.textFont"), self.textFont,
@@ -1194,7 +1312,7 @@ class _FormatTab(NScrollableForm):
1194
1312
  return
1195
1313
 
1196
1314
  @pyqtSlot()
1197
- def _pageSizeValueChanged(self):
1315
+ def _pageSizeValueChanged(self) -> None:
1198
1316
  """The user has changed the page size spin boxes, so we flip
1199
1317
  the page size box to Custom.
1200
1318
  """
@@ -1213,7 +1331,8 @@ class _OutputTab(NScrollableForm):
1213
1331
 
1214
1332
  self._build = build
1215
1333
 
1216
- iPx = SHARED.theme.baseIconSize
1334
+ iPx = SHARED.theme.baseIconHeight
1335
+ iSz = SHARED.theme.baseIconSize
1217
1336
  spW = 6*SHARED.theme.textNWidth
1218
1337
 
1219
1338
  # Open Document
@@ -1224,8 +1343,7 @@ class _OutputTab(NScrollableForm):
1224
1343
 
1225
1344
  self.odtPageHeader = QLineEdit(self)
1226
1345
  self.odtPageHeader.setMinimumWidth(CONFIG.pxInt(200))
1227
- self.btnPageHeader = QToolButton(self)
1228
- self.btnPageHeader.setIcon(SHARED.theme.getIcon("revert"))
1346
+ self.btnPageHeader = NIconToolButton(self, iSz, "revert")
1229
1347
  self.btnPageHeader.clicked.connect(self._resetPageHeader)
1230
1348
  self.addRow(
1231
1349
  self._build.getLabel("odt.pageHeader"), self.odtPageHeader,
@@ -1239,12 +1357,24 @@ class _OutputTab(NScrollableForm):
1239
1357
  self.odtPageCountOffset.setMinimumWidth(spW)
1240
1358
  self.addRow(self._build.getLabel("odt.pageCountOffset"), self.odtPageCountOffset)
1241
1359
 
1360
+ self.odtFirstLineIndent = NSwitch(self, height=iPx)
1361
+ self.addRow(self._build.getLabel("odt.firstLineIndent"), self.odtFirstLineIndent)
1362
+
1242
1363
  # HTML Document
1243
1364
  self.addGroupLabel(self._build.getLabel("html"))
1244
1365
 
1245
1366
  self.htmlAddStyles = NSwitch(self, height=iPx)
1246
1367
  self.addRow(self._build.getLabel("html.addStyles"), self.htmlAddStyles)
1247
1368
 
1369
+ self.htmlPreserveTabs = NSwitch(self, height=iPx)
1370
+ self.addRow(self._build.getLabel("html.preserveTabs"), self.htmlPreserveTabs)
1371
+
1372
+ # Markdown Document
1373
+ self.addGroupLabel(self._build.getLabel("md"))
1374
+
1375
+ self.mdPreserveBreaks = NSwitch(self, height=iPx)
1376
+ self.addRow(self._build.getLabel("md.preserveBreaks"), self.mdPreserveBreaks)
1377
+
1248
1378
  # Finalise
1249
1379
  self.finalise()
1250
1380
 
@@ -1255,7 +1385,11 @@ class _OutputTab(NScrollableForm):
1255
1385
  self.odtAddColours.setChecked(self._build.getBool("odt.addColours"))
1256
1386
  self.odtPageHeader.setText(self._build.getStr("odt.pageHeader"))
1257
1387
  self.odtPageCountOffset.setValue(self._build.getInt("odt.pageCountOffset"))
1388
+ self.odtFirstLineIndent.setChecked(self._build.getBool("odt.firstLineIndent"))
1258
1389
  self.htmlAddStyles.setChecked(self._build.getBool("html.addStyles"))
1390
+ self.htmlPreserveTabs.setChecked(self._build.getBool("html.preserveTabs"))
1391
+ self.mdPreserveBreaks.setChecked(self._build.getBool("md.preserveBreaks"))
1392
+ self.odtPageHeader.setCursorPosition(0)
1259
1393
  return
1260
1394
 
1261
1395
  def saveContent(self) -> None:
@@ -1263,7 +1397,10 @@ class _OutputTab(NScrollableForm):
1263
1397
  self._build.setValue("odt.addColours", self.odtAddColours.isChecked())
1264
1398
  self._build.setValue("odt.pageHeader", self.odtPageHeader.text())
1265
1399
  self._build.setValue("odt.pageCountOffset", self.odtPageCountOffset.value())
1400
+ self._build.setValue("odt.firstLineIndent", self.odtFirstLineIndent.isChecked())
1266
1401
  self._build.setValue("html.addStyles", self.htmlAddStyles.isChecked())
1402
+ self._build.setValue("html.preserveTabs", self.htmlPreserveTabs.isChecked())
1403
+ self._build.setValue("md.preserveBreaks", self.mdPreserveBreaks.isChecked())
1267
1404
  return
1268
1405
 
1269
1406
  ##
@@ -1273,6 +1410,7 @@ class _OutputTab(NScrollableForm):
1273
1410
  def _resetPageHeader(self) -> None:
1274
1411
  """Reset the ODT header format to default."""
1275
1412
  self.odtPageHeader.setText(nwHeadFmt.ODT_AUTO)
1413
+ self.odtPageHeader.setCursorPosition(0)
1276
1414
  return
1277
1415
 
1278
1416
  # END Class _OutputTab