novelWriter 2.4b1__py3-none-any.whl → 2.4.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (89) hide show
  1. {novelWriter-2.4b1.dist-info → novelWriter-2.4.1.dist-info}/METADATA +5 -6
  2. {novelWriter-2.4b1.dist-info → novelWriter-2.4.1.dist-info}/RECORD +79 -83
  3. novelwriter/__init__.py +15 -8
  4. novelwriter/assets/i18n/nw_de_DE.qm +0 -0
  5. novelwriter/assets/i18n/nw_en_US.qm +0 -0
  6. novelwriter/assets/i18n/nw_es_419.qm +0 -0
  7. novelwriter/assets/i18n/nw_fr_FR.qm +0 -0
  8. novelwriter/assets/i18n/nw_it_IT.qm +0 -0
  9. novelwriter/assets/i18n/nw_ja_JP.qm +0 -0
  10. novelwriter/assets/i18n/nw_nb_NO.qm +0 -0
  11. novelwriter/assets/i18n/nw_nl_NL.qm +0 -0
  12. novelwriter/assets/i18n/nw_pt_BR.qm +0 -0
  13. novelwriter/assets/i18n/nw_zh_CN.qm +0 -0
  14. novelwriter/assets/icons/none.svg +4 -0
  15. novelwriter/assets/icons/typicons_dark/icons.conf +2 -2
  16. novelwriter/assets/icons/typicons_dark/typ_unfold-hidden.svg +4 -0
  17. novelwriter/assets/icons/typicons_dark/typ_unfold-visible.svg +4 -0
  18. novelwriter/assets/icons/typicons_light/icons.conf +2 -2
  19. novelwriter/assets/icons/typicons_light/typ_unfold-hidden.svg +4 -0
  20. novelwriter/assets/icons/typicons_light/typ_unfold-visible.svg +4 -0
  21. novelwriter/assets/manual.pdf +0 -0
  22. novelwriter/assets/sample.zip +0 -0
  23. novelwriter/common.py +11 -3
  24. novelwriter/config.py +12 -4
  25. novelwriter/core/buildsettings.py +7 -7
  26. novelwriter/core/coretools.py +21 -22
  27. novelwriter/core/docbuild.py +2 -2
  28. novelwriter/core/projectxml.py +1 -1
  29. novelwriter/core/spellcheck.py +3 -3
  30. novelwriter/core/status.py +3 -2
  31. novelwriter/core/tokenizer.py +3 -3
  32. novelwriter/core/toodt.py +333 -356
  33. novelwriter/dialogs/about.py +9 -11
  34. novelwriter/dialogs/docmerge.py +17 -14
  35. novelwriter/dialogs/docsplit.py +14 -12
  36. novelwriter/dialogs/editlabel.py +5 -4
  37. novelwriter/dialogs/preferences.py +29 -34
  38. novelwriter/dialogs/projectsettings.py +31 -28
  39. novelwriter/dialogs/quotes.py +10 -9
  40. novelwriter/dialogs/wordlist.py +17 -14
  41. novelwriter/error.py +14 -12
  42. novelwriter/extensions/circularprogress.py +12 -8
  43. novelwriter/extensions/configlayout.py +1 -3
  44. novelwriter/extensions/modified.py +33 -2
  45. novelwriter/extensions/pagedsidebar.py +16 -14
  46. novelwriter/extensions/simpleprogress.py +3 -1
  47. novelwriter/extensions/statusled.py +3 -1
  48. novelwriter/extensions/switch.py +10 -9
  49. novelwriter/extensions/switchbox.py +14 -13
  50. novelwriter/gui/doceditor.py +205 -246
  51. novelwriter/gui/dochighlight.py +26 -9
  52. novelwriter/gui/docviewer.py +55 -59
  53. novelwriter/gui/docviewerpanel.py +16 -13
  54. novelwriter/gui/editordocument.py +4 -4
  55. novelwriter/gui/itemdetails.py +45 -48
  56. novelwriter/gui/mainmenu.py +2 -2
  57. novelwriter/gui/noveltree.py +23 -21
  58. novelwriter/gui/outline.py +93 -94
  59. novelwriter/gui/projtree.py +32 -30
  60. novelwriter/gui/search.py +75 -29
  61. novelwriter/gui/sidebar.py +24 -28
  62. novelwriter/gui/statusbar.py +14 -14
  63. novelwriter/gui/theme.py +61 -39
  64. novelwriter/guimain.py +37 -33
  65. novelwriter/shared.py +21 -9
  66. novelwriter/text/counting.py +1 -0
  67. novelwriter/tools/dictionaries.py +15 -14
  68. novelwriter/tools/lipsum.py +20 -17
  69. novelwriter/tools/manusbuild.py +44 -35
  70. novelwriter/tools/manuscript.py +112 -112
  71. novelwriter/tools/manussettings.py +91 -98
  72. novelwriter/tools/noveldetails.py +20 -18
  73. novelwriter/tools/welcome.py +51 -48
  74. novelwriter/tools/writingstats.py +61 -55
  75. novelwriter/types.py +90 -0
  76. novelwriter/assets/icons/typicons_dark/typ_arrow-down.svg +0 -4
  77. novelwriter/assets/icons/typicons_dark/typ_arrow-right.svg +0 -4
  78. novelwriter/assets/icons/typicons_light/typ_arrow-down.svg +0 -4
  79. novelwriter/assets/icons/typicons_light/typ_arrow-right.svg +0 -4
  80. novelwriter/core/__init__.py +0 -3
  81. novelwriter/dialogs/__init__.py +0 -3
  82. novelwriter/extensions/__init__.py +0 -3
  83. novelwriter/gui/__init__.py +0 -3
  84. novelwriter/text/__init__.py +0 -3
  85. novelwriter/tools/__init__.py +0 -3
  86. {novelWriter-2.4b1.dist-info → novelWriter-2.4.1.dist-info}/LICENSE.md +0 -0
  87. {novelWriter-2.4b1.dist-info → novelWriter-2.4.1.dist-info}/WHEEL +0 -0
  88. {novelWriter-2.4b1.dist-info → novelWriter-2.4.1.dist-info}/entry_points.txt +0 -0
  89. {novelWriter-2.4b1.dist-info → novelWriter-2.4.1.dist-info}/top_level.txt +0 -0
