novelWriter 2.4.2__py3-none-any.whl → 2.5b1__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 (109) hide show
  1. {novelWriter-2.4.2.dist-info → novelWriter-2.5b1.dist-info}/METADATA +4 -5
  2. {novelWriter-2.4.2.dist-info → novelWriter-2.5b1.dist-info}/RECORD +109 -101
  3. novelwriter/__init__.py +33 -39
  4. novelwriter/assets/i18n/project_en_GB.json +1 -0
  5. novelwriter/assets/icons/typicons_dark/icons.conf +2 -0
  6. novelwriter/assets/icons/typicons_dark/nw_font.svg +4 -0
  7. novelwriter/assets/icons/typicons_dark/nw_quote.svg +4 -0
  8. novelwriter/assets/icons/typicons_light/icons.conf +2 -0
  9. novelwriter/assets/icons/typicons_light/nw_font.svg +4 -0
  10. novelwriter/assets/icons/typicons_light/nw_quote.svg +4 -0
  11. novelwriter/assets/manual.pdf +0 -0
  12. novelwriter/assets/sample.zip +0 -0
  13. novelwriter/assets/syntax/cyberpunk_night.conf +5 -3
  14. novelwriter/assets/syntax/default_dark.conf +32 -18
  15. novelwriter/assets/syntax/default_light.conf +24 -10
  16. novelwriter/assets/syntax/dracula.conf +44 -0
  17. novelwriter/assets/syntax/grey_dark.conf +5 -4
  18. novelwriter/assets/syntax/grey_light.conf +5 -4
  19. novelwriter/assets/syntax/light_owl.conf +7 -6
  20. novelwriter/assets/syntax/night_owl.conf +7 -6
  21. novelwriter/assets/syntax/snazzy.conf +42 -0
  22. novelwriter/assets/syntax/solarized_dark.conf +4 -3
  23. novelwriter/assets/syntax/solarized_light.conf +4 -3
  24. novelwriter/assets/syntax/tango.conf +27 -11
  25. novelwriter/assets/syntax/tomorrow.conf +6 -5
  26. novelwriter/assets/syntax/tomorrow_night.conf +7 -6
  27. novelwriter/assets/syntax/tomorrow_night_blue.conf +6 -5
  28. novelwriter/assets/syntax/tomorrow_night_bright.conf +6 -5
  29. novelwriter/assets/syntax/tomorrow_night_eighties.conf +6 -5
  30. novelwriter/assets/text/credits_en.htm +4 -1
  31. novelwriter/assets/themes/cyberpunk_night.conf +2 -0
  32. novelwriter/assets/themes/default_dark.conf +1 -0
  33. novelwriter/assets/themes/default_light.conf +1 -0
  34. novelwriter/assets/themes/dracula.conf +47 -0
  35. novelwriter/assets/themes/solarized_dark.conf +1 -0
  36. novelwriter/assets/themes/solarized_light.conf +1 -0
  37. novelwriter/common.py +31 -9
  38. novelwriter/config.py +118 -84
  39. novelwriter/constants.py +40 -26
  40. novelwriter/core/buildsettings.py +63 -66
  41. novelwriter/core/coretools.py +2 -22
  42. novelwriter/core/docbuild.py +51 -40
  43. novelwriter/core/document.py +3 -5
  44. novelwriter/core/index.py +115 -45
  45. novelwriter/core/item.py +8 -19
  46. novelwriter/core/options.py +2 -4
  47. novelwriter/core/project.py +23 -57
  48. novelwriter/core/projectdata.py +1 -3
  49. novelwriter/core/projectxml.py +12 -15
  50. novelwriter/core/sessions.py +3 -5
  51. novelwriter/core/spellcheck.py +4 -9
  52. novelwriter/core/status.py +211 -164
  53. novelwriter/core/storage.py +0 -8
  54. novelwriter/core/tohtml.py +94 -100
  55. novelwriter/core/tokenizer.py +199 -112
  56. novelwriter/core/{tomd.py → tomarkdown.py} +97 -78
  57. novelwriter/core/toodt.py +212 -148
  58. novelwriter/core/toqdoc.py +403 -0
  59. novelwriter/core/tree.py +5 -7
  60. novelwriter/dialogs/about.py +3 -5
  61. novelwriter/dialogs/docmerge.py +1 -3
  62. novelwriter/dialogs/docsplit.py +1 -3
  63. novelwriter/dialogs/editlabel.py +0 -2
  64. novelwriter/dialogs/preferences.py +111 -88
  65. novelwriter/dialogs/projectsettings.py +216 -180
  66. novelwriter/dialogs/quotes.py +3 -4
  67. novelwriter/dialogs/wordlist.py +3 -9
  68. novelwriter/enum.py +31 -25
  69. novelwriter/error.py +8 -15
  70. novelwriter/extensions/circularprogress.py +5 -6
  71. novelwriter/extensions/configlayout.py +18 -18
  72. novelwriter/extensions/eventfilters.py +1 -5
  73. novelwriter/extensions/modified.py +50 -13
  74. novelwriter/extensions/novelselector.py +1 -3
  75. novelwriter/extensions/pagedsidebar.py +9 -12
  76. novelwriter/extensions/simpleprogress.py +1 -3
  77. novelwriter/extensions/statusled.py +1 -3
  78. novelwriter/extensions/switch.py +4 -6
  79. novelwriter/extensions/switchbox.py +7 -6
  80. novelwriter/extensions/versioninfo.py +3 -9
  81. novelwriter/gui/doceditor.py +132 -133
  82. novelwriter/gui/dochighlight.py +237 -183
  83. novelwriter/gui/docviewer.py +61 -97
  84. novelwriter/gui/docviewerpanel.py +3 -10
  85. novelwriter/gui/editordocument.py +1 -3
  86. novelwriter/gui/itemdetails.py +7 -11
  87. novelwriter/gui/mainmenu.py +11 -7
  88. novelwriter/gui/noveltree.py +11 -24
  89. novelwriter/gui/outline.py +11 -23
  90. novelwriter/gui/projtree.py +26 -43
  91. novelwriter/gui/search.py +1 -3
  92. novelwriter/gui/sidebar.py +2 -6
  93. novelwriter/gui/statusbar.py +6 -10
  94. novelwriter/gui/theme.py +26 -51
  95. novelwriter/guimain.py +50 -71
  96. novelwriter/shared.py +30 -15
  97. novelwriter/tools/dictionaries.py +12 -15
  98. novelwriter/tools/lipsum.py +2 -4
  99. novelwriter/tools/manusbuild.py +1 -3
  100. novelwriter/tools/manuscript.py +71 -144
  101. novelwriter/tools/manussettings.py +67 -73
  102. novelwriter/tools/noveldetails.py +6 -11
  103. novelwriter/tools/welcome.py +2 -16
  104. novelwriter/tools/writingstats.py +6 -9
  105. novelwriter/types.py +45 -3
  106. {novelWriter-2.4.2.dist-info → novelWriter-2.5b1.dist-info}/LICENSE.md +0 -0
  107. {novelWriter-2.4.2.dist-info → novelWriter-2.5b1.dist-info}/WHEEL +0 -0
  108. {novelWriter-2.4.2.dist-info → novelWriter-2.5b1.dist-info}/entry_points.txt +0 -0
  109. {novelWriter-2.4.2.dist-info → novelWriter-2.5b1.dist-info}/top_level.txt +0 -0
