novelWriter 2.6b2__py3-none-any.whl → 2.6.1__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 (107) hide show
  1. {novelWriter-2.6b2.dist-info → novelWriter-2.6.1.dist-info}/METADATA +2 -2
  2. {novelWriter-2.6b2.dist-info → novelWriter-2.6.1.dist-info}/RECORD +107 -106
  3. {novelWriter-2.6b2.dist-info → novelWriter-2.6.1.dist-info}/WHEEL +1 -1
  4. novelwriter/__init__.py +4 -4
  5. novelwriter/assets/i18n/nw_de_DE.qm +0 -0
  6. novelwriter/assets/i18n/nw_en_US.qm +0 -0
  7. novelwriter/assets/i18n/nw_es_419.qm +0 -0
  8. novelwriter/assets/i18n/nw_fr_FR.qm +0 -0
  9. novelwriter/assets/i18n/nw_it_IT.qm +0 -0
  10. novelwriter/assets/i18n/nw_ja_JP.qm +0 -0
  11. novelwriter/assets/i18n/nw_nb_NO.qm +0 -0
  12. novelwriter/assets/i18n/nw_nl_NL.qm +0 -0
  13. novelwriter/assets/i18n/nw_pl_PL.qm +0 -0
  14. novelwriter/assets/i18n/nw_pt_BR.qm +0 -0
  15. novelwriter/assets/i18n/nw_ru_RU.qm +0 -0
  16. novelwriter/assets/i18n/nw_zh_CN.qm +0 -0
  17. novelwriter/assets/i18n/project_de_DE.json +2 -0
  18. novelwriter/assets/i18n/project_en_US.json +2 -0
  19. novelwriter/assets/i18n/project_es_419.json +2 -0
  20. novelwriter/assets/i18n/project_fr_FR.json +3 -1
  21. novelwriter/assets/i18n/project_it_IT.json +2 -0
  22. novelwriter/assets/i18n/project_ja_JP.json +2 -0
  23. novelwriter/assets/i18n/project_nb_NO.json +2 -0
  24. novelwriter/assets/i18n/project_nl_NL.json +2 -0
  25. novelwriter/assets/i18n/project_pl_PL.json +2 -0
  26. novelwriter/assets/i18n/project_pt_BR.json +2 -0
  27. novelwriter/assets/i18n/project_zh_CN.json +2 -0
  28. novelwriter/assets/manual.pdf +0 -0
  29. novelwriter/assets/manual_fr_FR.pdf +0 -0
  30. novelwriter/assets/sample.zip +0 -0
  31. novelwriter/common.py +1 -1
  32. novelwriter/config.py +45 -20
  33. novelwriter/constants.py +40 -36
  34. novelwriter/core/buildsettings.py +8 -1
  35. novelwriter/core/coretools.py +1 -1
  36. novelwriter/core/docbuild.py +1 -1
  37. novelwriter/core/document.py +1 -1
  38. novelwriter/core/index.py +1 -1
  39. novelwriter/core/item.py +1 -1
  40. novelwriter/core/itemmodel.py +1 -1
  41. novelwriter/core/options.py +1 -1
  42. novelwriter/core/project.py +3 -7
  43. novelwriter/core/projectdata.py +8 -2
  44. novelwriter/core/projectxml.py +1 -1
  45. novelwriter/core/sessions.py +1 -1
  46. novelwriter/core/spellcheck.py +1 -1
  47. novelwriter/core/status.py +17 -3
  48. novelwriter/core/storage.py +1 -1
  49. novelwriter/core/tree.py +1 -1
  50. novelwriter/dialogs/about.py +1 -1
  51. novelwriter/dialogs/docmerge.py +1 -1
  52. novelwriter/dialogs/docsplit.py +1 -1
  53. novelwriter/dialogs/editlabel.py +1 -1
  54. novelwriter/dialogs/preferences.py +16 -7
  55. novelwriter/dialogs/projectsettings.py +146 -96
  56. novelwriter/dialogs/quotes.py +1 -1
  57. novelwriter/dialogs/wordlist.py +11 -10
  58. novelwriter/enum.py +1 -8
  59. novelwriter/error.py +2 -2
  60. novelwriter/extensions/configlayout.py +1 -1
  61. novelwriter/extensions/eventfilters.py +1 -1
  62. novelwriter/extensions/modified.py +17 -5
  63. novelwriter/extensions/novelselector.py +4 -3
  64. novelwriter/extensions/pagedsidebar.py +4 -4
  65. novelwriter/extensions/progressbars.py +4 -4
  66. novelwriter/extensions/statusled.py +8 -9
  67. novelwriter/extensions/switch.py +3 -3
  68. novelwriter/extensions/switchbox.py +1 -1
  69. novelwriter/extensions/versioninfo.py +1 -1
  70. novelwriter/formats/shared.py +13 -12
  71. novelwriter/formats/todocx.py +2 -2
  72. novelwriter/formats/tohtml.py +31 -28
  73. novelwriter/formats/tokenizer.py +19 -13
  74. novelwriter/formats/tomarkdown.py +4 -3
  75. novelwriter/formats/toodt.py +2 -2
  76. novelwriter/formats/toqdoc.py +3 -1
  77. novelwriter/formats/toraw.py +1 -1
  78. novelwriter/gui/doceditor.py +39 -21
  79. novelwriter/gui/dochighlight.py +1 -1
  80. novelwriter/gui/docviewer.py +2 -2
  81. novelwriter/gui/docviewerpanel.py +1 -1
  82. novelwriter/gui/editordocument.py +1 -1
  83. novelwriter/gui/itemdetails.py +4 -3
  84. novelwriter/gui/mainmenu.py +1 -1
  85. novelwriter/gui/noveltree.py +1 -1
  86. novelwriter/gui/outline.py +8 -9
  87. novelwriter/gui/projtree.py +20 -25
  88. novelwriter/gui/search.py +2 -9
  89. novelwriter/gui/sidebar.py +1 -1
  90. novelwriter/gui/statusbar.py +26 -10
  91. novelwriter/gui/theme.py +1 -1
  92. novelwriter/guimain.py +2 -6
  93. novelwriter/shared.py +1 -1
  94. novelwriter/text/counting.py +1 -1
  95. novelwriter/text/patterns.py +1 -1
  96. novelwriter/tools/dictionaries.py +3 -3
  97. novelwriter/tools/lipsum.py +1 -1
  98. novelwriter/tools/manusbuild.py +1 -1
  99. novelwriter/tools/manuscript.py +7 -7
  100. novelwriter/tools/manussettings.py +9 -9
  101. novelwriter/tools/noveldetails.py +1 -1
  102. novelwriter/tools/welcome.py +2 -2
  103. novelwriter/tools/writingstats.py +1 -1
  104. novelwriter/types.py +2 -2
  105. {novelWriter-2.6b2.dist-info → novelWriter-2.6.1.dist-info}/LICENSE.md +0 -0
  106. {novelWriter-2.6b2.dist-info → novelWriter-2.6.1.dist-info}/entry_points.txt +0 -0
  107. {novelWriter-2.6b2.dist-info → novelWriter-2.6.1.dist-info}/top_level.txt +0 -0
