novelWriter 2.4.3__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.3.dist-info → novelWriter-2.5b1.dist-info}/METADATA +4 -5
  2. {novelWriter-2.4.3.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 +98 -126
  82. novelwriter/gui/dochighlight.py +237 -183
  83. novelwriter/gui/docviewer.py +46 -94
  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 +23 -48
  95. novelwriter/guimain.py +50 -71
  96. novelwriter/shared.py +30 -15
  97. novelwriter/tools/dictionaries.py +8 -12
  98. novelwriter/tools/lipsum.py +2 -4
  99. novelwriter/tools/manusbuild.py +1 -3
  100. novelwriter/tools/manuscript.py +66 -145
  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.3.dist-info → novelWriter-2.5b1.dist-info}/LICENSE.md +0 -0
  107. {novelWriter-2.4.3.dist-info → novelWriter-2.5b1.dist-info}/WHEEL +0 -0
  108. {novelWriter-2.4.3.dist-info → novelWriter-2.5b1.dist-info}/entry_points.txt +0 -0
  109. {novelWriter-2.4.3.dist-info → novelWriter-2.5b1.dist-info}/top_level.txt +0 -0
novelwriter/guimain.py CHANGED
@@ -23,18 +23,18 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
23
23
  """
24
24
  from __future__ import annotations
25
25
 
26
- import sys
27
26
  import logging
27
+ import sys
28
28
 
29
- from time import time
30
- from pathlib import Path
31
29
  from datetime import datetime
30
+ from pathlib import Path
31
+ from time import time
32
32
 
33
33
  from PyQt5.QtCore import Qt, QTimer, pyqtSlot
34
34
  from PyQt5.QtGui import QCloseEvent, QCursor, QIcon
35
35
  from PyQt5.QtWidgets import (
36
- QApplication, QFileDialog, QHBoxLayout, QMainWindow, QMessageBox, QShortcut, QSplitter,
37
- QStackedWidget, QVBoxLayout, QWidget
36
+ QApplication, QFileDialog, QHBoxLayout, QMainWindow, QMessageBox,
37
+ QShortcut, QSplitter, QStackedWidget, QVBoxLayout, QWidget
38
38
  )
39
39
 
40
40
  from novelwriter import CONFIG, SHARED, __hexversion__, __version__
@@ -44,7 +44,7 @@ from novelwriter.dialogs.about import GuiAbout
44
44
  from novelwriter.dialogs.preferences import GuiPreferences
45
45
  from novelwriter.dialogs.projectsettings import GuiProjectSettings
46
46
  from novelwriter.dialogs.wordlist import GuiWordList
47
- from novelwriter.enum import nwDocAction, nwDocInsert, nwDocMode, nwItemType, nwWidget, nwView
47
+ from novelwriter.enum import nwDocAction, nwDocInsert, nwDocMode, nwItemType, nwView, nwWidget
48
48
  from novelwriter.gui.doceditor import GuiDocEditor
49
49
  from novelwriter.gui.docviewer import GuiDocViewer
50
50
  from novelwriter.gui.docviewerpanel import GuiDocViewerPanel
@@ -263,6 +263,7 @@ class GuiMain(QMainWindow):
263
263
  self.docEditor.requestProjectItemRenamed.connect(self.projView.renameTreeItem)
264
264
  self.docEditor.requestNewNoteCreation.connect(self.projView.createNewNote)
265
265
  self.docEditor.docTextChanged.connect(self.projSearch.textChanged)
266
+ self.docEditor.requestNextDocument.connect(self.openNextDocument)
266
267
 
267
268
  self.docViewer.documentLoaded.connect(self.docViewerPanel.updateHandle)
268
269
  self.docViewer.loadDocumentTagRequest.connect(self._followTag)
@@ -369,9 +370,7 @@ class GuiMain(QMainWindow):
369
370
  if not msgYes:
370
371
  return False
371
372
 
372
- if self.docEditor.docChanged:
373
- self.saveDocument()
374
-
373
+ self.saveDocument()
375
374
  saveOK = self.saveProject()
376
375
  doBackup = False
377
376
  if SHARED.project.data.doBackup and CONFIG.backupOnClose:
@@ -514,9 +513,7 @@ class GuiMain(QMainWindow):
514
513
  # Disable focus mode if it is active
515
514
  if SHARED.focusMode:
516
515
  SHARED.setFocusMode(False)
517
- self.docEditor.saveCursorPosition()
518
- if self.docEditor.docChanged:
519
- self.saveDocument()
516
+ self.saveDocument()
520
517
  self.docEditor.clearEditor()
521
518
  if not beforeOpen:
522
519
  self.novelView.setActiveHandle(None)
@@ -553,42 +550,43 @@ class GuiMain(QMainWindow):
553
550
 
554
551
  return True
555
552
 
556
- def openNextDocument(self, tHandle: str, wrapAround: bool = False) -> bool:
553
+ @pyqtSlot(str, bool)
554
+ def openNextDocument(self, tHandle: str, wrapAround: bool) -> None:
557
555
  """Open the next document in the project tree, following the