@@ -27,22 +27,25 @@ import logging
27
27
 
28
28
  from typing import TYPE_CHECKING
29
29
 
30
- from PyQt5.QtCore import QEvent, Qt, pyqtSignal, pyqtSlot
30
+ from PyQt5.QtCore import QEvent, pyqtSignal, pyqtSlot
31
31
  from PyQt5.QtGui import QFont, QIcon, QSyntaxHighlighter, QTextCharFormat, QTextDocument
32
32
  from PyQt5.QtWidgets import (
33
- QAbstractButton, QAbstractItemView, QDialog, QDialogButtonBox, QFontDialog,
34
- QFrame, QGridLayout, QHBoxLayout, QHeaderView, QLabel, QLineEdit, QMenu,
35
- QPlainTextEdit, QPushButton, QSplitter, QStackedWidget, QTreeWidget,
36
- QTreeWidgetItem, QVBoxLayout, QWidget
33
+ QAbstractButton, QAbstractItemView, QDialogButtonBox, QFrame, QGridLayout,
34
+ QHBoxLayout, QHeaderView, QLabel, QLineEdit, QMenu, QPlainTextEdit,
35
+ QPushButton, QSplitter, QStackedWidget, QTreeWidget, QTreeWidgetItem,
36
+ QVBoxLayout, QWidget
37
37
  )
38
38
 
39
39
  from novelwriter import CONFIG, SHARED
40
+ from novelwriter.common import describeFont
40
41
  from novelwriter.constants import nwHeadFmt, nwKeyWords, nwLabels, trConst
41
42
  from novelwriter.core.buildsettings import BuildSettings, FilterMode
42
43
  from novelwriter.extensions.configlayout import (
43
44
  NColourLabel, NFixedPage, NScrollableForm, NScrollablePage
44
45
  )
45
- from novelwriter.extensions.modified import NComboBox, NDoubleSpinBox, NIconToolButton, NSpinBox
46
+ from novelwriter.extensions.modified import (
47
+ NComboBox, NDoubleSpinBox, NIconToolButton, NSpinBox, NToolDialog
48
+ )
46
49
  from novelwriter.extensions.pagedsidebar import NPagedSideBar
47
50
  from novelwriter.extensions.switch import NSwitch
48
51
  from novelwriter.extensions.switchbox import NSwitchBox