@@ -28,16 +28,18 @@ import logging
28
28
  from pathlib import Path
29
29
  from zipfile import ZipFile
30
30
 
31
- from PyQt5.QtGui import QCloseEvent, QTextCursor
32
31
  from PyQt5.QtCore import pyqtSlot
32
+ from PyQt5.QtGui import QCloseEvent, QTextCursor
33
33
  from PyQt5.QtWidgets import (
34
- QDialog, QDialogButtonBox, QFileDialog, QFrame, QHBoxLayout, QLabel,
35
- QLineEdit, QPlainTextEdit, QPushButton, QVBoxLayout, QWidget, qApp
34
+ QApplication, QDialog, QDialogButtonBox, QFileDialog, QFrame, QHBoxLayout,
35
+ QLabel, QLineEdit, QPlainTextEdit, QPushButton, QVBoxLayout, QWidget
36
36
  )
37
37
 
38
38
  from novelwriter import CONFIG, SHARED
39
- from novelwriter.error import formatException
40
39
  from novelwriter.common import formatFileFilter, openExternalPath, formatInt, getFileSize
40
+ from novelwriter.error import formatException
41
+ from novelwriter.extensions.modified import NIconToolButton
42
+ from novelwriter.types import QtDialogClose
41
43
 
42
44
  logger = logging.getLogger(__name__)
43
45
 
@@ -54,6 +56,7 @@ class GuiDictionaries(QDialog):
54
56
  self._installPath = None
55
57
  self._currDicts = set()
56
58
 
59
+ iSz = SHARED.theme.baseIconSize
57
60
  iPx = CONFIG.pxInt(4)
58
61
  mPx = CONFIG.pxInt(8)
59
62
  sPx = CONFIG.pxInt(16)
@@ -68,12 +71,11 @@ class GuiDictionaries(QDialog):
68
71
  self.tr("Download a dictionary from one of the links, and add it below."),
69
72
  f"&nbsp;\u203a <a href='{foUrl}'>{foUrl}</a>",
70
73
  f"&nbsp;\u203a <a href='{loUrl}'>{loUrl}</a>",
