novelWriter 2.4.4__py3-none-any.whl → 2.5__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 (122) hide show
  1. {novelWriter-2.4.4.dist-info → novelWriter-2.5.dist-info}/METADATA +4 -5
  2. {novelWriter-2.4.4.dist-info → novelWriter-2.5.dist-info}/RECORD +121 -111
  3. {novelWriter-2.4.4.dist-info → novelWriter-2.5.dist-info}/WHEEL +1 -1
  4. novelwriter/__init__.py +33 -39
  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_zh_CN.qm +0 -0
  16. novelwriter/assets/i18n/project_en_GB.json +1 -0
  17. novelwriter/assets/i18n/project_pl_PL.json +116 -0
  18. novelwriter/assets/icons/typicons_dark/icons.conf +2 -0
  19. novelwriter/assets/icons/typicons_dark/nw_font.svg +4 -0
  20. novelwriter/assets/icons/typicons_dark/nw_quote.svg +4 -0
  21. novelwriter/assets/icons/typicons_light/icons.conf +2 -0
  22. novelwriter/assets/icons/typicons_light/nw_font.svg +4 -0
  23. novelwriter/assets/icons/typicons_light/nw_quote.svg +4 -0
  24. novelwriter/assets/manual.pdf +0 -0
  25. novelwriter/assets/sample.zip +0 -0
  26. novelwriter/assets/syntax/cyberpunk_night.conf +5 -3
  27. novelwriter/assets/syntax/default_dark.conf +32 -18
  28. novelwriter/assets/syntax/default_light.conf +24 -10
  29. novelwriter/assets/syntax/dracula.conf +44 -0
  30. novelwriter/assets/syntax/grey_dark.conf +5 -4
  31. novelwriter/assets/syntax/grey_light.conf +5 -4
  32. novelwriter/assets/syntax/light_owl.conf +7 -6
  33. novelwriter/assets/syntax/night_owl.conf +7 -6
  34. novelwriter/assets/syntax/snazzy.conf +42 -0
  35. novelwriter/assets/syntax/solarized_dark.conf +4 -3
  36. novelwriter/assets/syntax/solarized_light.conf +4 -3
  37. novelwriter/assets/syntax/tango.conf +27 -11
  38. novelwriter/assets/syntax/tomorrow.conf +6 -5
  39. novelwriter/assets/syntax/tomorrow_night.conf +7 -6
  40. novelwriter/assets/syntax/tomorrow_night_blue.conf +6 -5
  41. novelwriter/assets/syntax/tomorrow_night_bright.conf +6 -5
  42. novelwriter/assets/syntax/tomorrow_night_eighties.conf +6 -5
  43. novelwriter/assets/text/credits_en.htm +52 -41
  44. novelwriter/assets/themes/cyberpunk_night.conf +3 -0
  45. novelwriter/assets/themes/default_dark.conf +2 -0
  46. novelwriter/assets/themes/default_light.conf +2 -0
  47. novelwriter/assets/themes/dracula.conf +48 -0
  48. novelwriter/assets/themes/solarized_dark.conf +2 -0
  49. novelwriter/assets/themes/solarized_light.conf +2 -0
  50. novelwriter/common.py +33 -12
  51. novelwriter/config.py +184 -98
  52. novelwriter/constants.py +47 -35
  53. novelwriter/core/buildsettings.py +68 -69
  54. novelwriter/core/coretools.py +5 -23
  55. novelwriter/core/docbuild.py +52 -40
  56. novelwriter/core/document.py +3 -5
  57. novelwriter/core/index.py +115 -45
  58. novelwriter/core/item.py +8 -19
  59. novelwriter/core/options.py +2 -4
  60. novelwriter/core/project.py +37 -61
  61. novelwriter/core/projectdata.py +1 -3
  62. novelwriter/core/projectxml.py +12 -15
  63. novelwriter/core/sessions.py +3 -5
  64. novelwriter/core/spellcheck.py +4 -9
  65. novelwriter/core/status.py +211 -164
  66. novelwriter/core/storage.py +0 -8
  67. novelwriter/core/tohtml.py +139 -105
  68. novelwriter/core/tokenizer.py +278 -122
  69. novelwriter/core/{tomd.py → tomarkdown.py} +97 -78
  70. novelwriter/core/toodt.py +257 -166
  71. novelwriter/core/toqdoc.py +419 -0
  72. novelwriter/core/tree.py +5 -7
  73. novelwriter/dialogs/about.py +11 -18
  74. novelwriter/dialogs/docmerge.py +17 -19
  75. novelwriter/dialogs/docsplit.py +17 -19
  76. novelwriter/dialogs/editlabel.py +6 -10
  77. novelwriter/dialogs/preferences.py +200 -164
  78. novelwriter/dialogs/projectsettings.py +225 -189
  79. novelwriter/dialogs/quotes.py +12 -9
  80. novelwriter/dialogs/wordlist.py +9 -15
  81. novelwriter/enum.py +35 -30
  82. novelwriter/error.py +8 -15
  83. novelwriter/extensions/configlayout.py +55 -21
  84. novelwriter/extensions/eventfilters.py +1 -5
  85. novelwriter/extensions/modified.py +58 -14
  86. novelwriter/extensions/novelselector.py +1 -3
  87. novelwriter/extensions/pagedsidebar.py +9 -12
  88. novelwriter/extensions/{circularprogress.py → progressbars.py} +30 -8
  89. novelwriter/extensions/statusled.py +40 -26
  90. novelwriter/extensions/switch.py +4 -6
  91. novelwriter/extensions/switchbox.py +7 -6
  92. novelwriter/extensions/versioninfo.py +3 -9
  93. novelwriter/gui/doceditor.py +120 -139
  94. novelwriter/gui/dochighlight.py +231 -186
  95. novelwriter/gui/docviewer.py +69 -108
  96. novelwriter/gui/docviewerpanel.py +3 -10
  97. novelwriter/gui/editordocument.py +1 -3
  98. novelwriter/gui/itemdetails.py +7 -11
  99. novelwriter/gui/mainmenu.py +22 -18
  100. novelwriter/gui/noveltree.py +11 -24
  101. novelwriter/gui/outline.py +15 -26
  102. novelwriter/gui/projtree.py +35 -60
  103. novelwriter/gui/search.py +10 -3
  104. novelwriter/gui/sidebar.py +2 -6
  105. novelwriter/gui/statusbar.py +29 -37
  106. novelwriter/gui/theme.py +26 -48
  107. novelwriter/guimain.py +162 -160
  108. novelwriter/shared.py +36 -32
  109. novelwriter/text/patterns.py +113 -0
  110. novelwriter/tools/dictionaries.py +10 -20
  111. novelwriter/tools/lipsum.py +10 -16
  112. novelwriter/tools/manusbuild.py +9 -11
  113. novelwriter/tools/manuscript.py +71 -145
  114. novelwriter/tools/manussettings.py +71 -75
  115. novelwriter/tools/noveldetails.py +16 -21
  116. novelwriter/tools/welcome.py +21 -26
  117. novelwriter/tools/writingstats.py +9 -12
  118. novelwriter/types.py +49 -4
  119. novelwriter/extensions/simpleprogress.py +0 -55
  120. {novelWriter-2.4.4.dist-info → novelWriter-2.5.dist-info}/LICENSE.md +0 -0
  121. {novelWriter-2.4.4.dist-info → novelWriter-2.5.dist-info}/entry_points.txt +0 -0
  122. {novelWriter-2.4.4.dist-info → novelWriter-2.5.dist-info}/top_level.txt +0 -0