@@ -57,7 +60,7 @@ if TYPE_CHECKING: # pragma: no cover
57
60
  logger = logging.getLogger(__name__)
58
61
 
59
62
 
60
- class GuiBuildSettings(QDialog):
63
+ class GuiBuildSettings(NToolDialog):
61
64
  """GUI Tools: Manuscript Build Settings Dialog
62
65
 
63
66
  The main tool for configuring manuscript builds. It's a GUI tool for
@@ -72,13 +75,11 @@ class GuiBuildSettings(QDialog):
72
75
 
73
76
  newSettingsReady = pyqtSignal(BuildSettings)
74
77
 
75
- def __init__(self, mainGui: GuiMain, build: BuildSettings) -> None:
76
- super().__init__(parent=mainGui)
78
+ def __init__(self, parent: GuiMain, build: BuildSettings) -> None:
79
+ super().__init__(parent=parent)
77
80
 
78
81
  logger.debug("Create: GuiBuildSettings")
79
82
  self.setObjectName("GuiBuildSettings")
80
- if CONFIG.osDarwin:
81
- self.setWindowFlag(Qt.WindowType.Tool)
82
83
 
83
84
  self._build = build
84
85
 
@@ -278,8 +279,6 @@ class GuiBuildSettings(QDialog):
278
279
  self._build.resetChangedState()
279
280
  return
280
281
 
281
- # END Class GuiBuildSettings
282
-
283
282
 
284
283
  class _FilterTab(NFixedPage):
285
284
 
@@ -296,8 +295,8 @@ class _FilterTab(NFixedPage):
296
295
  F_INCLUDED = 2
297
296
  F_EXCLUDED = 3
298
297
 
299
- def __init__(self, buildMain: GuiBuildSettings, build: BuildSettings) -> None:
300
- super().__init__(parent=buildMain)
298
+ def __init__(self, parent: QWidget, build: BuildSettings) -> None:
299
+ super().__init__(parent=parent)
301
300
 
302
301
  self._treeMap: dict[str, QTreeWidgetItem] = {}
303
302
  self._build = build
@@ -574,8 +573,6 @@ class _FilterTab(NFixedPage):
574
573
  self._scanChildren(item.child(i), items)
575
574
  return items
576
575
 
577
- # END Class _FilterTab
578
-
579
576
 
580
577
  class _HeadingsTab(NScrollablePage):
581
578
 
@@ -586,8 +583,8 @@ class _HeadingsTab(NScrollablePage):
586
583
  EDIT_HSCENE = 5
587
584
  EDIT_SECTION = 6
588
585
 
589
- def __init__(self, buildMain: GuiBuildSettings, build: BuildSettings) -> None:
590
- super().__init__(parent=buildMain)
586
+ def __init__(self, parent: QWidget, build: BuildSettings) -> None:
587
+ super().__init__(parent=parent)
591
588
 
592
589
  self._build = build
593
590
  self._editing = 0
@@ -941,8 +938,6 @@ class _HeadingsTab(NScrollablePage):
941
938
 
942
939
  return
943
940
 
944
- # END Class _HeadingsTab
945
-
946
941
 
947
942
  class _HeadingSyntaxHighlighter(QSyntaxHighlighter):
948
943
 
@@ -967,13 +962,11 @@ class _HeadingSyntaxHighlighter(QSyntaxHighlighter):
967
962
  self.setFormat(pos + ddots, 1, self._fmtSymbol)
968
963
  return
969
964
 
970
- # END Class _HeadingSyntaxHighlighter
971
-
972
965
 
973
966
  class _ContentTab(NScrollableForm):
974
967
 
975
- def __init__(self, buildMain: GuiBuildSettings, build: BuildSettings) -> None:
976
- super().__init__(parent=buildMain)
968
+ def __init__(self, parent: QWidget, build: BuildSettings) -> None:
969
+ super().__init__(parent=parent)
977
970
 
978
971
  self._build = build
979
972
 
@@ -1052,16 +1045,15 @@ class _ContentTab(NScrollableForm):
1052
1045
  self.ignoredKeywords.setText(", ".join(verified))
1053
1046
  return
1054
1047
 
1055
- # END Class _ContentTab
1056
-
1057
1048
 
1058
1049
  class _FormatTab(NScrollableForm):
1059
1050
 
1060
- def __init__(self, buildMain: GuiBuildSettings, build: BuildSettings) -> None:
1061
- super().__init__(parent=buildMain)
1051
+ def __init__(self, parent: QWidget, build: BuildSettings) -> None:
1052
+ super().__init__(parent=parent)
1062
1053
 
1063
1054
  self._build = build
1064
1055
  self._unitScale = 1.0
1056
+ self._textFont = QFont(CONFIG.textFont)
1065
1057
 
1066
1058
  iPx = SHARED.theme.baseIconHeight
1067
1059
  iSz = SHARED.theme.baseIconSize
@@ -1073,24 +1065,16 @@ class _FormatTab(NScrollableForm):
1073
1065
 
1074
1066
  self.addGroupLabel(self._build.getLabel("format.grpFormat"))
1075
1067
 
1076
- # Font Family
1068
+ # Text Font
1077
1069
  self.textFont = QLineEdit(self)
1078
1070
  self.textFont.setReadOnly(True)
1079
- self.btnTextFont = NIconToolButton(self, iSz, "more")
1071
+ self.btnTextFont = NIconToolButton(self, iSz, "font")
1080
1072
  self.btnTextFont.clicked.connect(self._selectFont)
1081
1073
  self.addRow(
1082
1074
  self._build.getLabel("format.textFont"), self.textFont,
1083
- button=self.btnTextFont, stretch=(3, 2)
1075
+ button=self.btnTextFont, stretch=(1, 1)
1084
1076
  )
1085
1077
 
1086
- # Font Size
1087
- self.textSize = NSpinBox(self)
1088
- self.textSize.setMinimum(8)
1089
- self.textSize.setMaximum(60)
1090
- self.textSize.setSingleStep(1)
1091
- self.textSize.setMinimumWidth(spW)
1092
- self.addRow(self._build.getLabel("format.textSize"), self.textSize, unit="pt")
1093
-
1094
1078
  # Line Height
1095
1079
  self.lineHeight = NDoubleSpinBox(self)
1096
1080
  self.lineHeight.setFixedWidth(spW)
@@ -1108,10 +1092,31 @@ class _FormatTab(NScrollableForm):
1108
1092
  self.justifyText = NSwitch(self, height=iPx)
1109
1093
  self.stripUnicode = NSwitch(self, height=iPx)
1110
1094
  self.replaceTabs = NSwitch(self, height=iPx)
1095
+ self.keepBreaks = NSwitch(self, height=iPx)
1111
1096
 
1112
1097
  self.addRow(self._build.getLabel("format.justifyText"), self.justifyText)
1113
1098
  self.addRow(self._build.getLabel("format.stripUnicode"), self.stripUnicode)
1114
1099
  self.addRow(self._build.getLabel("format.replaceTabs"), self.replaceTabs)
1100
+ self.addRow(self._build.getLabel("format.keepBreaks"), self.keepBreaks)
1101
+
1102
+ # First Line Indent
1103
+ # =================
1104
+
1105
+ self.addGroupLabel(self._build.getLabel("format.grpParIndent"))
1106
+
1107
+ self.firstIndent = NSwitch(self, height=iPx)
1108
+ self.indentFirstPar = NSwitch(self, height=iPx)
1109
+
1110
+ self.indentWidth = NDoubleSpinBox(self)
1111
+ self.indentWidth.setFixedWidth(spW)
1112
+ self.indentWidth.setMinimum(0.1)
1113
+ self.indentWidth.setMaximum(9.9)
1114
+ self.indentWidth.setSingleStep(0.1)
1115
+ self.indentWidth.setDecimals(1)
1116
+
1117
+ self.addRow(self._build.getLabel("format.firstLineIndent"), self.firstIndent)
1118
+ self.addRow(self._build.getLabel("format.firstIndentWidth"), self.indentWidth, unit="em")
1119
+ self.addRow(self._build.getLabel("format.indentFirstPar"), self.indentFirstPar)
1115
1120
 
1116
1121
  # Page Layout
1117
1122
  # ===========
@@ -1164,17 +1169,21 @@ class _FormatTab(NScrollableForm):
1164
1169
 
1165
1170
  def loadContent(self) -> None:
1166
1171
  """Populate the widgets."""
1167
- textFont = self._build.getStr("format.textFont")
1168
- if not textFont:
1169
- textFont = str(CONFIG.textFont)
1172
+ self._textFont = QFont()
1173
+ self._textFont.fromString(self._build.getStr("format.textFont"))
1170
1174
 
1171
- self.textFont.setText(textFont)
1172
- self.textSize.setValue(self._build.getInt("format.textSize"))
1173
- self.lineHeight.setValue(self._build.getFloat("format.lineHeight"))
1175
+ self.textFont.setText(describeFont(self._textFont))
1176
+ self.textFont.setCursorPosition(0)
1174
1177
 
1178
+ self.lineHeight.setValue(self._build.getFloat("format.lineHeight"))
1175
1179
  self.justifyText.setChecked(self._build.getBool("format.justifyText"))
1176
1180
  self.stripUnicode.setChecked(self._build.getBool("format.stripUnicode"))
1177
1181
  self.replaceTabs.setChecked(self._build.getBool("format.replaceTabs"))
1182
+ self.keepBreaks.setChecked(self._build.getBool("format.keepBreaks"))
1183
+
1184
+ self.firstIndent.setChecked(self._build.getBool("format.firstLineIndent"))
1185
+ self.indentWidth.setValue(self._build.getFloat("format.firstIndentWidth"))
1186
+ self.indentFirstPar.setChecked(self._build.getBool("format.indentFirstPar"))
1178
1187
 
1179
1188
  pageUnit = self._build.getStr("format.pageUnit")
1180
1189
  index = self.pageUnit.findData(pageUnit)
@@ -1203,13 +1212,17 @@ class _FormatTab(NScrollableForm):
1203
1212
 
1204
1213
  def saveContent(self) -> None:
1205
1214
  """Save choices back into build object."""
1206
- self._build.setValue("format.textFont", self.textFont.text())
1207
- self._build.setValue("format.textSize", self.textSize.value())
1215
+ self._build.setValue("format.textFont", self._textFont.toString())
1208
1216
  self._build.setValue("format.lineHeight", self.lineHeight.value())
1209
1217
 
1210
1218
  self._build.setValue("format.justifyText", self.justifyText.isChecked())
1211
1219
  self._build.setValue("format.stripUnicode", self.stripUnicode.isChecked())
1212
1220
  self._build.setValue("format.replaceTabs", self.replaceTabs.isChecked())
1221
+ self._build.setValue("format.keepBreaks", self.keepBreaks.isChecked())
1222
+
1223
+ self._build.setValue("format.firstLineIndent", self.firstIndent.isChecked())
1224
+ self._build.setValue("format.firstIndentWidth", self.indentWidth.value())
1225
+ self._build.setValue("format.indentFirstPar", self.indentFirstPar.isChecked())
1213
1226
 
1214
1227
  self._build.setValue("format.pageUnit", str(self.pageUnit.currentData()))
1215
1228
  self._build.setValue("format.pageSize", str(self.pageSize.currentData()))
@@ -1228,13 +1241,11 @@ class _FormatTab(NScrollableForm):
1228
1241
  @pyqtSlot()
1229
1242
  def _selectFont(self) -> None:
1230
1243
  """Open the QFontDialog and set a font for the font style."""
1231
- currFont = QFont()
1232
- currFont.setFamily(self.textFont.text())
1233
- currFont.setPointSize(self.textSize.value())
1234
- newFont, status = QFontDialog.getFont(currFont, self)
1244
+ font, status = SHARED.getFont(self._textFont, CONFIG.nativeFont)
1235
1245
  if status:
1236
- self.textFont.setText(newFont.family())
1237
- self.textSize.setValue(newFont.pointSize())
1246
+ self.textFont.setText(describeFont(font))
1247
+ self.textFont.setCursorPosition(0)
1248
+ self._textFont = font
1238
1249
  return
1239
1250
 
1240
1251
  @pyqtSlot(int)
@@ -1319,13 +1330,11 @@ class _FormatTab(NScrollableForm):
1319
1330
  self.pageSize.setCurrentIndex(index)
1320
1331
  return
1321
1332
 
1322
- # END Class _FormatTab
1323
-
1324
1333
 
1325
1334
  class _OutputTab(NScrollableForm):
1326
1335
 
1327
- def __init__(self, buildMain: GuiBuildSettings, build: BuildSettings) -> None:
1328
- super().__init__(parent=buildMain)
1336
+ def __init__(self, parent: QWidget, build: BuildSettings) -> None:
1337
+ super().__init__(parent=parent)
1329
1338
 
1330
1339
  self._build = build
1331
1340
 
@@ -1355,9 +1364,6 @@ class _OutputTab(NScrollableForm):
1355
1364
  self.odtPageCountOffset.setMinimumWidth(spW)
1356
1365
  self.addRow(self._build.getLabel("odt.pageCountOffset"), self.odtPageCountOffset)
1357
1366
 
1358
- self.odtFirstLineIndent = NSwitch(self, height=iPx)
1359
- self.addRow(self._build.getLabel("odt.firstLineIndent"), self.odtFirstLineIndent)
1360
-
1361
1367
  # HTML Document
1362
1368
  self.addGroupLabel(self._build.getLabel("html"))
1363
1369
 
@@ -1367,12 +1373,6 @@ class _OutputTab(NScrollableForm):
1367
1373
  self.htmlPreserveTabs = NSwitch(self, height=iPx)
1368
1374
  self.addRow(self._build.getLabel("html.preserveTabs"), self.htmlPreserveTabs)
1369
1375
 
1370
- # Markdown Document
1371
- self.addGroupLabel(self._build.getLabel("md"))
1372
-
1373
- self.mdPreserveBreaks = NSwitch(self, height=iPx)
1374
- self.addRow(self._build.getLabel("md.preserveBreaks"), self.mdPreserveBreaks)
1375
-
1376
1376
  # Finalise
1377
1377
  self.finalise()
1378
1378
 
@@ -1383,10 +1383,8 @@ class _OutputTab(NScrollableForm):
1383
1383
  self.odtAddColours.setChecked(self._build.getBool("odt.addColours"))
1384
1384
  self.odtPageHeader.setText(self._build.getStr("odt.pageHeader"))
1385
1385
  self.odtPageCountOffset.setValue(self._build.getInt("odt.pageCountOffset"))
1386
- self.odtFirstLineIndent.setChecked(self._build.getBool("odt.firstLineIndent"))
1387
1386
  self.htmlAddStyles.setChecked(self._build.getBool("html.addStyles"))
1388
1387
  self.htmlPreserveTabs.setChecked(self._build.getBool("html.preserveTabs"))
1389
- self.mdPreserveBreaks.setChecked(self._build.getBool("md.preserveBreaks"))
1390
1388
  self.odtPageHeader.setCursorPosition(0)
1391
1389
  return
1392
1390
 
@@ -1395,10 +1393,8 @@ class _OutputTab(NScrollableForm):
1395
1393
  self._build.setValue("odt.addColours", self.odtAddColours.isChecked())
1396
1394
  self._build.setValue("odt.pageHeader", self.odtPageHeader.text())
1397
1395
  self._build.setValue("odt.pageCountOffset", self.odtPageCountOffset.value())
1398
- self._build.setValue("odt.firstLineIndent", self.odtFirstLineIndent.isChecked())
1399
1396
  self._build.setValue("html.addStyles", self.htmlAddStyles.isChecked())
1400
1397
  self._build.setValue("html.preserveTabs", self.htmlPreserveTabs.isChecked())
1401
- self._build.setValue("md.preserveBreaks", self.mdPreserveBreaks.isChecked())
1402
1398
  return
1403
1399
 
1404
1400
  ##
@@ -1410,5 +1406,3 @@ class _OutputTab(NScrollableForm):
1410
1406
  self.odtPageHeader.setText(nwHeadFmt.ODT_AUTO)
1411
1407
  self.odtPageHeader.setCursorPosition(0)
1412
1408
  return
1413
-
1414
- # END Class _OutputTab
@@ -23,21 +23,22 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
23
23
  """