71
- ]))
74
+ ]), self)
72
75
  self.huInfo.setOpenExternalLinks(True)
73
76
  self.huInfo.setWordWrap(True)
74
77
  self.huInput = QLineEdit(self)
75
- self.huBrowse = QPushButton(self)
76
- self.huBrowse.setIcon(SHARED.theme.getIcon("browse"))
78
+ self.huBrowse = NIconToolButton(self, iSz, "browse")
77
79
  self.huBrowse.clicked.connect(self._doBrowseHunspell)
78
80
  self.huImport = QPushButton(self.tr("Add Dictionary"), self)
79
81
  self.huImport.setIcon(SHARED.theme.getIcon("add"))
@@ -88,11 +90,10 @@ class GuiDictionaries(QDialog):
88
90
  self.huAddBox.addWidget(self.huImport)
89
91
 
90
92
  # Install Path
91
- self.inInfo = QLabel(self.tr("Dictionary install location"))
93
+ self.inInfo = QLabel(self.tr("Dictionary install location"), self)
92
94
  self.inPath = QLineEdit(self)
93
95
  self.inPath.setReadOnly(True)
94
- self.inBrowse = QPushButton(self)
95
- self.inBrowse.setIcon(SHARED.theme.getIcon("browse"))
96
+ self.inBrowse = NIconToolButton(self, iSz, "browse")
96
97
  self.inBrowse.clicked.connect(self._doOpenInstallLocation)
97
98
 
98
99
  self.inBox = QHBoxLayout()
@@ -107,7 +108,7 @@ class GuiDictionaries(QDialog):
107
108
  self.infoBox.setFrameStyle(QFrame.Shape.NoFrame)
108
109
 
109
110
  # Buttons
110
- self.buttonBox = QDialogButtonBox(QDialogButtonBox.Close)
111
+ self.buttonBox = QDialogButtonBox(QtDialogClose, self)
111
112
  self.buttonBox.rejected.connect(self._doClose)
112
113
 
113
114
  # Assemble
@@ -158,7 +159,7 @@ class GuiDictionaries(QDialog):
158
159
  "Additional dictionaries found: {0}"
159
160
  ).format(len(self._currDicts)))
160
161
 
161
- qApp.processEvents()
162
+ QApplication.processEvents()
162
163
  self.adjustSize()
163
164
 
164
165
  return True
@@ -178,7 +179,7 @@ class GuiDictionaries(QDialog):
178
179
  ##
179
180
 
180
181
  @pyqtSlot()
181
- def _doBrowseHunspell(self):
182
+ def _doBrowseHunspell(self) -> None:
182
183
  """Browse for a Free/Libre Office dictionary."""