558
556
  document with the given handle. Stop when reaching the end.
559
557
  """
560
- if not SHARED.hasProject:
561
- logger.error("No project open")
562
- return False
563
-
564
- nHandle = None # The next handle after tHandle
565
- fHandle = None # The first file handle we encounter
566
- foundIt = False # We've found tHandle, pick the next we see
567
- for tItem in SHARED.project.tree:
568
- if not tItem.isFileType():
569
- continue
570
- if fHandle is None:
571
- fHandle = tItem.itemHandle
572
- if tItem.itemHandle == tHandle:
573
- foundIt = True
574
- elif foundIt:
575
- nHandle = tItem.itemHandle
576
- break
577
-
578
- if nHandle is not None:
579
- self.openDocument(nHandle, tLine=1, doScroll=True)
580
- return True
581
- elif wrapAround:
582
- self.openDocument(fHandle, tLine=1, doScroll=True)
583
- return False
584
-
585
- return False
558
+ if SHARED.hasProject:
559
+ nHandle = None # The next handle after tHandle
560
+ fHandle = None # The first file handle we encounter
561
+ foundIt = False # We've found tHandle, pick the next we see
562
+ for tItem in SHARED.project.tree:
563
+ if not tItem.isFileType():
564
+ continue
565
+ if fHandle is None:
566
+ fHandle = tItem.itemHandle
567
+ if tItem.itemHandle == tHandle:
568
+ foundIt = True
569
+ elif foundIt:
570
+ nHandle = tItem.itemHandle
571
+ break
572
+ if nHandle is not None:
573
+ self.openDocument(nHandle, tLine=1, doScroll=True)
574
+ elif wrapAround:
575
+ self.openDocument(fHandle, tLine=1, doScroll=True)
576
+ return
586
577
 
587
- @pyqtSlot()
588
- def saveDocument(self) -> None:
578
+ def saveDocument(self, force: bool = False) -> None:
589
579
  """Save the current documents."""
590
580
  if SHARED.hasProject:
591
- self.docEditor.saveText()
581
+ self.docEditor.saveCursorPosition()
582
+ if force or self.docEditor.docChanged:
583
+ self.docEditor.saveText()
584
+ return
585
+
586
+ @pyqtSlot()
587
+ def forceSaveDocument(self) -> None:
588
+ """Save document even of it has not changed."""
589
+ self.saveDocument(force=True)
592
590
  return
593
591
 
594
592
  def viewDocument(self, tHandle: str | None = None, sTitle: str | None = None) -> bool:
@@ -794,10 +792,7 @@ class GuiMain(QMainWindow):
794
792
  """Open the novel details dialog."""
795
793
  if SHARED.hasProject:
796
794
  dialog = GuiNovelDetails(self)
797
- dialog.setModal(True)
798
- dialog.show()
799
- dialog.raise_()
800
- QApplication.processEvents()
795
+ dialog.activateDialog()
801
796
  dialog.updateValues()
802
797
  return
803
798
 
@@ -805,12 +800,8 @@ class GuiMain(QMainWindow):
805
800
  def showBuildManuscriptDialog(self) -> None:
806
801
  """Open the build manuscript dialog."""
807
802
  if SHARED.hasProject:
808
- if (dialog := SHARED.findTopLevelWidget(GuiManuscript)) is None:
809
- dialog = GuiManuscript(self)
810
- dialog.setModal(False)
811
- dialog.show()
812
- dialog.raise_()
813
- QApplication.processEvents()
803
+ dialog = GuiManuscript(self)
804
+ dialog.activateDialog()
814
805
  dialog.loadContent()
815
806
  return
816
807
 
@@ -827,12 +818,8 @@ class GuiMain(QMainWindow):
827
818
  def showWritingStatsDialog(self) -> None:
828
819
  """Open the session stats dialog."""
829
820
  if SHARED.hasProject:
830
- if (dialog := SHARED.findTopLevelWidget(GuiWritingStats)) is None:
831
- dialog = GuiWritingStats(self)
832
- dialog.setModal(False)
833
- dialog.show()
834
- dialog.raise_()
835
- QApplication.processEvents()
821
+ dialog = GuiWritingStats(self)
822
+ dialog.activateDialog()
836
823
  dialog.populateGUI()
837
824
  return
838
825
 
@@ -840,10 +827,7 @@ class GuiMain(QMainWindow):
840
827
  def showAboutNWDialog(self) -> None:
841
828
  """Show the novelWriter about dialog."""
842
829
  dialog = GuiAbout(self)
843
- dialog.setModal(True)
844
- dialog.show()
845
- dialog.raise_()
846
- QApplication.processEvents()
830
+ dialog.activateDialog()
847
831
  dialog.populateGUI()
848
832
  return
849
833
 
@@ -858,10 +842,7 @@ class GuiMain(QMainWindow):
858
842
  def showDictionariesDialog(self) -> None:
859
843
  """Show the download dictionaries dialog."""
860
844
  dialog = GuiDictionaries(self)
861
- dialog.setModal(True)
862
- dialog.show()
863
- dialog.raise_()
864
- QApplication.processEvents()
845
+ dialog.activateDialog()
865
846
  if not dialog.initDialog():
866
847
  dialog.close()
867
848
  SHARED.error(self.tr("Could not initialise the dialog."))
@@ -1148,7 +1129,7 @@ class GuiMain(QMainWindow):
1148
1129
  @pyqtSlot()
1149
1130
  def _reloadViewer(self) -> None:
1150
1131
  """Reload the document in the viewer."""
1151
- if self.docEditor.docChanged and self.docEditor.docHandle == self.docViewer.docHandle:
1132
+ if self.docEditor.docHandle == self.docViewer.docHandle:
1152
1133
  # If the two panels have the same document, save any changes in the editor
1153
1134
  self.saveDocument()
1154
1135
  self.docViewer.reloadText()
@@ -1228,7 +1209,7 @@ class GuiMain(QMainWindow):
1228
1209
  doSave &= SHARED.project.projChanged
1229
1210
  doSave &= SHARED.project.storage.isOpen()
1230
1211
  if doSave:
1231
- logger.debug("Autosaving project")
1212
+ logger.debug("Auto-saving project")
1232
1213
  self.saveProject(autoSave=True)
1233
1214
  return
1234
1215
 
@@ -1236,7 +1217,7 @@ class GuiMain(QMainWindow):
1236
1217
  def _autoSaveDocument(self) -> None:
1237
1218
  """Autosave of the document. This is a timer-activated slot."""
1238
1219
  if SHARED.hasProject and self.docEditor.docChanged:
1239
- logger.debug("Autosaving document")
1220
+ logger.debug("Auto-saving document")
1240
1221
  self.saveDocument()
1241
1222
  return
1242
1223
 
@@ -1416,5 +1397,3 @@ class GuiMain(QMainWindow):
1416
1397
  ))
1417
1398
  return None, None
1418
1399
  return tHandle, sTitle
1419
-
1420
- # END Class GuiMain
novelwriter/shared.py CHANGED
@@ -31,7 +31,8 @@ from time import time
31
31
  from typing import TYPE_CHECKING, TypeVar
32
32
 
33
33
  from PyQt5.QtCore import QObject, QRunnable, QThreadPool, QTimer, pyqtSignal
34
- from PyQt5.QtWidgets import QFileDialog, QMessageBox, QWidget
34
+ from PyQt5.QtGui import QFont
35
+ from PyQt5.QtWidgets import QFileDialog, QFontDialog, QMessageBox, QWidget
35
36
 
36
37
  from novelwriter.common import formatFileFilter
37
38
  from novelwriter.constants import nwFiles
@@ -171,6 +172,17 @@ class SharedData(QObject):
171
172
  logger.debug("Thread Pool Max Count: %d", QThreadPool.globalInstance().maxThreadCount())
172
173
  return
173
174
 
175
+ def closeDocument(self, tHandle: str | None = None) -> None:
176
+ """Close the document editor, optionally a specific document."""
177
+ if tHandle is None or tHandle == self.mainGui.docEditor.docHandle:
178
+ self.mainGui.closeDocument()
179
+ return
180
+
181
+ def saveDocument(self) -> None:
182
+ """Forward save document call to main GUI."""
183
+ self.mainGui.saveDocument()
184
+ return
185
+
174
186
  def openProject(self, path: str | Path, clearLock: bool = False) -> bool:
175
187
  """Open a project."""
176
188
  if self.project.isValid:
@@ -198,7 +210,7 @@ class SharedData(QObject):
198
210
 
199
211
  def closeProject(self) -> None:
200
212
  """Close the current project."""
201
- self._closeDialogs()
213
+ self._closeToolDialogs()
202
214
  self.project.closeProject(self._idleTime)
203
215
  self._resetProject()
204
216
  self._resetIdleTimer()
@@ -244,8 +256,11 @@ class SharedData(QObject):
244
256
  QThreadPool.globalInstance().start(runnable, priority=priority)
245
257
  return
246
258
 
247
- def getProjectPath(self, parent: QWidget, path: str | Path | None = None,
248
- allowZip: bool = False) -> Path | None:
259
+ def getProjectPath(
260
+ self, parent: QWidget,
261
+ path: str | Path | None = None,
262
+ allowZip: bool = False
263
+ ) -> Path | None:
249
264
  """Open the file dialog and select a novelWriter project file."""
250
265
  label = (self.tr("novelWriter Project File or Zip File")
251
266
  if allowZip else self.tr("novelWriter Project File"))
@@ -256,6 +271,13 @@ class SharedData(QObject):
256
271
  )
257
272
  return Path(selected) if selected else None
258
273
 
274
+ def getFont(self, current: QFont, native: bool) -> tuple[QFont, bool]:
275
+ """Open the font dialog and select a font."""
276
+ kwargs = {}
277
+ if not native:
278
+ kwargs["options"] = QFontDialog.FontDialogOption.DontUseNativeDialog
279
+ return QFontDialog.getFont(current, self.mainGui, self.tr("Select Font"), **kwargs)
280
+
259
281
  def findTopLevelWidget(self, kind: type[NWWidget]) -> NWWidget | None:
260
282
  """Find a top level widget."""
261
283
  for widget in self.mainGui.children():
@@ -357,19 +379,14 @@ class SharedData(QObject):
357
379
  self._idleTime = 0.0
358
380
  return
359
381
 
360
- def _closeDialogs(self) -> None:
361
- """Close non-modal dialogs."""
362
- from novelwriter.tools.manuscript import GuiManuscript
363
- from novelwriter.tools.writingstats import GuiWritingStats
364
-
382
+ def _closeToolDialogs(self) -> None:
383
+ """Close all open tool dialogs."""
384
+ from novelwriter.extensions.modified import NToolDialog
365
385
  for widget in self.mainGui.children():
366
- if isinstance(widget, (GuiManuscript, GuiWritingStats)):
386
+ if isinstance(widget, NToolDialog):
367
387
  widget.close()
368
-
369
388
  return
370
389
 
371
- # END Class SharedData
372
-
373
390
 
374
391
  class _GuiAlert(QMessageBox):
375
392
 
@@ -430,5 +447,3 @@ class _GuiAlert(QMessageBox):
430
447
  self.setIconPixmap(self._theme.getPixmap("alert_question", (pSz, pSz)))
431
448
  self.setWindowTitle(self.tr("Question"))
432
449
  return
433
-
434
- # END Class _GuiAlert
@@ -31,20 +31,20 @@ from zipfile import ZipFile
31
31
  from PyQt5.QtCore import pyqtSlot
32
32
  from PyQt5.QtGui import QCloseEvent, QTextCursor
33
33
  from PyQt5.QtWidgets import (
34
- QApplication, QDialog, QDialogButtonBox, QFileDialog, QFrame, QHBoxLayout,
35
- QLabel, QLineEdit, QPlainTextEdit, QPushButton, QVBoxLayout, QWidget
34
+ QApplication, QDialogButtonBox, QFileDialog, QFrame, QHBoxLayout, QLabel,
35
+ QLineEdit, QPlainTextEdit, QPushButton, QVBoxLayout, QWidget
36
36
  )
37
37
 
38
38
  from novelwriter import CONFIG, SHARED
39
- from novelwriter.common import formatFileFilter, formatInt, getFileSize, openExternalPath
39
+ from novelwriter.common import cssCol, formatFileFilter, formatInt, getFileSize, openExternalPath
40
40
  from novelwriter.error import formatException
41
- from novelwriter.extensions.modified import NIconToolButton
41
+ from novelwriter.extensions.modified import NIconToolButton, NNonBlockingDialog
42
42
  from novelwriter.types import QtDialogClose
43
43
 
44
44
  logger = logging.getLogger(__name__)
45
45
 
46
46
 
47
- class GuiDictionaries(QDialog):
47
+ class GuiDictionaries(NNonBlockingDialog):
48
48
 
49
49
  def __init__(self, parent: QWidget) -> None:
50
50
  super().__init__(parent=parent)
@@ -186,7 +186,7 @@ class GuiDictionaries(QDialog):
186
186
  (self.tr("Free or Libre Office extension"), "*.sox *.oxt"), "*"
187
187
  ])
188
188
  soxFile, _ = QFileDialog.getOpenFileName(
189
- self, self.tr("Browse Files"), "", filter=ffilter
189
+ self, self.tr("Browse Files"), str(CONFIG.homePath()), filter=ffilter
190
190
  )
191
191
  if soxFile:
192
192
  path = Path(soxFile).absolute()
@@ -257,13 +257,9 @@ class GuiDictionaries(QDialog):
257
257
  cursor.movePosition(QTextCursor.MoveOperation.End)
258
258
  if cursor.position() > 0:
259
259
  cursor.insertText("\n")
260
- if err:
261
- cursor.insertHtml(f"<font color='red'>{text}</font>")
262
- else:
263
- cursor.insertText(text)
260
+ textCol = cssCol(SHARED.theme.errorText if err else self.palette().text().color())
261
+ cursor.insertHtml(f"<font style='color: {textCol}'>{text}</font>")
264
262
  cursor.movePosition(QTextCursor.MoveOperation.End)
265
263
  cursor.deleteChar()
266
264
  self.infoBox.setTextCursor(cursor)
267
265
  return
268
-
269
- # END Class GuiDictionaries
@@ -23,8 +23,8 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
23
23
  """