24
24
  from __future__ import annotations
25
25
 
26
- import math
27
26
  import logging
27
+ import math
28
28
 
29
29
  from PyQt5.QtCore import pyqtSlot
30
30
  from PyQt5.QtGui import QCloseEvent
31
31
  from PyQt5.QtWidgets import (
32
- QAbstractItemView, QDialog, QDialogButtonBox, QFormLayout, QGridLayout,
33
- QHBoxLayout, QLabel, QSpinBox, QStackedWidget, QTreeWidget,
34
- QTreeWidgetItem, QVBoxLayout, QWidget
32
+ QAbstractItemView, QDialogButtonBox, QFormLayout, QGridLayout, QHBoxLayout,
33
+ QLabel, QSpinBox, QStackedWidget, QTreeWidget, QTreeWidgetItem,
34
+ QVBoxLayout, QWidget
35
35
  )
36
36
 
37
37
  from novelwriter import CONFIG, SHARED
38
38
  from novelwriter.common import formatTime, numberToRoman
39
39
  from novelwriter.constants import nwUnicode
40
40
  from novelwriter.extensions.configlayout import NColourLabel, NFixedPage, NScrollablePage
41
+ from novelwriter.extensions.modified import NNonBlockingDialog
41
42
  from novelwriter.extensions.novelselector import NovelSelector
