novelWriter 2.4.3__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 (123) hide show
  1. {novelWriter-2.4.3.dist-info → novelWriter-2.5.dist-info}/METADATA +4 -5
  2. {novelWriter-2.4.3.dist-info → novelWriter-2.5.dist-info}/RECORD +122 -112
  3. {novelWriter-2.4.3.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/i18n/project_pt_BR.json +74 -74
  19. novelwriter/assets/icons/typicons_dark/icons.conf +2 -0
  20. novelwriter/assets/icons/typicons_dark/nw_font.svg +4 -0
  21. novelwriter/assets/icons/typicons_dark/nw_quote.svg +4 -0
  22. novelwriter/assets/icons/typicons_light/icons.conf +2 -0
  23. novelwriter/assets/icons/typicons_light/nw_font.svg +4 -0
  24. novelwriter/assets/icons/typicons_light/nw_quote.svg +4 -0
  25. novelwriter/assets/manual.pdf +0 -0
  26. novelwriter/assets/sample.zip +0 -0
  27. novelwriter/assets/syntax/cyberpunk_night.conf +5 -3
  28. novelwriter/assets/syntax/default_dark.conf +32 -18
  29. novelwriter/assets/syntax/default_light.conf +24 -10
  30. novelwriter/assets/syntax/dracula.conf +44 -0
  31. novelwriter/assets/syntax/grey_dark.conf +5 -4
  32. novelwriter/assets/syntax/grey_light.conf +5 -4
  33. novelwriter/assets/syntax/light_owl.conf +7 -6
  34. novelwriter/assets/syntax/night_owl.conf +7 -6
  35. novelwriter/assets/syntax/snazzy.conf +42 -0
  36. novelwriter/assets/syntax/solarized_dark.conf +4 -3
  37. novelwriter/assets/syntax/solarized_light.conf +4 -3
  38. novelwriter/assets/syntax/tango.conf +27 -11
  39. novelwriter/assets/syntax/tomorrow.conf +6 -5
  40. novelwriter/assets/syntax/tomorrow_night.conf +7 -6
  41. novelwriter/assets/syntax/tomorrow_night_blue.conf +6 -5
  42. novelwriter/assets/syntax/tomorrow_night_bright.conf +6 -5
  43. novelwriter/assets/syntax/tomorrow_night_eighties.conf +6 -5
  44. novelwriter/assets/text/credits_en.htm +52 -41
  45. novelwriter/assets/themes/cyberpunk_night.conf +3 -0
  46. novelwriter/assets/themes/default_dark.conf +2 -0
  47. novelwriter/assets/themes/default_light.conf +2 -0
  48. novelwriter/assets/themes/dracula.conf +48 -0
  49. novelwriter/assets/themes/solarized_dark.conf +2 -0
  50. novelwriter/assets/themes/solarized_light.conf +2 -0
  51. novelwriter/common.py +33 -12
  52. novelwriter/config.py +184 -98
  53. novelwriter/constants.py +47 -35
  54. novelwriter/core/buildsettings.py +68 -69
  55. novelwriter/core/coretools.py +5 -23
  56. novelwriter/core/docbuild.py +52 -40
  57. novelwriter/core/document.py +3 -5
  58. novelwriter/core/index.py +115 -45
  59. novelwriter/core/item.py +8 -19
  60. novelwriter/core/options.py +2 -4
  61. novelwriter/core/project.py +37 -61
  62. novelwriter/core/projectdata.py +1 -3
  63. novelwriter/core/projectxml.py +12 -15
  64. novelwriter/core/sessions.py +3 -5
  65. novelwriter/core/spellcheck.py +4 -9
  66. novelwriter/core/status.py +211 -164
  67. novelwriter/core/storage.py +0 -8
  68. novelwriter/core/tohtml.py +139 -105
  69. novelwriter/core/tokenizer.py +278 -122
  70. novelwriter/core/{tomd.py → tomarkdown.py} +97 -78
  71. novelwriter/core/toodt.py +257 -166
  72. novelwriter/core/toqdoc.py +419 -0
  73. novelwriter/core/tree.py +5 -7
  74. novelwriter/dialogs/about.py +11 -18
  75. novelwriter/dialogs/docmerge.py +17 -19
  76. novelwriter/dialogs/docsplit.py +17 -19
  77. novelwriter/dialogs/editlabel.py +6 -10
  78. novelwriter/dialogs/preferences.py +200 -164
  79. novelwriter/dialogs/projectsettings.py +225 -189
  80. novelwriter/dialogs/quotes.py +12 -9
  81. novelwriter/dialogs/wordlist.py +9 -15
  82. novelwriter/enum.py +35 -30
  83. novelwriter/error.py +8 -15
  84. novelwriter/extensions/configlayout.py +55 -21
  85. novelwriter/extensions/eventfilters.py +1 -5
  86. novelwriter/extensions/modified.py +70 -14
  87. novelwriter/extensions/novelselector.py +1 -3
  88. novelwriter/extensions/pagedsidebar.py +9 -12
  89. novelwriter/extensions/{circularprogress.py → progressbars.py} +30 -8
  90. novelwriter/extensions/statusled.py +40 -26
  91. novelwriter/extensions/switch.py +4 -6
  92. novelwriter/extensions/switchbox.py +7 -6
  93. novelwriter/extensions/versioninfo.py +3 -9
  94. novelwriter/gui/doceditor.py +120 -139
  95. novelwriter/gui/dochighlight.py +231 -186
  96. novelwriter/gui/docviewer.py +69 -108
  97. novelwriter/gui/docviewerpanel.py +3 -10
  98. novelwriter/gui/editordocument.py +1 -3
  99. novelwriter/gui/itemdetails.py +7 -11
  100. novelwriter/gui/mainmenu.py +22 -18
  101. novelwriter/gui/noveltree.py +11 -24
  102. novelwriter/gui/outline.py +15 -26
  103. novelwriter/gui/projtree.py +39 -65
  104. novelwriter/gui/search.py +10 -3
  105. novelwriter/gui/sidebar.py +2 -6
  106. novelwriter/gui/statusbar.py +29 -37
  107. novelwriter/gui/theme.py +26 -48
  108. novelwriter/guimain.py +162 -160
  109. novelwriter/shared.py +36 -19
  110. novelwriter/text/patterns.py +113 -0
  111. novelwriter/tools/dictionaries.py +10 -20
  112. novelwriter/tools/lipsum.py +10 -16
  113. novelwriter/tools/manusbuild.py +9 -11
  114. novelwriter/tools/manuscript.py +75 -149
  115. novelwriter/tools/manussettings.py +74 -76
  116. novelwriter/tools/noveldetails.py +16 -21
  117. novelwriter/tools/welcome.py +21 -26
  118. novelwriter/tools/writingstats.py +9 -12
  119. novelwriter/types.py +49 -4
  120. novelwriter/extensions/simpleprogress.py +0 -55
  121. {novelWriter-2.4.3.dist-info → novelWriter-2.5.dist-info}/LICENSE.md +0 -0
  122. {novelWriter-2.4.3.dist-info → novelWriter-2.5.dist-info}/entry_points.txt +0 -0
  123. {novelWriter-2.4.3.dist-info → novelWriter-2.5.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
 
@@ -97,8 +98,8 @@ class GuiBuildSettings(QDialog):
97
98
 
98
99
  # Title
99
100
  self.titleLabel = NColourLabel(
100
- self.tr("Manuscript Build Settings"), SHARED.theme.helpText,
101
- 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)
102
103
  )
103
104
 
104
105
  # Settings Name
@@ -199,7 +200,7 @@ class GuiBuildSettings(QDialog):
199
200
  self._askToSaveBuild()
200
201
  self._saveSettings()
201
202
  event.accept()
202
- self.deleteLater()
203
+ self.softDelete()
203
204
  return
204
205
 
205
206
  ##
@@ -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,33 @@ 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)
1096
+ self.showDialogue = NSwitch(self, height=iPx)
1111
1097
 