@@ -6,7 +6,7 @@ File History:
6
6
  Created: 2022-11-17 [2.0] NovelSelector
7
7
 
8
8
  This file is a part of novelWriter
9
- Copyright 2018–2024, Veronica Berglyd Olsen
9
+ Copyright (C) 2022 Veronica Berglyd Olsen and novelWriter contributors
10
10
 
11
11
  This program is free software: you can redistribute it and/or modify
12
12
  it under the terms of the GNU General Public License as published by
@@ -90,12 +90,13 @@ class NovelSelector(QComboBox):
90
90
  @pyqtSlot()
91
91
  def refreshNovelList(self) -> None:
92
92
  """Rebuild the list of novel items."""
93
+ cHandle = self.currentData()
94
+
93
95
  self._blockSignal = True
94
96
  self._firstHandle = None
95
97
  self.clear()
96
98
 
97
99
  icon = SHARED.theme.getIcon(nwLabels.CLASS_ICON[nwItemClass.NOVEL])
98
- handle = self.currentData()
99
100
  for tHandle, nwItem in SHARED.project.tree.iterRoots(nwItemClass.NOVEL):
100
101
  if self._listFormat:
101
102
  name = self._listFormat.format(nwItem.itemName)
@@ -110,7 +111,7 @@ class NovelSelector(QComboBox):
110
111
  self.insertSeparator(self.count())
111
112
  self.addItem(icon, self.tr("All Novel Folders"), "")
112
113
 
113
- self.setHandle(handle)
114
+ self.setHandle(cHandle)
114
115
  self.setEnabled(self.count() > 1)
115
116
  self._blockSignal = False
116
117
 
@@ -8,7 +8,7 @@ Created: 2023-02-21 [2.1b1] NPagedToolButton
8
8
  Created: 2023-02-21 [2.1b1] NPagedToolLabel
9
9
 
10
10
  This file is a part of novelWriter
11
- Copyright 2018–2024, Veronica Berglyd Olsen
11
+ Copyright (C) 2023 Veronica Berglyd Olsen and novelWriter contributors
12
12
 
13
13
  This program is free software: you can redistribute it and/or modify
14
14
  it under the terms of the GNU General Public License as published by
@@ -33,7 +33,7 @@ from PyQt5.QtWidgets import (
33
33
  )
34
34
 
35
35
  from novelwriter.types import (
36
- QtAlignLeft, QtMouseOver, QtNoBrush, QtNoPen, QtPaintAnitAlias,
36
+ QtAlignLeft, QtMouseOver, QtNoBrush, QtNoPen, QtPaintAntiAlias,
37
37
  QtSizeExpanding, QtSizeFixed
38
38
  )