42
43
  from novelwriter.extensions.pagedsidebar import NPagedSideBar
43
44
  from novelwriter.extensions.switch import NSwitch
@@ -46,7 +47,7 @@ from novelwriter.types import QtAlignRight, QtDecoration, QtDialogClose
46
47
  logger = logging.getLogger(__name__)
47
48
 
48
49
 
49
- class GuiNovelDetails(QDialog):
50
+ class GuiNovelDetails(NNonBlockingDialog):
50
51
 
51
52
  PAGE_OVERVIEW = 1
52
53
  PAGE_CONTENTS = 2
@@ -185,8 +186,6 @@ class GuiNovelDetails(QDialog):
185
186
 
186
187
  return
187
188
 
188
- # END Class GuiNovelDetails
189
-
190
189
 
191
190
  class _OverviewPage(NScrollablePage):
192
191
 
@@ -293,8 +292,6 @@ class _OverviewPage(NScrollablePage):
293
292
 
294
293
  return
295
294
 
296
- # END Class _OverviewPage
297
-
298
295
 
299
296
  class _ContentsPage(NFixedPage):
300
297
 
@@ -523,5 +520,3 @@ class _ContentsPage(NFixedPage):
523
520
  self._data = SHARED.project.index.getTableOfContents(rootHandle, 2)