1112
1098
  self.addRow(self._build.getLabel("format.justifyText"), self.justifyText)
1113
1099
  self.addRow(self._build.getLabel("format.stripUnicode"), self.stripUnicode)
1114
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)
1115
1122
 
1116
1123
  # Page Layout
1117
1124
  # ===========
@@ -1164,17 +1171,22 @@ class _FormatTab(NScrollableForm):
1164
1171
 
1165
1172
  def loadContent(self) -> None:
1166
1173
  """Populate the widgets."""
1167
- textFont = self._build.getStr("format.textFont")
1168
- if not textFont:
1169
- textFont = str(CONFIG.textFont)
1174
+ self._textFont = QFont()
1175
+ self._textFont.fromString(self._build.getStr("format.textFont"))
1170
1176
 
1171
- self.textFont.setText(textFont)
1172
- self.textSize.setValue(self._build.getInt("format.textSize"))
1173
- self.lineHeight.setValue(self._build.getFloat("format.lineHeight"))
1177
+ self.textFont.setText(describeFont(self._textFont))
1178
+ self.textFont.setCursorPosition(0)
1174
1179
 
1180
+ self.lineHeight.setValue(self._build.getFloat("format.lineHeight"))
1175
1181
  self.justifyText.setChecked(self._build.getBool("format.justifyText"))
1176
1182
  self.stripUnicode.setChecked(self._build.getBool("format.stripUnicode"))
1177
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"))
1178
1190
 
1179
1191
  pageUnit = self._build.getStr("format.pageUnit")
1180
1192
  index = self.pageUnit.findData(pageUnit)
@@ -1203,13 +1215,18 @@ class _FormatTab(NScrollableForm):
1203
1215
 
1204
1216
  def saveContent(self) -> None:
1205
1217
  """Save choices back into build object."""
1206
- self._build.setValue("format.textFont", self.textFont.text())
1207
- self._build.setValue("format.textSize", self.textSize.value())
1218
+ self._build.setValue("format.textFont", self._textFont.toString())
1208
1219
  self._build.setValue("format.lineHeight", self.lineHeight.value())