24
24
  from __future__ import annotations
25
25
 
26
- import random
27
26
  import logging
27
+ import random
28
28
 
29
29
  from PyQt5.QtCore import Qt, pyqtSlot
30
30
  from PyQt5.QtWidgets import (
@@ -35,7 +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
+ from novelwriter.types import QtAlignLeft, QtAlignRight, QtDialogClose, QtRoleAction
39
39
 
40
40
  logger = logging.getLogger(__name__)
41
41
 
@@ -150,5 +150,3 @@ class GuiLipsum(QDialog):
150
150
  self._lipsumText = "\n\n".join(lipsumText[0:pCount]) + "\n\n"
151
151
  self.close()
152
152
  return
153
-
154
- # END Class GuiLipsum
@@ -327,7 +327,7 @@ class GuiManuscriptBuild(QDialog):
327
327
  return False
328
328
 
329
329
  # Make sure editor content is saved before we start
330
- SHARED.mainGui.saveDocument()
330
+ SHARED.saveDocument()
331
331
 
332
332
  docBuild = NWBuildDocument(SHARED.project, self._build)
333
333
  docBuild.queueAll()
@@ -403,5 +403,3 @@ class GuiManuscriptBuild(QDialog):
403
403
  """Open the build folder in the system's file explorer."""
404
404
  openExternalPath(Path(self.buildPath.text()))
405
405
  return
406
-
407
- # END Class GuiManuscriptBuild