524
521
  self._data.append(("", 0, self.tr("END"), 0))
525
522
  return
526
-
527
- # END Class _ContentsPage
@@ -32,11 +32,11 @@ from PyQt5.QtCore import (
32
32
  QAbstractListModel, QEvent, QModelIndex, QObject, QPoint, QSize, Qt,
33
33
  pyqtSignal, pyqtSlot
34
34
  )
35
- from PyQt5.QtGui import QCloseEvent, QColor, QFont, QPaintEvent, QPainter, QPen
35
+ from PyQt5.QtGui import QCloseEvent, QColor, QFont, QPainter, QPaintEvent, QPen
36
36
  from PyQt5.QtWidgets import (
37
37
  QAction, QApplication, QDialog, QFileDialog, QFormLayout, QHBoxLayout,
38
38
  QLabel, QLineEdit, QListView, QMenu, QPushButton, QScrollArea, QShortcut,
39
- QStackedWidget, QStyleOptionViewItem, QStyledItemDelegate, QVBoxLayout,
39
+ QStackedWidget, QStyledItemDelegate, QStyleOptionViewItem, QVBoxLayout,
40
40
  QWidget
41
41
  )
42
42
 
@@ -267,8 +267,6 @@ class GuiWelcome(QDialog):
267
267
  self.btnCreate.setFocus()