1209
1220
 
1210
1221
  self._build.setValue("format.justifyText", self.justifyText.isChecked())
1211
1222
  self._build.setValue("format.stripUnicode", self.stripUnicode.isChecked())
1212
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())
1213
1230
 
1214
1231
  self._build.setValue("format.pageUnit", str(self.pageUnit.currentData()))
1215
1232
  self._build.setValue("format.pageSize", str(self.pageSize.currentData()))
@@ -1228,13 +1245,11 @@ class _FormatTab(NScrollableForm):
1228
1245
  @pyqtSlot()
1229
1246
  def _selectFont(self) -> None:
1230
1247
  """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)
1248
+ font, status = SHARED.getFont(self._textFont, CONFIG.nativeFont)
1235
1249
  if status:
1236
- self.textFont.setText(newFont.family())
1237
- self.textSize.setValue(newFont.pointSize())
1250
+ self.textFont.setText(describeFont(font))
1251
+ self.textFont.setCursorPosition(0)
1252
+ self._textFont = font
1238
1253
  return
1239
1254
 
1240
1255
  @pyqtSlot(int)
@@ -1319,13 +1334,11 @@ class _FormatTab(NScrollableForm):
1319
1334
  self.pageSize.setCurrentIndex(index)
1320
1335
  return
1321
1336
 
1322
- # END Class _FormatTab
1323
-
1324
1337
 
1325
1338
  class _OutputTab(NScrollableForm):
1326
1339
 
1327
- def __init__(self, buildMain: GuiBuildSettings, build: BuildSettings) -> None:
1328
- super().__init__(parent=buildMain)
1340
+ def __init__(self, parent: QWidget, build: BuildSettings) -> None:
1341
+ super().__init__(parent=parent)
1329
1342
 
1330
1343
  self._build = build
1331
1344
 
@@ -1355,9 +1368,6 @@ class _OutputTab(NScrollableForm):
1355
1368
  self.odtPageCountOffset.setMinimumWidth(spW)
1356
1369
  self.addRow(self._build.getLabel("odt.pageCountOffset"), self.odtPageCountOffset)
1357
1370
 
1358
- self.odtFirstLineIndent = NSwitch(self, height=iPx)
1359
- self.addRow(self._build.getLabel("odt.firstLineIndent"), self.odtFirstLineIndent)
1360
-
1361
1371
  # HTML Document
1362
1372
  self.addGroupLabel(self._build.getLabel("html"))
1363
1373
 
@@ -1367,12 +1377,6 @@ class _OutputTab(NScrollableForm):
1367
1377
  self.htmlPreserveTabs = NSwitch(self, height=iPx)
1368
1378
  self.addRow(self._build.getLabel("html.preserveTabs"), self.htmlPreserveTabs)
1369
1379
 
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
1380
  # Finalise
1377
1381
  self.finalise()
1378
1382
 
@@ -1383,10 +1387,8 @@ class _OutputTab(NScrollableForm):
1383
1387
  self.odtAddColours.setChecked(self._build.getBool("odt.addColours"))
1384
1388
  self.odtPageHeader.setText(self._build.getStr("odt.pageHeader"))
1385
1389
  self.odtPageCountOffset.setValue(self._build.getInt("odt.pageCountOffset"))
1386
- self.odtFirstLineIndent.setChecked(self._build.getBool("odt.firstLineIndent"))
1387
1390
  self.htmlAddStyles.setChecked(self._build.getBool("html.addStyles"))
1388
1391
  self.htmlPreserveTabs.setChecked(self._build.getBool("html.preserveTabs"))
1389
- self.mdPreserveBreaks.setChecked(self._build.getBool("md.preserveBreaks"))
1390
1392
  self.odtPageHeader.setCursorPosition(0)
1391
1393
  return
1392
1394
 
@@ -1395,10 +1397,8 @@ class _OutputTab(NScrollableForm):
1395
1397
  self._build.setValue("odt.addColours", self.odtAddColours.isChecked())
1396
1398
  self._build.setValue("odt.pageHeader", self.odtPageHeader.text())
1397
1399
  self._build.setValue("odt.pageCountOffset", self.odtPageCountOffset.value())
1398
- self._build.setValue("odt.firstLineIndent", self.odtFirstLineIndent.isChecked())
1399
1400
  self._build.setValue("html.addStyles", self.htmlAddStyles.isChecked())
1400
1401
  self._build.setValue("html.preserveTabs", self.htmlPreserveTabs.isChecked())
1401
- self._build.setValue("md.preserveBreaks", self.mdPreserveBreaks.isChecked())
1402
1402
  return
1403
1403
 
1404
1404
  ##
@@ -1410,5 +1410,3 @@ class _OutputTab(NScrollableForm):
1410
1410
  self.odtPageHeader.setText(nwHeadFmt.ODT_AUTO)
1411
1411
  self.odtPageHeader.setCursorPosition(0)
1412
1412
  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
@@ -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