@@ -27,23 +27,24 @@ 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, QDialogButtonBox, QFontDialog, QFrame,
34
- 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
46
  from novelwriter.extensions.modified import (
46
- NComboBox, NDialog, NDoubleSpinBox, NIconToolButton, NSpinBox
47
+ NComboBox, NDoubleSpinBox, NIconToolButton, NSpinBox, NToolDialog
47
48
  )
48
49
  from novelwriter.extensions.pagedsidebar import NPagedSideBar
49
50
  from novelwriter.extensions.switch import NSwitch
@@ -59,7 +60,7 @@ if TYPE_CHECKING: # pragma: no cover
59
60
  logger = logging.getLogger(__name__)
60
61
 
61
62
 
62
- class GuiBuildSettings(NDialog):
63
+ class GuiBuildSettings(NToolDialog):
63
64
  """GUI Tools: Manuscript Build Settings Dialog
64
65
 
65
66
  The main tool for configuring manuscript builds. It's a GUI tool for
@@ -74,13 +75,11 @@ class GuiBuildSettings(NDialog):
74
75
 
75
76
  newSettingsReady = pyqtSignal(BuildSettings)
76
77
 
77
- def __init__(self, mainGui: GuiMain, build: BuildSettings) -> None:
78
- super().__init__(parent=mainGui)
78
+ def __init__(self, parent: GuiMain, build: BuildSettings) -> None:
79
+ super().__init__(parent=parent)
79
80
 
80
81
  logger.debug("Create: GuiBuildSettings")
81
82
  self.setObjectName("GuiBuildSettings")
82
- if CONFIG.osDarwin:
83
- self.setWindowFlag(Qt.WindowType.Tool)
84
83
 
85
84
  self._build = build
86
85
 
@@ -99,8 +98,8 @@ class GuiBuildSettings(NDialog):
99
98
 
100
99
  # Title
101
100
  self.titleLabel = NColourLabel(
102
- self.tr("Manuscript Build Settings"), SHARED.theme.helpText,
103
- parent=self, scale=NColourLabel.HEADER_SCALE, indent=CONFIG.pxInt(4)
101
+ self.tr("Manuscript Build Settings"), self, color=SHARED.theme.helpText,
102
+ scale=NColourLabel.HEADER_SCALE, indent=CONFIG.pxInt(4)
104
103
  )
105
104
 
106
105
  # Settings Name
@@ -280,8 +279,6 @@ class GuiBuildSettings(NDialog):
280
279
  self._build.resetChangedState()
281
280
  return
282
281
 
283
- # END Class GuiBuildSettings
284
-
285
282
 
286
283
  class _FilterTab(NFixedPage):
287
284
 
@@ -298,8 +295,8 @@ class _FilterTab(NFixedPage):
298
295
  F_INCLUDED = 2
299
296
  F_EXCLUDED = 3
300
297
 
301
- def __init__(self, buildMain: GuiBuildSettings, build: BuildSettings) -> None:
302
- super().__init__(parent=buildMain)
298
+ def __init__(self, parent: QWidget, build: BuildSettings) -> None:
299
+ super().__init__(parent=parent)
303
300
 
304
301
  self._treeMap: dict[str, QTreeWidgetItem] = {}
305
302
  self._build = build
@@ -576,8 +573,6 @@ class _FilterTab(NFixedPage):
576
573
  self._scanChildren(item.child(i), items)
577
574
  return items
578
575
 
579
- # END Class _FilterTab
580
-
581
576
 
582
577
  class _HeadingsTab(NScrollablePage):
583
578
 
@@ -588,8 +583,8 @@ class _HeadingsTab(NScrollablePage):
588
583
  EDIT_HSCENE = 5
589
584
  EDIT_SECTION = 6
590
585
 
591
- def __init__(self, buildMain: GuiBuildSettings, build: BuildSettings) -> None:
592
- super().__init__(parent=buildMain)
586
+ def __init__(self, parent: QWidget, build: BuildSettings) -> None:
587
+ super().__init__(parent=parent)
593
588
 
594
589
  self._build = build
595
590
  self._editing = 0
@@ -943,8 +938,6 @@ class _HeadingsTab(NScrollablePage):
943
938
 
944
939
  return
945
940
 
946
- # END Class _HeadingsTab
947
-
948
941
 
949
942
  class _HeadingSyntaxHighlighter(QSyntaxHighlighter):
950
943
 
@@ -969,13 +962,11 @@ class _HeadingSyntaxHighlighter(QSyntaxHighlighter):
969
962
  self.setFormat(pos + ddots, 1, self._fmtSymbol)
970
963
  return
971
964
 
972
- # END Class _HeadingSyntaxHighlighter
973
-
974
965
 
975
966
  class _ContentTab(NScrollableForm):
976
967
 
977
- def __init__(self, buildMain: GuiBuildSettings, build: BuildSettings) -> None:
978
- super().__init__(parent=buildMain)
968
+ def __init__(self, parent: QWidget, build: BuildSettings) -> None:
969
+ super().__init__(parent=parent)
979
970
 
980
971
  self._build = build
981
972
 
@@ -1054,16 +1045,15 @@ class _ContentTab(NScrollableForm):
1054
1045
  self.ignoredKeywords.setText(", ".join(verified))
1055
1046
  return
1056
1047
 
1057
- # END Class _ContentTab
1058
-
1059
1048
 
1060
1049
  class _FormatTab(NScrollableForm):
1061
1050
 
1062
- def __init__(self, buildMain: GuiBuildSettings, build: BuildSettings) -> None:
1063
- super().__init__(parent=buildMain)
1051
+ def __init__(self, parent: QWidget, build: BuildSettings) -> None:
1052
+ super().__init__(parent=parent)
1064
1053
 
1065
1054
  self._build = build
1066
1055
  self._unitScale = 1.0
1056
+ self._textFont = QFont(CONFIG.textFont)
1067
1057
 
1068
1058
  iPx = SHARED.theme.baseIconHeight
1069
1059
  iSz = SHARED.theme.baseIconSize
@@ -1075,24 +1065,16 @@ class _FormatTab(NScrollableForm):
1075
1065
 
1076
1066
  self.addGroupLabel(self._build.getLabel("format.grpFormat"))
1077
1067
 
1078
- # Font Family
1068
+ # Text Font
1079
1069
  self.textFont = QLineEdit(self)
1080
1070
  self.textFont.setReadOnly(True)
1081
- self.btnTextFont = NIconToolButton(self, iSz, "more")
1071
+ self.btnTextFont = NIconToolButton(self, iSz, "font")
1082
1072
  self.btnTextFont.clicked.connect(self._selectFont)
1083
1073
  self.addRow(
1084
1074
  self._build.getLabel("format.textFont"), self.textFont,
1085
- button=self.btnTextFont, stretch=(3, 2)
1075
+ button=self.btnTextFont, stretch=(1, 1)
1086
1076
  )
1087
1077
 
1088
- # Font Size
1089
- self.textSize = NSpinBox(self)
1090
- self.textSize.setMinimum(8)
1091
- self.textSize.setMaximum(60)
1092
- self.textSize.setSingleStep(1)
1093
- self.textSize.setMinimumWidth(spW)
1094
- self.addRow(self._build.getLabel("format.textSize"), self.textSize, unit="pt")
1095
-
1096
1078
  # Line Height
1097
1079
  self.lineHeight = NDoubleSpinBox(self)
1098
1080
  self.lineHeight.setFixedWidth(spW)
@@ -1110,10 +1092,33 @@ class _FormatTab(NScrollableForm):
1110
1092
  self.justifyText = NSwitch(self, height=iPx)
1111
1093
  self.stripUnicode = NSwitch(self, height=iPx)
1112
1094
  self.replaceTabs = NSwitch(self, height=iPx)
1095
+ self.keepBreaks = NSwitch(self, height=iPx)
1096
+ self.showDialogue = NSwitch(self, height=iPx)
1113
1097
 
1114
1098
  self.addRow(self._build.getLabel("format.justifyText"), self.justifyText)
1115
1099
  self.addRow(self._build.getLabel("format.stripUnicode"), self.stripUnicode)
1116
1100
  self.addRow(self._build.getLabel("format.replaceTabs"), self.replaceTabs)
1101
+ self.addRow(self._build.getLabel("format.keepBreaks"), self.keepBreaks)
1102
+ self.addRow(self._build.getLabel("format.showDialogue"), self.showDialogue)
1103
+
1104
+ # First Line Indent
1105
+ # =================
1106
+
1107
+ self.addGroupLabel(self._build.getLabel("format.grpParIndent"))
1108
+
1109
+ self.firstIndent = NSwitch(self, height=iPx)
1110
+ self.indentFirstPar = NSwitch(self, height=iPx)
1111
+
1112
+ self.indentWidth = NDoubleSpinBox(self)
1113
+ self.indentWidth.setFixedWidth(spW)
1114
+ self.indentWidth.setMinimum(0.1)
1115
+ self.indentWidth.setMaximum(9.9)
1116
+ self.indentWidth.setSingleStep(0.1)
1117
+ self.indentWidth.setDecimals(1)
1118
+
1119
+ self.addRow(self._build.getLabel("format.firstLineIndent"), self.firstIndent)
1120
+ self.addRow(self._build.getLabel("format.firstIndentWidth"), self.indentWidth, unit="em")
1121
+ self.addRow(self._build.getLabel("format.indentFirstPar"), self.indentFirstPar)
1117
1122
 
1118
1123
  # Page Layout
1119
1124
  # ===========
@@ -1166,17 +1171,22 @@ class _FormatTab(NScrollableForm):
1166
1171
 
1167
1172
  def loadContent(self) -> None:
1168
1173
  """Populate the widgets."""
1169
- textFont = self._build.getStr("format.textFont")
1170
- if not textFont:
1171
- textFont = str(CONFIG.textFont)
1174
+ self._textFont = QFont()
1175
+ self._textFont.fromString(self._build.getStr("format.textFont"))
1172
1176
 
1173
- self.textFont.setText(textFont)
1174
- self.textSize.setValue(self._build.getInt("format.textSize"))
1175
- self.lineHeight.setValue(self._build.getFloat("format.lineHeight"))
1177
+ self.textFont.setText(describeFont(self._textFont))
1178
+ self.textFont.setCursorPosition(0)
1176
1179
 
1180
+ self.lineHeight.setValue(self._build.getFloat("format.lineHeight"))
1177
1181
  self.justifyText.setChecked(self._build.getBool("format.justifyText"))
1178
1182
  self.stripUnicode.setChecked(self._build.getBool("format.stripUnicode"))
1179
1183
  self.replaceTabs.setChecked(self._build.getBool("format.replaceTabs"))
1184
+ self.keepBreaks.setChecked(self._build.getBool("format.keepBreaks"))
1185
+ self.showDialogue.setChecked(self._build.getBool("format.showDialogue"))
1186
+
1187
+ self.firstIndent.setChecked(self._build.getBool("format.firstLineIndent"))
1188
+ self.indentWidth.setValue(self._build.getFloat("format.firstIndentWidth"))
1189
+ self.indentFirstPar.setChecked(self._build.getBool("format.indentFirstPar"))
1180
1190
 
1181
1191
  pageUnit = self._build.getStr("format.pageUnit")
1182
1192
  index = self.pageUnit.findData(pageUnit)
@@ -1205,13 +1215,18 @@ class _FormatTab(NScrollableForm):
1205
1215
 
1206
1216
  def saveContent(self) -> None:
1207
1217
  """Save choices back into build object."""
1208
- self._build.setValue("format.textFont", self.textFont.text())
1209
- self._build.setValue("format.textSize", self.textSize.value())
1218
+ self._build.setValue("format.textFont", self._textFont.toString())
1210
1219
  self._build.setValue("format.lineHeight", self.lineHeight.value())
1211
1220
 
1212
1221
  self._build.setValue("format.justifyText", self.justifyText.isChecked())
1213
1222
  self._build.setValue("format.stripUnicode", self.stripUnicode.isChecked())
1214
1223
  self._build.setValue("format.replaceTabs", self.replaceTabs.isChecked())
1224
+ self._build.setValue("format.keepBreaks", self.keepBreaks.isChecked())
1225
+ self._build.setValue("format.showDialogue", self.showDialogue.isChecked())
1226
+
1227
+ self._build.setValue("format.firstLineIndent", self.firstIndent.isChecked())
1228
+ self._build.setValue("format.firstIndentWidth", self.indentWidth.value())
1229
+ self._build.setValue("format.indentFirstPar", self.indentFirstPar.isChecked())
1215
1230
 
1216
1231
  self._build.setValue("format.pageUnit", str(self.pageUnit.currentData()))
1217
1232
  self._build.setValue("format.pageSize", str(self.pageSize.currentData()))
@@ -1230,13 +1245,11 @@ class _FormatTab(NScrollableForm):
1230
1245
  @pyqtSlot()
1231
1246
  def _selectFont(self) -> None:
1232
1247
  """Open the QFontDialog and set a font for the font style."""
1233
- currFont = QFont()
1234
- currFont.setFamily(self.textFont.text())
1235
- currFont.setPointSize(self.textSize.value())
1236
- newFont, status = QFontDialog.getFont(currFont, self)
1248
+ font, status = SHARED.getFont(self._textFont, CONFIG.nativeFont)
1237
1249
  if status:
1238
- self.textFont.setText(newFont.family())
1239
- self.textSize.setValue(newFont.pointSize())
1250
+ self.textFont.setText(describeFont(font))
1251
+ self.textFont.setCursorPosition(0)
1252
+ self._textFont = font
1240
1253
  return
1241
1254
 
1242
1255
  @pyqtSlot(int)
@@ -1321,13 +1334,11 @@ class _FormatTab(NScrollableForm):
1321
1334
  self.pageSize.setCurrentIndex(index)
1322
1335
  return
1323
1336
 
1324
- # END Class _FormatTab
1325
-
1326
1337
 
1327
1338
  class _OutputTab(NScrollableForm):
1328
1339
 
1329
- def __init__(self, buildMain: GuiBuildSettings, build: BuildSettings) -> None:
1330
- super().__init__(parent=buildMain)
1340
+ def __init__(self, parent: QWidget, build: BuildSettings) -> None:
1341
+ super().__init__(parent=parent)
1331
1342
 
1332
1343
  self._build = build
1333
1344
 
@@ -1357,9 +1368,6 @@ class _OutputTab(NScrollableForm):
1357
1368
  self.odtPageCountOffset.setMinimumWidth(spW)
1358
1369
  self.addRow(self._build.getLabel("odt.pageCountOffset"), self.odtPageCountOffset)
1359
1370
 
1360
- self.odtFirstLineIndent = NSwitch(self, height=iPx)
1361
- self.addRow(self._build.getLabel("odt.firstLineIndent"), self.odtFirstLineIndent)
1362
-
1363
1371
  # HTML Document
1364
1372
  self.addGroupLabel(self._build.getLabel("html"))
1365
1373
 
@@ -1369,12 +1377,6 @@ class _OutputTab(NScrollableForm):
1369
1377
  self.htmlPreserveTabs = NSwitch(self, height=iPx)
1370
1378
  self.addRow(self._build.getLabel("html.preserveTabs"), self.htmlPreserveTabs)
1371
1379
 
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
-
1378
1380
  # Finalise
1379
1381
  self.finalise()
1380
1382
 
@@ -1385,10 +1387,8 @@ class _OutputTab(NScrollableForm):
1385
1387
  self.odtAddColours.setChecked(self._build.getBool("odt.addColours"))
1386
1388
  self.odtPageHeader.setText(self._build.getStr("odt.pageHeader"))
1387
1389
  self.odtPageCountOffset.setValue(self._build.getInt("odt.pageCountOffset"))
1388
- self.odtFirstLineIndent.setChecked(self._build.getBool("odt.firstLineIndent"))
1389
1390
  self.htmlAddStyles.setChecked(self._build.getBool("html.addStyles"))
1390
1391
  self.htmlPreserveTabs.setChecked(self._build.getBool("html.preserveTabs"))
1391
- self.mdPreserveBreaks.setChecked(self._build.getBool("md.preserveBreaks"))
1392
1392
  self.odtPageHeader.setCursorPosition(0)
1393
1393
  return
1394
1394
 
@@ -1397,10 +1397,8 @@ class _OutputTab(NScrollableForm):
1397
1397
  self._build.setValue("odt.addColours", self.odtAddColours.isChecked())
1398
1398
  self._build.setValue("odt.pageHeader", self.odtPageHeader.text())
1399
1399
  self._build.setValue("odt.pageCountOffset", self.odtPageCountOffset.value())
1400
- self._build.setValue("odt.firstLineIndent", self.odtFirstLineIndent.isChecked())
1401
1400
  self._build.setValue("html.addStyles", self.htmlAddStyles.isChecked())
1402
1401
  self._build.setValue("html.preserveTabs", self.htmlPreserveTabs.isChecked())
1403
- self._build.setValue("md.preserveBreaks", self.mdPreserveBreaks.isChecked())
1404
1402
  return
1405
1403
 
1406
1404
  ##
@@ -1412,5 +1410,3 @@ class _OutputTab(NScrollableForm):
1412
1410
  self.odtPageHeader.setText(nwHeadFmt.ODT_AUTO)
1413
1411
  self.odtPageHeader.setCursorPosition(0)
1414
1412
  return
1415
-
1416
- # 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
@@ -67,8 +68,8 @@ class GuiNovelDetails(QDialog):
67
68
 
68
69
  # Title
69
70
  self.titleLabel = NColourLabel(
70
- self.tr("Novel Details"), SHARED.theme.helpText,
71
- parent=self, scale=NColourLabel.HEADER_SCALE, indent=CONFIG.pxInt(4)
71
+ self.tr("Novel Details"), self, color=SHARED.theme.helpText,
72
+ scale=NColourLabel.HEADER_SCALE, indent=CONFIG.pxInt(4)
72
73
  )
73
74
 
74
75
  # Novel Selector
@@ -96,7 +97,7 @@ class GuiNovelDetails(QDialog):
96
97
 
97
98
  # Buttons
98
99
  self.buttonBox = QDialogButtonBox(QtDialogClose, self)
99
- self.buttonBox.rejected.connect(self.close)
100
+ self.buttonBox.rejected.connect(self.reject)
100
101
 
101
102
  # Assemble
102
103
  self.topBox = QHBoxLayout()
@@ -149,7 +150,7 @@ class GuiNovelDetails(QDialog):
149
150
  """Capture the user closing the window and save settings."""
150
151
  self._saveSettings()
151
152
  event.accept()
152
- self.deleteLater()
153
+ self.softDelete()
153
154
  return
154
155
 
155
156
  ##
@@ -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
 
@@ -200,8 +199,8 @@ class _OverviewPage(NScrollablePage):
200
199
 
201
200
  # Project Info
202
201
  self.projLabel = NColourLabel(
203
- self.tr("Project"), SHARED.theme.helpText,
204
- parent=self, scale=NColourLabel.HEADER_SCALE
202
+ self.tr("Project"), self, color=SHARED.theme.helpText,
203
+ scale=NColourLabel.HEADER_SCALE
205
204
  )
206
205
 
207
206
  self.projName = QLabel("", self)
@@ -224,8 +223,8 @@ class _OverviewPage(NScrollablePage):
224
223
 
225
224
  # Novel Info
226
225
  self.novelLabel = NColourLabel(
227
- self.tr("Selected Novel"), SHARED.theme.helpText,
228
- parent=self, scale=NColourLabel.HEADER_SCALE
226
+ self.tr("Selected Novel"), self, color=SHARED.theme.helpText,
227
+ scale=NColourLabel.HEADER_SCALE
229
228
  )
230
229
 
231
230
  self.novelName = QLabel("", self)
@@ -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
 
@@ -318,8 +315,8 @@ class _ContentsPage(NFixedPage):
318
315
 
319
316
  # Title
320
317
  self.contentLabel = NColourLabel(
321
- self.tr("Table of Contents"), SHARED.theme.helpText,
322
- parent=self, scale=NColourLabel.HEADER_SCALE
318
+ self.tr("Table of Contents"), self, color=SHARED.theme.helpText,
319
+ scale=NColourLabel.HEADER_SCALE
323
320
  )
324
321
 
325
322
  # Contents Tree
@@ -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
- QAction, QApplication, QDialog, QFileDialog, QFormLayout, QHBoxLayout,
38
- QLabel, QLineEdit, QListView, QMenu, QPushButton, QScrollArea, QShortcut,
39
- QStackedWidget, QStyleOptionViewItem, QStyledItemDelegate, QVBoxLayout,
37
+ QAction, QApplication, QFileDialog, QFormLayout, QHBoxLayout, QLabel,
38
+ QLineEdit, QListView, QMenu, QPushButton, QScrollArea, QShortcut,
39
+ QStackedWidget, QStyledItemDelegate, QStyleOptionViewItem, QVBoxLayout,
40
40
  QWidget
41
41
  )
42
42
 
@@ -46,7 +46,7 @@ from novelwriter.constants import nwFiles
46
46
  from novelwriter.core.coretools import ProjectBuilder
47
47
  from novelwriter.enum import nwItemClass
48
48
  from novelwriter.extensions.configlayout import NWrappedWidgetBox
49
- from novelwriter.extensions.modified import NIconToolButton, NSpinBox
49
+ from novelwriter.extensions.modified import NDialog, NIconToolButton, NSpinBox
50
50
  from novelwriter.extensions.switch import NSwitch
51
51
  from novelwriter.extensions.versioninfo import VersionInfoWidget
52
52
  from novelwriter.types import QtAlignLeft, QtAlignRightTop, QtSelected
@@ -56,7 +56,7 @@ logger = logging.getLogger(__name__)
56
56
  PANEL_ALPHA = 178
57
57
 
58
58
 
59
- class GuiWelcome(QDialog):
59
+ class GuiWelcome(NDialog):
60
60
 
61
61
  openProjectRequest = pyqtSignal(Path)
62
62
 
@@ -196,7 +196,7 @@ class GuiWelcome(QDialog):
196
196
  """Capture the user closing the window and save settings."""
197
197
  self._saveSettings()
198
198
  event.accept()
199
- self.deleteLater()
199
+ self.softDelete()
200
200
  return
201
201
 
202
202
  ##
@@ -208,6 +208,7 @@ class GuiWelcome(QDialog):
208
208
  """Show the create new project page."""
209
209
  self.mainStack.setCurrentWidget(self.tabNew)
210
210
  self._setButtonVisibility()
211
+ self.tabNew.enterForm()
211
212
  return
212
213
 
213
214
  @pyqtSlot()
@@ -220,8 +221,7 @@ class GuiWelcome(QDialog):
220
221
  @pyqtSlot()
221
222
  def _browseForProject(self) -> None:
222
223
  """Browse for a project to open."""
223
- if path := SHARED.getProjectPath(self, path=CONFIG.lastPath(), allowZip=False):
224
- CONFIG.setLastPath(path)
224
+ if path := SHARED.getProjectPath(self, path=CONFIG.homePath(), allowZip=False):
225
225
  self._openProjectPath(path)
226
226
  return
227
227
 
@@ -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
 
@@ -512,6 +504,8 @@ class _NewProjectPage(QWidget):
512
504
  self.scrollArea.setHorizontalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAsNeeded)
513
505
  self.scrollArea.setVerticalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAsNeeded)
514
506
 
507
+ self.enterForm = self.projectForm.enterForm
508
+
515
509
  # Assemble
516
510
  # ========
517
511
 
@@ -548,8 +542,6 @@ class _NewProjectPage(QWidget):
548
542
  self.openProjectRequest.emit(path)
549
543
  return
550
544
 
551
- # END Class _NewProjectPage
552
-
553
545
 
554
546
  class _NewProjectForm(QWidget):
555
547
 
@@ -560,7 +552,7 @@ class _NewProjectForm(QWidget):
560
552
  def __init__(self, parent: QWidget) -> None:
561
553
  super().__init__(parent=parent)
562
554
 
563
- self._basePath = CONFIG.homePath()
555
+ self._basePath = CONFIG.lastPath("project")
564
556
  self._fillMode = self.FILL_BLANK
565
557
  self._copyPath = None
566
558
 
@@ -707,6 +699,12 @@ class _NewProjectForm(QWidget):
707
699
 
708
700
  return
709
701
 
702
+ def enterForm(self) -> None:
703
+ """Focus the project name field when entering the form."""
704
+ self.projName.setFocus()
705
+ self.projName.selectAll()
706
+ return
707
+
710
708
  def getProjectData(self) -> dict:
711
709
  """Collect form data and return it as a dictionary."""
712
710
  roots = []
@@ -736,12 +734,13 @@ class _NewProjectForm(QWidget):
736
734
  @pyqtSlot()
737
735
  def _doBrowse(self) -> None:
738
736
  """Select a project folder."""
739
- if projDir := QFileDialog.getExistingDirectory(
737
+ if path := QFileDialog.getExistingDirectory(
740
738
  self, self.tr("Select Project Folder"),
741
739
  str(self._basePath), options=QFileDialog.Option.ShowDirsOnly
742
740
  ):
743
- self._basePath = Path(projDir)
741
+ self._basePath = Path(path)
744
742
  self._updateProjPath()
743
+ CONFIG.setLastPath("project", path)
745
744
  return
746
745
 
747
746
  @pyqtSlot()
@@ -805,8 +804,6 @@ class _NewProjectForm(QWidget):
805
804
 
806
805
  return
807
806
 
808
- # END Class _NewProjectForm
809
-
810
807
 
811
808
  class _PopLeftDirectionMenu(QMenu):
812
809
 
@@ -817,5 +814,3 @@ class _PopLeftDirectionMenu(QMenu):
817
814
  offset = QPoint(parent.width() - self.width(), parent.height())
818
815
  self.move(parent.mapToGlobal(offset))
819
816
  return super(_PopLeftDirectionMenu, self).event(event)
820
-
821
- # END Class _PopLeftDirectionMenu