268
268
  return
269
269
 
270
- # END Class GuiWelcome
271
-
272
270
 
273
271
  class _OpenProjectPage(QWidget):
274
272
 
@@ -392,8 +390,6 @@ class _OpenProjectPage(QWidget):
392
390
  self._projectClicked(index)
393
391
  return
394
392
 
395
- # END Class _OpenProjectPage
396
-
397
393
 
398
394
  class _ProjectListItem(QStyledItemDelegate):
399
395
 
@@ -450,8 +446,6 @@ class _ProjectListItem(QStyledItemDelegate):
450
446
  """Set the size hint to fixed height."""
451
447
  return QSize(opt.rect.width(), self._hPx)
452
448
 
453
- # END Class _ProjectListItem
454
-
455
449
 
456
450
  class _ProjectListModel(QAbstractListModel):
457
451
 
@@ -491,8 +485,6 @@ class _ProjectListModel(QAbstractListModel):
491
485
  return True
492
486
  return False
493
487
 
494
- # END Class _ProjectListModel
495
-
496
488
 
497
489
  class _NewProjectPage(QWidget):
498
490
 
@@ -548,8 +540,6 @@ class _NewProjectPage(QWidget):
548
540
  self.openProjectRequest.emit(path)
549
541
  return
550
542
 
551
- # END Class _NewProjectPage
552
-
553
543
 
554
544
  class _NewProjectForm(QWidget):
555
545
 
@@ -805,8 +795,6 @@ class _NewProjectForm(QWidget):
805
795
 
806
796
  return
807
797
 
808
- # END Class _NewProjectForm
809
-
810
798
 
811
799
  class _PopLeftDirectionMenu(QMenu):
812
800
 
@@ -817,5 +805,3 @@ class _PopLeftDirectionMenu(QMenu):
817
805
  offset = QPoint(parent.width() - self.width(), parent.height())
818
806
  self.move(parent.mapToGlobal(offset))
819
807
  return super(_PopLeftDirectionMenu, self).event(event)
820
-
821
- # END Class _PopLeftDirectionMenu
@@ -32,15 +32,16 @@ from typing import TYPE_CHECKING
32
32
  from PyQt5.QtCore import Qt, pyqtSlot
33
33
  from PyQt5.QtGui import QCloseEvent, QCursor, QPixmap
34
34
  from PyQt5.QtWidgets import (
35
- QAction, QApplication, QDialog, QDialogButtonBox, QFileDialog, QGridLayout,
35
+ QAction, QApplication, QDialogButtonBox, QFileDialog, QGridLayout,
36
36
  QGroupBox, QHBoxLayout, QLabel, QMenu, QSpinBox, QTreeWidget,
37
37
  QTreeWidgetItem
38
38
  )
39
39
 
40
40
  from novelwriter import CONFIG, SHARED
41
- from novelwriter.common import formatTime, checkInt, checkIntTuple, minmax
41
+ from novelwriter.common import checkInt, checkIntTuple, formatTime, minmax
42
42
  from novelwriter.constants import nwConst
43
43
  from novelwriter.error import formatException
44
+ from novelwriter.extensions.modified import NToolDialog
44
45
  from novelwriter.extensions.switch import NSwitch