39
39
 
@@ -146,7 +146,7 @@ class _PagedToolButton(QToolButton):
146
146
  opt.initFrom(self)
147
147
 
148
148
  paint = QPainter(self)
149
- paint.setRenderHint(QtPaintAnitAlias, True)
149
+ paint.setRenderHint(QtPaintAntiAlias, True)
150
150
  paint.setPen(QtNoPen)
151
151
  paint.setBrush(QtNoBrush)
152
152
 
@@ -213,7 +213,7 @@ class _NPagedToolLabel(QLabel):
213
213
  label that matches the button style.
214
214
  """
215
215
  paint = QPainter(self)
216
- paint.setRenderHint(QtPaintAnitAlias, True)
216
+ paint.setRenderHint(QtPaintAntiAlias, True)
217
217
  paint.setPen(QtNoPen)
218
218
 
219
219
  width = self.width()
@@ -7,7 +7,7 @@ Created: 2023-06-07 [2.1b1] NProgressCircle
7
7
  Created: 2023-06-09 [2.1b1] NProgressSimple
8
8
 
9
9
  This file is a part of novelWriter
10
- Copyright 2018–2024, Veronica Berglyd Olsen
10
+ Copyright (C) 2023 Veronica Berglyd Olsen and novelWriter contributors
11
11
 
12
12
  This program is free software: you can redistribute it and/or modify
13
13
  it under the terms of the GNU General Public License as published by
@@ -31,7 +31,7 @@ from PyQt5.QtGui import QBrush, QColor, QPainter, QPaintEvent, QPen
31
31
  from PyQt5.QtWidgets import QProgressBar, QWidget
32
32
 
33
33
  from novelwriter.types import (
34
- QtAlignCenter, QtPaintAnitAlias, QtRoundCap, QtSizeFixed, QtSolidLine,
34
+ QtAlignCenter, QtPaintAntiAlias, QtRoundCap, QtSizeFixed, QtSolidLine,
35
35
  QtTransparent
36
36
  )
37
37
 
@@ -91,7 +91,7 @@ class NProgressCircle(QProgressBar):
91
91
  progress = 100.0*self.value()/self.maximum()
92
92
  angle = ceil(16*3.6*progress)
93
93
  painter = QPainter(self)
94
- painter.setRenderHint(QtPaintAnitAlias, True)
94
+ painter.setRenderHint(QtPaintAntiAlias, True)
95
95
  painter.setPen(self._dPen)
96
96
  painter.setBrush(self._dBrush)
97
97
  painter.drawEllipse(self._dRect)
@@ -119,7 +119,7 @@ class NProgressSimple(QProgressBar):
119
119
  if (value := self.value()) > 0:
120
120
  progress = ceil(self.width()*float(value)/self.maximum())
121
121
  painter = QPainter(self)
122
- painter.setRenderHint(QtPaintAnitAlias, True)
122
+ painter.setRenderHint(QtPaintAntiAlias, True)
123
123
  painter.setPen(self.palette().highlight().color())
124
124
  painter.setBrush(self.palette().highlight())
125
125
  painter.drawRect(0, 0, progress, self.height())
@@ -6,7 +6,7 @@ File History:
6
6
  Created: 2020-05-17 [0.5.1]
7
7
 
8
8
  This file is a part of novelWriter
9
- Copyright 2018–2024, Veronica Berglyd Olsen
9
+ Copyright (C) 2020 Veronica Berglyd Olsen and novelWriter contributors
10
10
 
11
11
  This program is free software: you can redistribute it and/or modify
12
12
  it under the terms of the GNU General Public License as published by
@@ -29,8 +29,7 @@ from PyQt5.QtGui import QColor, QPainter, QPaintEvent
29
29
  from PyQt5.QtWidgets import QAbstractButton, QWidget
30
30
 
31
31
  from novelwriter import CONFIG
32
- from novelwriter.enum import nwTrinary
33
- from novelwriter.types import QtBlack, QtPaintAnitAlias
32
+ from novelwriter.types import QtBlack, QtPaintAntiAlias
34
33
 
35
34
  logger = logging.getLogger(__name__)
36
35
 
@@ -47,14 +46,14 @@ class StatusLED(QAbstractButton):
47
46
  self._postitve = QtBlack
48
47
  self._negative = QtBlack
49
48
  self._color = QtBlack
50
- self._state = nwTrinary.NEUTRAL
49
+ self._state = None
51
50
  self._bPx = CONFIG.pxInt(1)
52
51
  self.setFixedWidth(sW)
53
52
  self.setFixedHeight(sH)
54
53
  return
55
54
 
56
55
  @property
57
- def state(self) -> nwTrinary:
56
+ def state(self) -> bool | None:
58
57
  """The current state of the LED."""
59
58
  return self._state
60
59
 
@@ -66,11 +65,11 @@ class StatusLED(QAbstractButton):
66
65
  self.setState(self._state)
67
66
  return
68
67
 
69
- def setState(self, state: nwTrinary) -> None:
68
+ def setState(self, state: bool | None) -> None:
70
69
  """Set the colour state."""
71
- if state == nwTrinary.POSITIVE:
70
+ if state is True:
72
71
  self._color = self._postitve
73
- elif state == nwTrinary.NEGATIVE:
72
+ elif state is False:
74
73
  self._color = self._negative
75
74
  else:
76
75
  self._color = self._neutral
@@ -81,7 +80,7 @@ class StatusLED(QAbstractButton):
81
80
  def paintEvent(self, event: QPaintEvent) -> None:
82
81
  """Draw the LED."""
83
82
  painter = QPainter(self)
84
- painter.setRenderHint(QtPaintAnitAlias, True)
83
+ painter.setRenderHint(QtPaintAntiAlias, True)
85
84
  painter.setPen(self.palette().windowText().color())
86
85
  painter.setBrush(self._color)
87
86
  painter.setOpacity(1.0)
@@ -6,7 +6,7 @@ File History:
6
6
  Created: 2020-05-03 [0.4.5]
7
7
 
8
8
  This file is a part of novelWriter
9
- Copyright 2018–2024, Veronica Berglyd Olsen
9
+ Copyright (C) 2020 Veronica Berglyd Olsen and novelWriter contributors
10
10
 
11
11
  This program is free software: you can redistribute it and/or modify
12
12
  it under the terms of the GNU General Public License as published by
@@ -28,7 +28,7 @@ from PyQt5.QtGui import QMouseEvent, QPainter, QPaintEvent, QResizeEvent
28
28
  from PyQt5.QtWidgets import QAbstractButton, QWidget
29
29
 
30
30
  from novelwriter import CONFIG, SHARED
31
- from novelwriter.types import QtMouseLeft, QtNoPen, QtPaintAnitAlias, QtSizeFixed
31
+ from novelwriter.types import QtMouseLeft, QtNoPen, QtPaintAntiAlias, QtSizeFixed
32
32
 
33
33
 
34
34
  class NSwitch(QAbstractButton):
@@ -90,7 +90,7 @@ class NSwitch(QAbstractButton):
90
90
  def paintEvent(self, event: QPaintEvent) -> None:
91
91
  """Drawing the switch itself."""
92
92
  painter = QPainter(self)
93
- painter.setRenderHint(QtPaintAnitAlias, True)
93
+ painter.setRenderHint(QtPaintAntiAlias, True)
94
94
  painter.setPen(QtNoPen)
95
95
 
96
96
  palette = self.palette()
@@ -6,7 +6,7 @@ File History:
6
6
  Created: 2023-04-16 [2.1b1]
7
7
 
8
8
  This file is a part of novelWriter
9
- Copyright 2018–2024, Veronica Berglyd Olsen
9
+ Copyright (C) 2023 Veronica Berglyd Olsen and novelWriter contributors
10
10
 
11
11
  This program is free software: you can redistribute it and/or modify
12
12
  it under the terms of the GNU General Public License as published by
@@ -6,7 +6,7 @@ File History:
6
6
  Created: 2024-02-14 [2.3b1] VersionInfoWidget
7
7
 
8
8
  This file is a part of novelWriter
9
- Copyright 2018–2024, Veronica Berglyd Olsen
9
+ Copyright (C) 2024 Veronica Berglyd Olsen and novelWriter contributors
10
10
 
11
11
  This program is free software: you can redistribute it and/or modify
12
12
  it under the terms of the GNU General Public License as published by
@@ -6,7 +6,7 @@ File History:
6
6
  Created: 2024-10-21 [2.6b1]
7
7
 
8
8
  This file is a part of novelWriter
9
- Copyright 2018–2024, Veronica Berglyd Olsen
9
+ Copyright (C) 2024 Veronica Berglyd Olsen and novelWriter contributors
10
10
 
11
11
  This program is free software: you can redistribute it and/or modify
12
12
  it under the terms of the GNU General Public License as published by
@@ -104,17 +104,18 @@ class BlockTyp(IntEnum):
104
104
 
105
105
  EMPTY = 1 # Empty line (new paragraph)
106
106
  TITLE = 2 # Title
107
- HEAD1 = 3 # Heading 1
108
- HEAD2 = 4 # Heading 2
109
- HEAD3 = 5 # Heading 3
110
- HEAD4 = 6 # Heading 4
111
- TEXT = 7 # Text line
112
- SEP = 8 # Scene separator
113
- SKIP = 9 # Paragraph break
114
- SUMMARY = 10 # Synopsis/short comment
115
- NOTE = 11 # Note
116
- COMMENT = 12 # Comment
117
- KEYWORD = 13 # Tag/reference keywords
107
+ PART = 3 # Partition
108
+ HEAD1 = 4 # Heading 1 or Chapter
109
+ HEAD2 = 5 # Heading 2 or Scene
110
+ HEAD3 = 6 # Heading 3 or Section
111
+ HEAD4 = 7 # Heading 4
112
+ TEXT = 8 # Text line
113
+ SEP = 9 # Scene separator
114
+ SKIP = 10 # Paragraph break
115
+ SUMMARY = 11 # Synopsis/short comment
116
+ NOTE = 12 # Note
117
+ COMMENT = 13 # Comment
118
+ KEYWORD = 14 # Tag/reference keywords
118
119
 
119
120
 
120
121
  class BlockFmt(Flag):
@@ -7,7 +7,7 @@ Created: 2024-10-18 [2.6b1] ToDocX
7
7
  Created: 2024-10-18 [2.6b1] DocXParagraph
8
8
 
9
9
  This file is a part of novelWriter
10
- Copyright 2018–2024, Veronica Berglyd Olsen
10
+ Copyright (C) 2024 Veronica Berglyd Olsen and novelWriter contributors
11
11
 
12
12
  This program is free software: you can redistribute it and/or modify
13
13
  it under the terms of the GNU General Public License as published by
@@ -271,7 +271,7 @@ class ToDocX(Tokenizer):
271
271
  if tType == BlockTyp.TEXT:
272
272
  self._processFragments(par, S_NORM, tText, tFormat)
273
273
 
274
- elif tType == BlockTyp.TITLE:
274
+ elif tType in (BlockTyp.TITLE, BlockTyp.PART):
275
275
  self._processFragments(par, S_TITLE, tText, tFormat)
276
276
 
277
277
  elif tType == BlockTyp.HEAD1:
@@ -6,7 +6,7 @@ File History:
6
6
  Created: 2019-05-07 [0.0.1] ToHtml
7
7
 
8
8
  This file is a part of novelWriter
9
- Copyright 2018–2024, Veronica Berglyd Olsen
9
+ Copyright (C) 2019 Veronica Berglyd Olsen and novelWriter contributors
10
10
 
11
11
  This program is free software: you can redistribute it and/or modify
12
12
  it under the terms of the GNU General Public License as published by
@@ -30,7 +30,7 @@ from pathlib import Path
30
30
  from time import time
31
31
 
32
32
  from novelwriter.common import formatTimeStamp
33
- from novelwriter.constants import nwHtmlUnicode
33
+ from novelwriter.constants import nwHtmlUnicode, nwStyles
34
34
  from novelwriter.core.project import NWProject
35
35
  from novelwriter.formats.shared import BlockFmt, BlockTyp, T_Formats, TextFmt, stripEscape
36
36
  from novelwriter.formats.tokenizer import Tokenizer
@@ -130,20 +130,6 @@ class ToHtml(Tokenizer):
130
130
 
131
131
  def doConvert(self) -> None:
132
132
  """Convert the list of text tokens into an HTML document."""
133
- if self._isNovel:
134
- # For story files, we bump the titles one level up
135
- h1Cl = " class='title'"
136
- h1 = "h1"
137
- h2 = "h1"
138
- h3 = "h2"
139
- h4 = "h3"
140
- else:
141
- h1Cl = ""
142
- h1 = "h1"
143
- h2 = "h2"
144
- h3 = "h3"
145
- h4 = "h4"
146
-
147
133
  lines = []
148
134
  for tType, tMeta, tText, tFmt, tStyle in self._blocks:
149
135
 
@@ -213,25 +199,25 @@ class ToHtml(Tokenizer):
213
199
  if tType == BlockTyp.TEXT:
214
200
  lines.append(f"<p{hStyle}>{self._formatText(tText, tFmt)}</p>\n")
215
201
 
216
- elif tType == BlockTyp.TITLE:
202
+ elif tType in (BlockTyp.TITLE, BlockTyp.PART):
217
203
  tHead = tText.replace("\n", "<br>")
218
204
  lines.append(f"<h1 class='title'{hStyle}>{aNm}{tHead}</h1>\n")
219
205
 
220
206
  elif tType == BlockTyp.HEAD1:
221
207
  tHead = tText.replace("\n", "<br>")
222
- lines.append(f"<{h1}{h1Cl}{hStyle}>{aNm}{tHead}</{h1}>\n")
208
+ lines.append(f"<h1{hStyle}>{aNm}{tHead}</h1>\n")
223
209
 
224
210
  elif tType == BlockTyp.HEAD2:
225
211
  tHead = tText.replace("\n", "<br>")
226
- lines.append(f"<{h2}{hStyle}>{aNm}{tHead}</{h2}>\n")
212
+ lines.append(f"<h2{hStyle}>{aNm}{tHead}</h2>\n")
227
213
 
228
214
  elif tType == BlockTyp.HEAD3:
229
215
  tHead = tText.replace("\n", "<br>")
230
- lines.append(f"<{h3}{hStyle}>{aNm}{tHead}</{h3}>\n")
216
+ lines.append(f"<h3{hStyle}>{aNm}{tHead}</h3>\n")
231
217
 
232
218
  elif tType == BlockTyp.HEAD4:
233
219
  tHead = tText.replace("\n", "<br>")
234
- lines.append(f"<{h4}{hStyle}>{aNm}{tHead}</{h4}>\n")
220
+ lines.append(f"<h4{hStyle}>{aNm}{tHead}</h4>\n")
235
221
 
236
222
  elif tType == BlockTyp.SEP:
237
223
  lines.append(f"<p class='sep'{hStyle}>{tText}</p>\n")
@@ -310,9 +296,7 @@ class ToHtml(Tokenizer):
310
296
  "</style>\n"
311
297
  "</head>\n"
312
298
  "<body>\n"
313
- "<article>\n"
314
299
  "{body:s}\n"
315
- "</article>\n"
316
300
  "</body>\n"
317
301
  "</html>\n"
318
302
  ).format(
@@ -359,6 +343,12 @@ class ToHtml(Tokenizer):
359
343
  mtSP = self._marginSep[0]
360
344
  mbSP = self._marginSep[1]
361
345
 
346
+ fSz0 = nwStyles.H_SIZES[0]
347
+ fSz1 = nwStyles.H_SIZES[1]
348
+ fSz2 = nwStyles.H_SIZES[2]
349
+ fSz3 = nwStyles.H_SIZES[3]
350
+ fSz4 = nwStyles.H_SIZES[4]
351
+
362
352
  font = self._textFont
363
353
  fFam = font.family()
364
354
  fSz = font.pointSize()
@@ -379,12 +369,25 @@ class ToHtml(Tokenizer):
379
369
  styles.append(f"a {{color: {lColor};}}")
380
370
  styles.append(f"mark {{background: {mColor};}}")
381
371
  styles.append(f"h1, h2, h3, h4 {{color: {hColor}; page-break-after: avoid;}}")
382
- styles.append(f"h1 {{margin-top: {mtH1:.2f}em; margin-bottom: {mbH1:.2f}em;}}")
383
- styles.append(f"h2 {{margin-top: {mtH2:.2f}em; margin-bottom: {mbH2:.2f}em;}}")
384
- styles.append(f"h3 {{margin-top: {mtH3:.2f}em; margin-bottom: {mbH3:.2f}em;}}")
385
- styles.append(f"h4 {{margin-top: {mtH4:.2f}em; margin-bottom: {mbH4:.2f}em;}}")
386
372
  styles.append(
387
- f".title {{font-size: 2.5em; margin-top: {mtH0:.2f}em; margin-bottom: {mbH0:.2f}em;}}"
373
+ f"h1 {{font-size: {fSz1:.2f}em; "
374
+ f"margin-top: {mtH1:.2f}em; margin-bottom: {mbH1:.2f}em;}}"
375
+ )
376
+ styles.append(
377
+ f"h2 {{font-size: {fSz2:.2f}em; "
378
+ f"margin-top: {mtH2:.2f}em; margin-bottom: {mbH2:.2f}em;}}"
379
+ )
380
+ styles.append(
381
+ f"h3 {{font-size: {fSz3:.2f}em; "
382
+ f"margin-top: {mtH3:.2f}em; margin-bottom: {mbH3:.2f}em;}}"
383
+ )
384
+ styles.append(
385
+ f"h4 {{font-size: {fSz4:.2f}em; "
386
+ f"margin-top: {mtH4:.2f}em; margin-bottom: {mbH4:.2f}em;}}"
387
+ )
388
+ styles.append(
389
+ f".title {{font-size: {fSz0:.2f}em; "
390
+ f"margin-top: {mtH0:.2f}em; margin-bottom: {mbH0:.2f}em;}}"
388
391
  )
389
392
  styles.append(
390
393
  f".sep {{text-align: center; margin-top: {mtSP:.2f}em; margin-bottom: {mbSP:.2f}em;}}"
@@ -7,7 +7,7 @@ Created: 2019-05-05 [0.0.1] Tokenizer
7
7
  Created: 2023-05-23 [2.1b1] HeadingFormatter
8
8
 
9
9
  This file is a part of novelWriter
10
- Copyright 2018–2024, Veronica Berglyd Olsen
10
+ Copyright (C) 2019 Veronica Berglyd Olsen and novelWriter contributors
11
11
 
12
12
  This program is free software: you can redistribute it and/or modify
13
13
  it under the terms of the GNU General Public License as published by
@@ -68,11 +68,11 @@ COMMENT_STYLE = {
68
68
  nwComment.COMMENT: ComStyle(),
69
69
  nwComment.STORY: ComStyle("", "modifier", "note"),
70
70
  }
71
- HEADINGS = [BlockTyp.TITLE, BlockTyp.HEAD1, BlockTyp.HEAD2, BlockTyp.HEAD3, BlockTyp.HEAD4]
72
- SKIP_INDENT = [
73
- BlockTyp.TITLE, BlockTyp.HEAD1, BlockTyp.HEAD2, BlockTyp.HEAD2, BlockTyp.HEAD3,
74
- BlockTyp.HEAD4, BlockTyp.SEP, BlockTyp.SKIP,
71
+ HEADINGS = [
72
+ BlockTyp.TITLE, BlockTyp.PART, BlockTyp.HEAD1,
73
+ BlockTyp.HEAD2, BlockTyp.HEAD3, BlockTyp.HEAD4,
75
74
  ]
75
+ SKIP_INDENT = HEADINGS + [BlockTyp.SEP, BlockTyp.SKIP]
76
76
  B_EMPTY: T_Block = (BlockTyp.EMPTY, "", "", [], BlockFmt.NONE)
77
77
 
78
78
 
@@ -654,6 +654,7 @@ class Tokenizer(ABC):
654
654
  if not (isPlain or isNovel and sHide):
655
655
  tStyle |= self._titleStyle
656
656
  if isNovel:
657
+ tType = BlockTyp.PART if isPlain else BlockTyp.TITLE
657
658
  if sHide:
658
659
  tText = ""
659
660
  tType = BlockTyp.EMPTY
@@ -687,6 +688,7 @@ class Tokenizer(ABC):
687
688
  sHide = self._hideChapter if isPlain else self._hideUnNum
688
689
  tFormat = self._fmtChapter if isPlain else self._fmtUnNum
689
690
  if isNovel:
691
+ tType = BlockTyp.HEAD1 # Promote
690
692
  if isPlain:
691
693
  self._hFormatter.incChapter()
692
694
  if sHide:
@@ -721,6 +723,7 @@ class Tokenizer(ABC):
721
723
  sHide = self._hideScene if isPlain else self._hideHScene
722
724
  tFormat = self._fmtScene if isPlain else self._fmtHScene
723
725
  if isNovel:
726
+ tType = BlockTyp.HEAD2 # Promote
724
727
  self._hFormatter.incScene()
725
728
  if sHide:
726
729
  tText = ""
@@ -752,6 +755,7 @@ class Tokenizer(ABC):
752
755
  tText = aLine[5:].strip()
753
756
  tType = BlockTyp.HEAD4
754
757
  if isNovel:
758
+ tType = BlockTyp.HEAD3 # Promote
755
759
  if self._hideSection:
756
760
  tText = ""
757
761
  tType = BlockTyp.EMPTY
@@ -927,12 +931,14 @@ class Tokenizer(ABC):
927
931
  for tType, tKey, tText, _, _ in self._blocks:
928
932
  if tType == BlockTyp.TITLE:
929
933
  prefix = "TT"
934
+ elif tType == BlockTyp.PART:
935
+ prefix = "PT"
930
936
  elif tType == BlockTyp.HEAD1:
931
- prefix = "PT" if isNovel else "H1"
937
+ prefix = "CH" if isNovel else "H1"
932
938
  elif tType == BlockTyp.HEAD2:
933
- prefix = "CH" if isNovel else "H2"
934
- elif tType == BlockTyp.HEAD3:
935
- prefix = "SC" if isNovel else "H3"
939
+ prefix = "SC" if isNovel else "H2"
940
+ elif tType == BlockTyp.HEAD3 and not isNovel:
941
+ prefix = "H3"
936
942
  else:
937
943
  continue
938
944
 
@@ -946,11 +952,11 @@ class Tokenizer(ABC):
946
952
  titleCount = self._counts.get(nwStats.TITLES, 0)
947
953
  paragraphCount = self._counts.get(nwStats.PARAGRAPHS, 0)
948
954
 
949
- allWords = self._counts.get(nwStats.WORDS_ALL, 0)
955
+ allWords = self._counts.get(nwStats.WORDS, 0)
950
956
  textWords = self._counts.get(nwStats.WORDS_TEXT, 0)
951
957
  titleWords = self._counts.get(nwStats.WORDS_TITLE, 0)
952
958
 
953
- allChars = self._counts.get(nwStats.CHARS_ALL, 0)
959
+ allChars = self._counts.get(nwStats.CHARS, 0)
954
960
  textChars = self._counts.get(nwStats.CHARS_TEXT, 0)
955
961
  titleChars = self._counts.get(nwStats.CHARS_TITLE, 0)
956
962
 
@@ -1004,11 +1010,11 @@ class Tokenizer(ABC):
1004
1010
  self._counts[nwStats.TITLES] = titleCount
1005
1011
  self._counts[nwStats.PARAGRAPHS] = paragraphCount
1006
1012
 
1007
- self._counts[nwStats.WORDS_ALL] = allWords
1013
+ self._counts[nwStats.WORDS] = allWords
1008
1014
  self._counts[nwStats.WORDS_TEXT] = textWords
1009
1015
  self._counts[nwStats.WORDS_TITLE] = titleWords
1010
1016
 
1011
- self._counts[nwStats.CHARS_ALL] = allChars
1017
+ self._counts[nwStats.CHARS] = allChars
1012
1018
  self._counts[nwStats.CHARS_TEXT] = textChars
1013
1019
  self._counts[nwStats.CHARS_TITLE] = titleChars
1014
1020
 
@@ -6,7 +6,7 @@ File History:
6
6
  Created: 2021-02-06 [1.2b1] ToMarkdown
7
7
 
8
8
  This file is a part of novelWriter
9
- Copyright 2018–2024, Veronica Berglyd Olsen
9
+ Copyright (C) 2021 Veronica Berglyd Olsen and novelWriter contributors
10
10
 
11
11
  This program is free software: you can redistribute it and/or modify
12
12
  it under the terms of the GNU General Public License as published by
@@ -113,9 +113,10 @@ class ToMarkdown(Tokenizer):
113
113
  tTemp = self._formatText(tText, tFormat, mTags).replace("\n", " \n")
114
114
  lines.append(f"{tTemp}\n\n")
115
115
 
116
- elif tType == BlockTyp.TITLE:
116
+ elif tType in (BlockTyp.TITLE, BlockTyp.PART):
117
117
  tHead = tText.replace("\n", " - ")
118
- lines.append(f"# {tHead}\n\n")
118
+ lines.append(f"{tHead}\n")
119
+ lines.append("="*len(tHead) + "\n\n")
119
120
 
120
121
  elif tType == BlockTyp.HEAD1:
121
122
  tHead = tText.replace("\n", " - ")
@@ -9,7 +9,7 @@ Created: 2021-01-27 [1.2b1] ODTTextStyle
9
9
  Created: 2021-08-14 [1.5b1] XMLParagraph
10
10
 
11
11
  This file is a part of novelWriter
12
- Copyright 2018–2024, Veronica Berglyd Olsen
12
+ Copyright (C) 2021 Veronica Berglyd Olsen and novelWriter contributors
13
13
 
14
14
  This program is free software: you can redistribute it and/or modify
15
15
  it under the terms of the GNU General Public License as published by
@@ -363,7 +363,7 @@ class ToOdt(Tokenizer):
363
363
  else:
364
364
  self._addTextPar(xText, S_TEXT, oStyle, tText, tFmt=tFormat)
365
365
 
366
- elif tType == BlockTyp.TITLE:
366
+ elif tType in (BlockTyp.TITLE, BlockTyp.PART):
367
367
  # Title must be text:p
368
368
  self._addTextPar(xText, S_TITLE, oStyle, tText, isHead=False)
369
369
 
@@ -6,7 +6,7 @@ File History:
6
6
  Created: 2024-05-21 [2.5b1] ToQTextDocument
7
7
 
8
8
  This file is a part of novelWriter
9
- Copyright 2018–2024, Veronica Berglyd Olsen
9
+ Copyright (C) 2024 Veronica Berglyd Olsen and novelWriter contributors
10
10
 
11
11
  This program is free software: you can redistribute it and/or modify
12
12
  it under the terms of the GNU General Public License as published by
@@ -157,6 +157,7 @@ class ToQTextDocument(Tokenizer):
157
157
 
158
158
  self._mHead = {
159
159
  BlockTyp.TITLE: (fPx * self._marginTitle[0], fPx * self._marginTitle[1]),
160
+ BlockTyp.PART: (fPx * self._marginTitle[0], fPx * self._marginTitle[1]),
160
161
  BlockTyp.HEAD1: (fPx * self._marginHead1[0], fPx * self._marginHead1[1]),
161
162
  BlockTyp.HEAD2: (fPx * self._marginHead2[0], fPx * self._marginHead2[1]),
162
163
  BlockTyp.HEAD3: (fPx * self._marginHead3[0], fPx * self._marginHead3[1]),
@@ -166,6 +167,7 @@ class ToQTextDocument(Tokenizer):
166
167
  hScale = self._scaleHeads
167
168
  self._sHead = {
168
169
  BlockTyp.TITLE: (nwStyles.H_SIZES.get(0, 1.0) * fPt) if hScale else fPt,
170
+ BlockTyp.PART: (nwStyles.H_SIZES.get(0, 1.0) * fPt) if hScale else fPt,
169
171
  BlockTyp.HEAD1: (nwStyles.H_SIZES.get(1, 1.0) * fPt) if hScale else fPt,
170
172
  BlockTyp.HEAD2: (nwStyles.H_SIZES.get(2, 1.0) * fPt) if hScale else fPt,
171
173
  BlockTyp.HEAD3: (nwStyles.H_SIZES.get(3, 1.0) * fPt) if hScale else fPt,
@@ -6,7 +6,7 @@ File History:
6
6
  Created: 2024-10-15 [2.6b1] ToRaw
7
7
 
8
8
  This file is a part of novelWriter
9
- Copyright 2018–2024, Veronica Berglyd Olsen
9
+ Copyright (C) 2024 Veronica Berglyd Olsen and novelWriter contributors
10
10
 
11
11
  This program is free software: you can redistribute it and/or modify
12
12
  it under the terms of the GNU General Public License as published by