183
184
  ffilter = formatFileFilter([
184
185
  (self.tr("Free or Libre Office extension"), "*.sox *.oxt"), "*"
@@ -192,7 +193,7 @@ class GuiDictionaries(QDialog):
192
193
  return
193
194
 
194
195
  @pyqtSlot()
195
- def _doImportHunspell(self):
196
+ def _doImportHunspell(self) -> None:
196
197
  """Import a hunspell dictionary from .sox or .oxt file."""
197
198
  procErr = self.tr("Could not process dictionary file")
198
199
  if self._installPath:
@@ -35,6 +35,7 @@ from PyQt5.QtWidgets import (
35
35
  from novelwriter import CONFIG, SHARED
36
36
  from novelwriter.common import readTextFile
37
37
  from novelwriter.extensions.switch import NSwitch
38
+ from novelwriter.types import QtAlignLeft, QtAlignRight, QtRoleAction, QtDialogClose
38
39
 
39
40
  logger = logging.getLogger(__name__)
40
41
 
@@ -53,13 +54,14 @@ class GuiLipsum(QDialog):
53
54
 
54
55
  self.setWindowTitle(self.tr("Insert Placeholder Text"))
55
56
 
57
+ vSp = CONFIG.pxInt(4)
58
+ nPx = CONFIG.pxInt(64)
59
+
56
60
  self.innerBox = QHBoxLayout()
57
61
  self.innerBox.setSpacing(CONFIG.pxInt(16))
58
62
 
59
63
  # Icon
60
- nPx = CONFIG.pxInt(64)
61
- vSp = CONFIG.pxInt(4)
62
- self.docIcon = QLabel()
64
+ self.docIcon = QLabel(self)
63
65
  self.docIcon.setPixmap(SHARED.theme.getPixmap("proj_document", (nPx, nPx)))
64
66
 
65
67
  self.leftBox = QVBoxLayout()
@@ -69,35 +71,36 @@ class GuiLipsum(QDialog):
69
71
  self.innerBox.addLayout(self.leftBox)
70
72
 
71
73
  # Form
72
- self.headLabel = QLabel("<b>{0}</b>".format(self.tr("Insert Lorem Ipsum Text")))
74
+ self.headLabel = QLabel(self.tr("Insert Lorem Ipsum Text"))
75
+ self.headLabel.setFont(SHARED.theme.guiFontB)
73
76
 
74
- self.paraLabel = QLabel(self.tr("Number of paragraphs"))
75
- self.paraCount = QSpinBox()
77
+ self.paraLabel = QLabel(self.tr("Number of paragraphs"), self)
78
+ self.paraCount = QSpinBox(self)
76
79
  self.paraCount.setMinimum(1)
77
80
  self.paraCount.setMaximum(100)
78
81
  self.paraCount.setValue(5)
79
82
 
80
- self.randLabel = QLabel(self.tr("Randomise order"))
81
- self.randSwitch = NSwitch()
83
+ self.randLabel = QLabel(self.tr("Randomise order"), self)
84
+ self.randSwitch = NSwitch(self)
82
85
 
83
86
  self.formBox = QGridLayout()
84
- self.formBox.addWidget(self.headLabel, 0, 0, 1, 2, Qt.AlignLeft)
85
- self.formBox.addWidget(self.paraLabel, 1, 0, 1, 1, Qt.AlignLeft)
86
- self.formBox.addWidget(self.paraCount, 1, 1, 1, 1, Qt.AlignRight)
87
- self.formBox.addWidget(self.randLabel, 2, 0, 1, 1, Qt.AlignLeft)
88
- self.formBox.addWidget(self.randSwitch, 2, 1, 1, 1, Qt.AlignRight)
87
+ self.formBox.addWidget(self.headLabel, 0, 0, 1, 2, QtAlignLeft)
88
+ self.formBox.addWidget(self.paraLabel, 1, 0, 1, 1, QtAlignLeft)
89
+ self.formBox.addWidget(self.paraCount, 1, 1, 1, 1, QtAlignRight)
90
+ self.formBox.addWidget(self.randLabel, 2, 0, 1, 1, QtAlignLeft)
91
+ self.formBox.addWidget(self.randSwitch, 2, 1, 1, 1, QtAlignRight)
89
92
  self.formBox.setVerticalSpacing(vSp)
90
93
  self.formBox.setRowStretch(3, 1)
91
94
  self.innerBox.addLayout(self.formBox)
92
95
 
93
96
  # Buttons
94
- self.buttonBox = QDialogButtonBox()
97
+ self.buttonBox = QDialogButtonBox(self)
95
98
  self.buttonBox.rejected.connect(self.close)
96
99
 
97
- self.btnClose = self.buttonBox.addButton(QDialogButtonBox.Close)
100
+ self.btnClose = self.buttonBox.addButton(QtDialogClose)
98
101
  self.btnClose.setAutoDefault(False)
99
102
 
100
- self.btnInsert = self.buttonBox.addButton(self.tr("Insert"), QDialogButtonBox.ActionRole)
103
+ self.btnInsert = self.buttonBox.addButton(self.tr("Insert"), QtRoleAction)
101
104
  self.btnInsert.clicked.connect(self._doInsert)
102
105
  self.btnInsert.setAutoDefault(False)
103
106
 
@@ -127,7 +130,7 @@ class GuiLipsum(QDialog):
127
130
  def getLipsum(cls, parent: QWidget) -> str:
128
131
  """Pop the dialog and return the lipsum text."""
129
132
  cls = GuiLipsum(parent)
130
- cls.exec_()
133
+ cls.exec()
131
134
  text = cls.lipsumText
132
135
  cls.deleteLater()
133
136
  return text
@@ -27,8 +27,8 @@ import logging
27
27
 
28
28
  from pathlib import Path
29
29
 
30
+ from PyQt5.QtCore import QTimer, pyqtSlot
30
31
  from PyQt5.QtGui import QCloseEvent
31
- from PyQt5.QtCore import QSize, QTimer, Qt, pyqtSlot
32
32
  from PyQt5.QtWidgets import (
33
33
  QAbstractButton, QAbstractItemView, QDialog, QDialogButtonBox, QFileDialog,
34
34
  QGridLayout, QHBoxLayout, QLabel, QLineEdit, QListWidget, QListWidgetItem,
@@ -36,13 +36,15 @@ from PyQt5.QtWidgets import (
36
36
  )
37
37
 
38
38
  from novelwriter import CONFIG, SHARED
39
- from novelwriter.enum import nwBuildFmt
40
39
  from novelwriter.common import makeFileNameSafe, openExternalPath
41
40
  from novelwriter.constants import nwLabels
42
- from novelwriter.core.item import NWItem
43
- from novelwriter.core.docbuild import NWBuildDocument
44
41
  from novelwriter.core.buildsettings import BuildSettings
42
+ from novelwriter.core.docbuild import NWBuildDocument
43
+ from novelwriter.core.item import NWItem
44
+ from novelwriter.enum import nwBuildFmt
45
+ from novelwriter.extensions.modified import NIconToolButton
45
46
  from novelwriter.extensions.simpleprogress import NProgressSimple
47
+ from novelwriter.types import QtAlignCenter, QtDialogClose, QtRoleAction, QtRoleReject, QtUserRole
46
48
 
47
49
  logger = logging.getLogger(__name__)
48
50
 
@@ -54,9 +56,9 @@ class GuiManuscriptBuild(QDialog):
54
56
  independently of the Manuscript Build Tool.
55
57
  """
56
58
 
57
- D_KEY = Qt.ItemDataRole.UserRole
59
+ D_KEY = QtUserRole
58
60
 
59
- def __init__(self, parent: QWidget, build: BuildSettings):
61
+ def __init__(self, parent: QWidget, build: BuildSettings) -> None:
60
62
  super().__init__(parent=parent)
61
63
 
62
64
  logger.debug("Create: GuiManuscriptBuild")
@@ -69,7 +71,8 @@ class GuiManuscriptBuild(QDialog):
69
71
  self.setMinimumWidth(CONFIG.pxInt(500))
70
72
  self.setMinimumHeight(CONFIG.pxInt(300))
71
73
 
72
- iPx = SHARED.theme.baseIconSize
74
+ iSz = SHARED.theme.baseIconSize
75
+ bSz = SHARED.theme.buttonIconSize
73
76
  sp4 = CONFIG.pxInt(4)
74
77
  sp8 = CONFIG.pxInt(8)
75
78
  sp16 = CONFIG.pxInt(16)
@@ -85,9 +88,9 @@ class GuiManuscriptBuild(QDialog):
85
88
  # Output Format
86
89
  # =============
87
90
 
88
- self.lblFormat = QLabel(self.tr("Output Format"))
89
- self.listFormats = QListWidget()
90
- self.listFormats.setIconSize(QSize(iPx, iPx))
91
+ self.lblFormat = QLabel(self.tr("Output Format"), self)
92
+ self.listFormats = QListWidget(self)
93
+ self.listFormats.setIconSize(iSz)
91
94
  current = None
92
95
  for key in nwBuildFmt:
93
96
  item = QListWidgetItem()
@@ -104,17 +107,17 @@ class GuiManuscriptBuild(QDialog):
104
107
  self.formatBox.addWidget(self.listFormats, 1)
105
108
  self.formatBox.setContentsMargins(0, 0, 0, 0)
106
109
 
107
- self.formatWidget = QWidget()
110
+ self.formatWidget = QWidget(self)
108
111
  self.formatWidget.setLayout(self.formatBox)
109
112
  self.formatWidget.setContentsMargins(0, 0, 0, 0)
110
113
 
111
114
  # Table of Contents
112
115
  # =================
113
116
 
114
- self.lblContent = QLabel(self.tr("Table of Contents"))
117
+ self.lblContent = QLabel(self.tr("Table of Contents"), self)
115
118
 
116
119
  self.listContent = QListWidget(self)
117
- self.listContent.setIconSize(QSize(iPx, iPx))
120
+ self.listContent.setIconSize(iSz)
118
121
  self.listContent.setSelectionMode(QAbstractItemView.SelectionMode.NoSelection)
119
122
 
120
123
  self.contentBox = QVBoxLayout()
@@ -122,7 +125,7 @@ class GuiManuscriptBuild(QDialog):
122
125
  self.contentBox.addWidget(self.listContent, 0)
123
126
  self.contentBox.setContentsMargins(0, 0, 0, 0)
124
127
 
125
- self.contentWidget = QWidget()
128
+ self.contentWidget = QWidget(self)
126
129
  self.contentWidget.setLayout(self.contentBox)
127
130
  self.contentWidget.setContentsMargins(0, 0, 0, 0)
128
131
 
@@ -134,14 +137,14 @@ class GuiManuscriptBuild(QDialog):
134
137
  font.setUnderline(True)
135
138
  font.setPointSizeF(1.5*font.pointSizeF())
136
139
 
137
- self.lblMain = QLabel(self._build.name)
140
+ self.lblMain = QLabel(self._build.name, self)
138
141
  self.lblMain.setWordWrap(True)
139
142
  self.lblMain.setFont(font)
140
143
 
141
144
  # Build Path
142
- self.lblPath = QLabel(self.tr("Path"))
145
+ self.lblPath = QLabel(self.tr("Path"), self)
143
146
  self.buildPath = QLineEdit(self)
144
- self.btnBrowse = QPushButton(SHARED.theme.getIcon("browse"), "")
147
+ self.btnBrowse = NIconToolButton(self, iSz, "browse")
145
148
 
146
149
  self.pathBox = QHBoxLayout()
147
150
  self.pathBox.addWidget(self.buildPath)
@@ -149,9 +152,9 @@ class GuiManuscriptBuild(QDialog):
149
152
  self.pathBox.setSpacing(sp8)
150
153
 
151
154
  # Build Name
152
- self.lblName = QLabel(self.tr("File Name"))
155
+ self.lblName = QLabel(self.tr("File Name"), self)
153
156
  self.buildName = QLineEdit(self)
154
- self.btnReset = QPushButton(SHARED.theme.getIcon("revert"), "")
157
+ self.btnReset = NIconToolButton(self, iSz, "revert")
155
158
  self.btnReset.setToolTip(self.tr("Reset file name to default"))
156
159
 
157
160
  self.nameBox = QHBoxLayout()
@@ -176,16 +179,19 @@ class GuiManuscriptBuild(QDialog):
176
179
  self.buildBox.setVerticalSpacing(sp4)
177
180
 
178
181
  # Dialog Buttons
179
- self.btnOpen = QPushButton(SHARED.theme.getIcon("browse"), self.tr("Open Folder"))
180
- self.btnBuild = QPushButton(SHARED.theme.getIcon("export"), self.tr("&Build"))
181
- self.dlgButtons = QDialogButtonBox(QDialogButtonBox.StandardButton.Close)
182
- self.dlgButtons.addButton(self.btnOpen, QDialogButtonBox.ButtonRole.ActionRole)
183
- self.dlgButtons.addButton(self.btnBuild, QDialogButtonBox.ButtonRole.ActionRole)
182
+ self.btnOpen = QPushButton(SHARED.theme.getIcon("browse"), self.tr("Open Folder"), self)
183
+ self.btnOpen.setIconSize(bSz)
184
+ self.btnBuild = QPushButton(SHARED.theme.getIcon("export"), self.tr("&Build"), self)
185
+ self.btnBuild.setIconSize(bSz)
186
+
187
+ self.dlgButtons = QDialogButtonBox(QtDialogClose, self)
188
+ self.dlgButtons.addButton(self.btnOpen, QtRoleAction)
189
+ self.dlgButtons.addButton(self.btnBuild, QtRoleAction)
184
190
 
185
191
  # Assemble GUI
186
192
  # ============
187
193
 
188
- self.mainSplit = QSplitter()
194
+ self.mainSplit = QSplitter(self)
189
195
  self.mainSplit.addWidget(self.formatWidget)
190
196
  self.mainSplit.addWidget(self.contentWidget)
191
197
  self.mainSplit.setHandleWidth(sp16)
@@ -199,7 +205,7 @@ class GuiManuscriptBuild(QDialog):
199
205
  ])
200
206
 
201
207
  self.outerBox = QVBoxLayout()
202
- self.outerBox.addWidget(self.lblMain, 0, Qt.AlignCenter)
208
+ self.outerBox.addWidget(self.lblMain, 0, QtAlignCenter)
203
209
  self.outerBox.addSpacing(sp16)
204
210
  self.outerBox.addWidget(self.mainSplit, 1)
205
211
  self.outerBox.addSpacing(sp4)
@@ -252,20 +258,20 @@ class GuiManuscriptBuild(QDialog):
252
258
  ##
253
259
 
254
260
  @pyqtSlot("QAbstractButton*")
255
- def _dialogButtonClicked(self, button: QAbstractButton):
261
+ def _dialogButtonClicked(self, button: QAbstractButton) -> None:
256
262
  """Handle button clicks from the dialog button box."""
257
263
  role = self.dlgButtons.buttonRole(button)
258
- if role == QDialogButtonBox.ActionRole:
264
+ if role == QtRoleAction:
259
265
  if button == self.btnBuild:
260
266
  self._runBuild()
261
267
  elif button == self.btnOpen:
262
268
  self._openOutputFolder()
263
- elif role == QDialogButtonBox.RejectRole:
269
+ elif role == QtRoleReject:
264
270
  self.close()
265
271
  return
266
272
 
267
273
  @pyqtSlot()
268
- def _doSelectPath(self):
274
+ def _doSelectPath(self) -> None:
269
275
  """Select a folder for output."""
270
276
  bPath = Path(self.buildPath.text())
271
277
  bPath = bPath if bPath.is_dir() else self._build.lastPath
@@ -277,7 +283,7 @@ class GuiManuscriptBuild(QDialog):
277
283
  return
278
284
 
279
285
  @pyqtSlot()
280
- def _doResetBuildName(self):
286
+ def _doResetBuildName(self) -> None:
281
287
  """Generate a default build name."""
282
288
  bName = f"{SHARED.project.data.name} - {self._build.name}"
283
289
  self.buildName.setText(bName)
@@ -285,7 +291,7 @@ class GuiManuscriptBuild(QDialog):
285
291
  return
286
292
 
287
293
  @pyqtSlot()
288
- def _resetProgress(self):
294
+ def _resetProgress(self) -> None:
289
295
  """Set the progress bar back to 0."""
290
296
  self.buildProgress.setValue(0)
291
297
  return
@@ -320,6 +326,9 @@ class GuiManuscriptBuild(QDialog):
320
326
  ):
321
327
  return False
322
328
 
329
+ # Make sure editor content is saved before we start
330
+ SHARED.mainGui.saveDocument()
331
+
323
332
  docBuild = NWBuildDocument(SHARED.project, self._build)
324
333
  docBuild.queueAll()
325
334
 
@@ -342,7 +351,7 @@ class GuiManuscriptBuild(QDialog):
342
351
  return items[0].data(self.D_KEY)
343
352
  return None
344
353
 
345
- def _saveSettings(self):
354
+ def _saveSettings(self) -> None:
346
355
  """Save the user GUI settings."""
347
356
  winWidth = CONFIG.rpxInt(self.width())
348
357
  winHeight = CONFIG.rpxInt(self.height())
@@ -361,7 +370,7 @@ class GuiManuscriptBuild(QDialog):
361
370
 
362
371
  return
363
372
 
364
- def _populateContentList(self):
373
+ def _populateContentList(self) -> None:
365
374
  """Build the content list."""
366
375
  rootMap = {}
367
376
  filtered = self._build.buildItemFilter(SHARED.project)
@@ -390,7 +399,7 @@ class GuiManuscriptBuild(QDialog):
390
399
 
391
400
  return
392
401
 
393
- def _openOutputFolder(self):
402
+ def _openOutputFolder(self) -> None:
394
403
  """Open the build folder in the system's file explorer."""
395
404
  openExternalPath(Path(self.buildPath.text()))
396
405
  return