45
46
  from novelwriter.types import (
46
47
  QtAlignLeftMiddle, QtAlignRight, QtAlignRightMiddle, QtDecoration,
@@ -53,7 +54,7 @@ if TYPE_CHECKING: # pragma: no cover
53
54
  logger = logging.getLogger(__name__)
54
55
 
55
56
 
56
- class GuiWritingStats(QDialog):
57
+ class GuiWritingStats(NToolDialog):
57
58
  """GUI Tools: Writing Statistics
58
59
 
59
60
  Displays data from the NWSessionLog object.
@@ -68,13 +69,11 @@ class GuiWritingStats(QDialog):
68
69
  FMT_JSON = 0
69
70
  FMT_CSV = 1
70
71
 
71
- def __init__(self, mainGui: GuiMain) -> None:
72
- super().__init__(parent=mainGui)
72
+ def __init__(self, parent: GuiMain) -> None:
73
+ super().__init__(parent=parent)
73
74
 
74
75
  logger.debug("Create: GuiWritingStats")
75
76
  self.setObjectName("GuiWritingStats")
76
- if CONFIG.osDarwin:
77
- self.setWindowFlag(Qt.WindowType.Tool)
78
77
 
79
78
  self.logData = []
80
79
  self.filterData = []
@@ -615,5 +614,3 @@ class GuiWritingStats(QDialog):
615
614
  self.labelFilter.setText(formatTime(round(self.timeFilter)))
616
615
 
617
616
  return
618
-
619
- # END Class GuiWritingStats
novelwriter/types.py CHANGED
@@ -23,9 +23,9 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
23
23
  """
24
24
  from __future__ import annotations
25
25
 
26
- from PyQt5.QtCore import Qt
27
- from PyQt5.QtGui import QColor, QPainter, QTextCursor
28
- from PyQt5.QtWidgets import QDialogButtonBox, QStyle
26
+ from PyQt5.QtCore import QRegularExpression, Qt
27
+ from PyQt5.QtGui import QColor, QFont, QPainter, QTextCharFormat, QTextCursor, QTextFormat
28
+ from PyQt5.QtWidgets import QDialogButtonBox, QSizePolicy, QStyle
29
29
 
30
30
  # Qt Alignment Flags
31
31
 
@@ -44,9 +44,19 @@ QtAlignRightMiddle = Qt.AlignmentFlag.AlignRight | Qt.AlignmentFlag.AlignVCenter
44
44
  QtAlignRightTop = Qt.AlignmentFlag.AlignRight | Qt.AlignmentFlag.AlignTop
45
45
  QtAlignTop = Qt.AlignmentFlag.AlignTop
46
46
 
47
+ QtVAlignNormal = QTextCharFormat.VerticalAlignment.AlignNormal
48
+ QtVAlignSub = QTextCharFormat.VerticalAlignment.AlignSubScript
49
+ QtVAlignSuper = QTextCharFormat.VerticalAlignment.AlignSuperScript
50
+
51
+ # Qt Page Break
52
+
53
+ QtPageBreakBefore = QTextFormat.PageBreakFlag.PageBreak_AlwaysBefore
54
+ QtPageBreakAfter = QTextFormat.PageBreakFlag.PageBreak_AlwaysAfter
55
+
47
56
  # Qt Painter Types
48
57
 
49
58
  QtTransparent = QColor(0, 0, 0, 0)
59
+ QtBlack = QColor(0, 0, 0)
50
60
  QtNoBrush = Qt.BrushStyle.NoBrush
51
61
  QtNoPen = Qt.PenStyle.NoPen
52
62
  QtRoundCap = Qt.PenCapStyle.RoundCap
@@ -88,3 +98,35 @@ QtKeepAnchor = QTextCursor.MoveMode.KeepAnchor
88
98
  QtMoveAnchor = QTextCursor.MoveMode.MoveAnchor
89
99
  QtMoveLeft = QTextCursor.MoveOperation.Left
90
100
  QtMoveRight = QTextCursor.MoveOperation.Right
101
+
102
+ # Size Policy
103
+
104
+ QtSizeExpanding = QSizePolicy.Policy.Expanding
105
+ QtSizeFixed = QSizePolicy.Policy.Fixed
106
+ QtSizeIgnored = QSizePolicy.Policy.Ignored
107
+ QtSizeMinimum = QSizePolicy.Policy.Minimum
108
+ QtSizeMinimumExpanding = QSizePolicy.Policy.MinimumExpanding
109
+
110
+ # Other
111
+
112
+ QRegExUnicode = QRegularExpression.PatternOption.UseUnicodePropertiesOption
113
+
114
+ # Maps
115
+
116
+ FONT_WEIGHTS: dict[int, int] = {
117
+ QFont.Weight.Thin: 100,
118
+ QFont.Weight.ExtraLight: 200,
119
+ QFont.Weight.Light: 300,
120
+ QFont.Weight.Normal: 400,
121
+ QFont.Weight.Medium: 500,
122
+ QFont.Weight.DemiBold: 600,
123
+ QFont.Weight.Bold: 700,
124
+ QFont.Weight.ExtraBold: 800,
125
+ QFont.Weight.Black: 900,
126
+ }
127
+
128
+ FONT_STYLE: dict[int, str] = {
129
+ QFont.Style.StyleNormal: "normal",
130
+ QFont.Style.StyleItalic: "italic",
131
+ QFont.Style.StyleOblique: "oblique",
132
+ }