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
@@ -25,18 +25,16 @@ from __future__ import annotations
25
25
 
26
26
  import logging
27
27
 
28
- from PyQt5.QtWidgets import (
29
- QDialog, QDialogButtonBox, QHBoxLayout, QLabel, QLineEdit, QVBoxLayout,
30
- QWidget
31
- )
28
+ from PyQt5.QtWidgets import QDialogButtonBox, QHBoxLayout, QLabel, QLineEdit, QVBoxLayout, QWidget
32
29
 
33
30
  from novelwriter import CONFIG
34
- from novelwriter.types import QtDialogCancel, QtDialogOk
31
+ from novelwriter.extensions.modified import NDialog
32
+ from novelwriter.types import QtAccepted, QtDialogCancel, QtDialogOk
35
33
 
36
34
  logger = logging.getLogger(__name__)
37
35
 
38
36
 
39
- class GuiEditLabel(QDialog):
37
+ class GuiEditLabel(NDialog):
40
38
 
41
39
  def __init__(self, parent: QWidget, text: str = "") -> None:
42
40
  super().__init__(parent=parent)
@@ -91,8 +89,6 @@ class GuiEditLabel(QDialog):
91
89
  cls = GuiEditLabel(parent, text=text)
92
90
  cls.exec()
93
91
  label = cls.itemLabel
94
- accepted = cls.result() == QDialog.DialogCode.Accepted
95
- cls.deleteLater()
92
+ accepted = cls.result() == QtAccepted
93
+ cls.softDelete()
96
94
  return label, accepted
97
-
98
- # END Class GuiEditLabel
@@ -27,29 +27,28 @@ from __future__ import annotations
27
27
  import logging
28
28
 
29
29
  from PyQt5.QtCore import Qt, pyqtSignal, pyqtSlot
30
- from PyQt5.QtGui import QCloseEvent, QFont, QKeyEvent, QKeySequence
30
+ from PyQt5.QtGui import QCloseEvent, QKeyEvent, QKeySequence
31
31
  from PyQt5.QtWidgets import (
32
- QAbstractButton, QApplication, QCompleter, QDialog, QDialogButtonBox,
33
- QFileDialog, QFontDialog, QHBoxLayout, QLineEdit, QPushButton, QVBoxLayout,
34
- QWidget
32
+ QCompleter, QDialogButtonBox, QFileDialog, QHBoxLayout, QLineEdit,
33
+ QPushButton, QVBoxLayout, QWidget
35
34
  )
36
35
 
37
36
  from novelwriter import CONFIG, SHARED
38
- from novelwriter.constants import nwConst, nwUnicode
37
+ from novelwriter.common import describeFont
38
+ from novelwriter.constants import nwUnicode
39
39
  from novelwriter.dialogs.quotes import GuiQuoteSelect
40
40
  from novelwriter.extensions.configlayout import NColourLabel, NScrollableForm
41
- from novelwriter.extensions.modified import NComboBox, NDoubleSpinBox, NIconToolButton, NSpinBox
41
+ from novelwriter.extensions.modified import (
42
+ NComboBox, NDialog, NDoubleSpinBox, NIconToolButton, NSpinBox
43
+ )
42
44
  from novelwriter.extensions.pagedsidebar import NPagedSideBar
43
45
  from novelwriter.extensions.switch import NSwitch
44
- from novelwriter.types import (
45
- QtAlignCenter, QtDialogApply, QtDialogClose, QtDialogSave, QtRoleAccept,
46
- QtRoleApply, QtRoleReject
47
- )
46
+ from novelwriter.types import QtAlignCenter, QtDialogCancel, QtDialogSave
48
47
 
49
48
  logger = logging.getLogger(__name__)
50
49
 
51
50
 
52
- class GuiPreferences(QDialog):
51
+ class GuiPreferences(NDialog):
53
52
 
54
53
  newPreferencesReady = pyqtSignal(bool, bool, bool, bool)
55
54
 
@@ -64,8 +63,8 @@ class GuiPreferences(QDialog):
64
63
 
65
64
  # Title
66
65
  self.titleLabel = NColourLabel(
67
- self.tr("Preferences"), SHARED.theme.helpText,
68
- parent=self, scale=NColourLabel.HEADER_SCALE, indent=CONFIG.pxInt(4)
66
+ self.tr("Preferences"), self, color=SHARED.theme.helpText,
67
+ scale=NColourLabel.HEADER_SCALE, indent=CONFIG.pxInt(4)
69
68
  )
70
69
 
71
70
  # Search Box
@@ -87,8 +86,9 @@ class GuiPreferences(QDialog):
87
86
  self.mainForm.setHelpTextStyle(SHARED.theme.helpText)
88
87
 
89
88
  # Buttons
90
- self.buttonBox = QDialogButtonBox(QtDialogApply | QtDialogSave | QtDialogClose, self)
91
- self.buttonBox.clicked.connect(self._dialogButtonClicked)
89
+ self.buttonBox = QDialogButtonBox(QtDialogSave | QtDialogCancel, self)
90
+ self.buttonBox.accepted.connect(self._doSave)
91
+ self.buttonBox.rejected.connect(self.reject)
92
92
 
93
93
  # Assemble
94
94
  self.searchBox = QHBoxLayout()
@@ -133,7 +133,13 @@ class GuiPreferences(QDialog):
133
133
  """Build the settings form."""
134
134
  section = 0
135
135
  iSz = SHARED.theme.baseIconSize
136
+ boxFixed = 5*SHARED.theme.textNWidth
136
137
  minWidth = CONFIG.pxInt(200)
138
+ fontWidth = CONFIG.pxInt(162)
139
+
140
+ # Temporary Variables
141
+ self._guiFont = CONFIG.guiFont
142
+ self._textFont = CONFIG.textFont
137
143
 
138
144
  # Label
139
145
  self.sidebar.addLabel(self.tr("General"))
@@ -173,27 +179,17 @@ class GuiPreferences(QDialog):
173
179
  # Application Font Family
174
180
  self.guiFont = QLineEdit(self)
175
181
  self.guiFont.setReadOnly(True)
176
- self.guiFont.setMinimumWidth(CONFIG.pxInt(162))
177
- self.guiFont.setText(CONFIG.guiFont)
178
- self.guiFontButton = NIconToolButton(self, iSz, "more")
182
+ self.guiFont.setMinimumWidth(fontWidth)
183
+ self.guiFont.setText(describeFont(self._guiFont))
184
+ self.guiFont.setCursorPosition(0)
185
+ self.guiFontButton = NIconToolButton(self, iSz, "font")
179
186
  self.guiFontButton.clicked.connect(self._selectGuiFont)
180
187
  self.mainForm.addRow(
181
- self.tr("Application font family"), self.guiFont,
188
+ self.tr("Application font"), self.guiFont,
182
189
  self.tr("Requires restart to take effect."), stretch=(3, 2),
183
190
  button=self.guiFontButton
184
191
  )
185
192
 
186
- # Application Font Size
187
- self.guiFontSize = NSpinBox(self)
188
- self.guiFontSize.setMinimum(8)
189
- self.guiFontSize.setMaximum(60)
190
- self.guiFontSize.setSingleStep(1)
191
- self.guiFontSize.setValue(CONFIG.guiFontSize)
192
- self.mainForm.addRow(
193
- self.tr("Application font size"), self.guiFontSize,
194
- self.tr("Requires restart to take effect."), unit=self.tr("pt")
195
- )
196
-
197
193
  # Vertical Scrollbars
198
194
  self.hideVScroll = NSwitch(self)
199
195
  self.hideVScroll.setChecked(CONFIG.hideVScroll)
@@ -210,6 +206,14 @@ class GuiPreferences(QDialog):
210
206
  self.tr("Scrolling available with mouse wheel and keys only.")
211
207
  )
212
208
 
209
+ # Native Font Dialog
210
+ self.nativeFont = NSwitch(self)
211
+ self.nativeFont.setChecked(CONFIG.nativeFont)
212
+ self.mainForm.addRow(
213
+ self.tr("Use the system's font selection dialog"), self.nativeFont,
214
+ self.tr("Turn off to use the Qt font dialog, which may have more options.")
215
+ )
216
+
213
217
  # Document Style
214
218
  # ==============
215
219
 
@@ -233,27 +237,17 @@ class GuiPreferences(QDialog):
233
237
  # Document Font Family
234
238
  self.textFont = QLineEdit(self)
235
239
  self.textFont.setReadOnly(True)
236
- self.textFont.setMinimumWidth(CONFIG.pxInt(162))
237
- self.textFont.setText(CONFIG.textFont)
238
- self.textFontButton = NIconToolButton(self, iSz, "more")
240
+ self.textFont.setMinimumWidth(fontWidth)
241
+ self.textFont.setText(describeFont(CONFIG.textFont))
242
+ self.textFont.setCursorPosition(0)
243
+ self.textFontButton = NIconToolButton(self, iSz, "font")
239
244
  self.textFontButton.clicked.connect(self._selectTextFont)
240
245
  self.mainForm.addRow(
241
- self.tr("Document font family"), self.textFont,
246
+ self.tr("Document font"), self.textFont,
242
247
  self.tr("Applies to both document editor and viewer."), stretch=(3, 2),
243
248
  button=self.textFontButton
244
249
  )
245
250
 
246
- # Document Font Size
247
- self.textSize = NSpinBox(self)
248
- self.textSize.setMinimum(8)
249
- self.textSize.setMaximum(60)
250
- self.textSize.setSingleStep(1)
251
- self.textSize.setValue(CONFIG.textSize)
252
- self.mainForm.addRow(
253
- self.tr("Document font size"), self.textSize,
254
- self.tr("Applies to both document editor and viewer."), unit=self.tr("pt")
255
- )
256
-
257
251
  # Emphasise Labels
258
252
  self.emphLabels = NSwitch(self)
259
253
  self.emphLabels.setChecked(CONFIG.emphLabels)
@@ -538,26 +532,59 @@ class GuiPreferences(QDialog):
538
532
  self.sidebar.addButton(title, section)
539
533
  self.mainForm.addGroupLabel(title, section)
540
534
 
541
- self.highlightQuotes = NSwitch(self)
542
- self.highlightQuotes.setChecked(CONFIG.highlightQuotes)
543
- self.highlightQuotes.toggled.connect(self._toggleHighlightQuotes)
535
+ self.dialogStyle = NComboBox(self)
536
+ self.dialogStyle.addItem(self.tr("None"), 0)
537
+ self.dialogStyle.addItem(self.tr("Single Quotes"), 1)
538
+ self.dialogStyle.addItem(self.tr("Double Quotes"), 2)
539
+ self.dialogStyle.addItem(self.tr("Both"), 3)
540
+ self.dialogStyle.setCurrentData(CONFIG.dialogStyle, 2)
544
541
  self.mainForm.addRow(
545
- self.tr("Highlight text wrapped in quotes"), self.highlightQuotes,
546
- self.tr("Applies to the document editor only.")
542
+ self.tr("Highlight dialogue"), self.dialogStyle,
543
+ self.tr("Applies to the selected quote styles.")
544
+ )
545
+
546
+ self.allowOpenDial = NSwitch(self)
547
+ self.allowOpenDial.setChecked(CONFIG.allowOpenDial)
548
+ self.mainForm.addRow(
549
+ self.tr("Allow open-ended dialogue"), self.allowOpenDial,
550
+ self.tr("Highlight dialogue line with no closing quote.")
547
551
  )
548
552
 
549
- self.allowOpenSQuote = NSwitch(self)
550
- self.allowOpenSQuote.setChecked(CONFIG.allowOpenSQuote)
553
+ self.narratorBreak = QLineEdit(self)
554
+ self.narratorBreak.setMaxLength(1)
555
+ self.narratorBreak.setFixedWidth(boxFixed)
556
+ self.narratorBreak.setAlignment(QtAlignCenter)
557
+ self.narratorBreak.setText(CONFIG.narratorBreak)
551
558
  self.mainForm.addRow(
552
- self.tr("Allow open-ended single quotes"), self.allowOpenSQuote,
553
- self.tr("Highlight single-quoted line with no closing quote.")
559
+ self.tr("Dialogue narrator break symbol"), self.narratorBreak,
560
+ self.tr("Symbol to indicate injected narrator break.")
554
561
  )
555
562
 
556
- self.allowOpenDQuote = NSwitch(self)
557
- self.allowOpenDQuote.setChecked(CONFIG.allowOpenDQuote)
563
+ self.dialogLine = QLineEdit(self)
564
+ self.dialogLine.setMaxLength(1)
565
+ self.dialogLine.setFixedWidth(boxFixed)
566
+ self.dialogLine.setAlignment(QtAlignCenter)
567
+ self.dialogLine.setText(CONFIG.dialogLine)
558
568
  self.mainForm.addRow(
559
- self.tr("Allow open-ended double quotes"), self.allowOpenDQuote,
560
- self.tr("Highlight double-quoted line with no closing quote.")
569
+ self.tr("Dialogue line symbol"), self.dialogLine,
570
+ self.tr("Lines starting with this symbol are dialogue.")
571
+ )
572
+
573
+ self.altDialogOpen = QLineEdit(self)
574
+ self.altDialogOpen.setMaxLength(4)
575
+ self.altDialogOpen.setFixedWidth(boxFixed)
576
+ self.altDialogOpen.setAlignment(QtAlignCenter)
577
+ self.altDialogOpen.setText(CONFIG.altDialogOpen)
578
+
579
+ self.altDialogClose = QLineEdit(self)
580
+ self.altDialogClose.setMaxLength(4)
581
+ self.altDialogClose.setFixedWidth(boxFixed)
582
+ self.altDialogClose.setAlignment(QtAlignCenter)
583
+ self.altDialogClose.setText(CONFIG.altDialogClose)
584
+
585
+ self.mainForm.addRow(
586
+ self.tr("Alternative dialogue symbols"), [self.altDialogOpen, self.altDialogClose],
587
+ self.tr("Custom highlighting of dialogue text.")
561
588
  )
562
589
 
563
590
  self.highlightEmph = NSwitch(self)
@@ -666,65 +693,62 @@ class GuiPreferences(QDialog):
666
693
  self.sidebar.addButton(title, section)
667
694
  self.mainForm.addGroupLabel(title, section)
668
695
 
669
- self.quoteSym = {}
670
- qWidth = CONFIG.pxInt(40)
671
-
672
696
  # Single Quote Style
673
- self.quoteSym["SO"] = QLineEdit(self)
674
- self.quoteSym["SO"].setMaxLength(1)
675
- self.quoteSym["SO"].setReadOnly(True)
676
- self.quoteSym["SO"].setFixedWidth(qWidth)
677
- self.quoteSym["SO"].setAlignment(QtAlignCenter)
678
- self.quoteSym["SO"].setText(CONFIG.fmtSQuoteOpen)
679
- self.btnSingleStyleO = NIconToolButton(self, iSz, "more")
680
- self.btnSingleStyleO.clicked.connect(lambda: self._getQuote("SO"))
681
- self.mainForm.addRow(
682
- self.tr("Single quote open style"), self.quoteSym["SO"],
697
+ self.fmtSQuoteOpen = QLineEdit(self)
698
+ self.fmtSQuoteOpen.setMaxLength(1)
699
+ self.fmtSQuoteOpen.setReadOnly(True)
700
+ self.fmtSQuoteOpen.setFixedWidth(boxFixed)
701
+ self.fmtSQuoteOpen.setAlignment(QtAlignCenter)
702
+ self.fmtSQuoteOpen.setText(CONFIG.fmtSQuoteOpen)
703
+ self.btnSQuoteOpen = NIconToolButton(self, iSz, "quote")
704
+ self.btnSQuoteOpen.clicked.connect(self._changeSingleQuoteOpen)
705
+ self.mainForm.addRow(
706
+ self.tr("Single quote open style"), self.fmtSQuoteOpen,
683
707
  self.tr("The symbol to use for a leading single quote."),
684
- button=self.btnSingleStyleO
708
+ button=self.btnSQuoteOpen
685
709
  )
686
710
 
687
- self.quoteSym["SC"] = QLineEdit(self)
688
- self.quoteSym["SC"].setMaxLength(1)
689
- self.quoteSym["SC"].setReadOnly(True)
690
- self.quoteSym["SC"].setFixedWidth(qWidth)
691
- self.quoteSym["SC"].setAlignment(QtAlignCenter)
692
- self.quoteSym["SC"].setText(CONFIG.fmtSQuoteClose)
693
- self.btnSingleStyleC = NIconToolButton(self, iSz, "more")
694
- self.btnSingleStyleC.clicked.connect(lambda: self._getQuote("SC"))
711
+ self.fmtSQuoteClose = QLineEdit(self)
712
+ self.fmtSQuoteClose.setMaxLength(1)
713
+ self.fmtSQuoteClose.setReadOnly(True)
714
+ self.fmtSQuoteClose.setFixedWidth(boxFixed)
715
+ self.fmtSQuoteClose.setAlignment(QtAlignCenter)
716
+ self.fmtSQuoteClose.setText(CONFIG.fmtSQuoteClose)
717
+ self.btnSQuoteClose = NIconToolButton(self, iSz, "quote")
718
+ self.btnSQuoteClose.clicked.connect(self._changeSingleQuoteClose)
695
719
  self.mainForm.addRow(
696
- self.tr("Single quote close style"), self.quoteSym["SC"],
720
+ self.tr("Single quote close style"), self.fmtSQuoteClose,
697
721
  self.tr("The symbol to use for a trailing single quote."),
698
- button=self.btnSingleStyleC
722
+ button=self.btnSQuoteClose
699
723
  )
700
724
 
701
725
  # Double Quote Style
702
- self.quoteSym["DO"] = QLineEdit(self)
703
- self.quoteSym["DO"].setMaxLength(1)
704
- self.quoteSym["DO"].setReadOnly(True)
705
- self.quoteSym["DO"].setFixedWidth(qWidth)
706
- self.quoteSym["DO"].setAlignment(QtAlignCenter)
707
- self.quoteSym["DO"].setText(CONFIG.fmtDQuoteOpen)
708
- self.btnDoubleStyleO = NIconToolButton(self, iSz, "more")
709
- self.btnDoubleStyleO.clicked.connect(lambda: self._getQuote("DO"))
710
- self.mainForm.addRow(
711
- self.tr("Double quote open style"), self.quoteSym["DO"],
726
+ self.fmtDQuoteOpen = QLineEdit(self)
727
+ self.fmtDQuoteOpen.setMaxLength(1)
728
+ self.fmtDQuoteOpen.setReadOnly(True)
729
+ self.fmtDQuoteOpen.setFixedWidth(boxFixed)
730
+ self.fmtDQuoteOpen.setAlignment(QtAlignCenter)
731
+ self.fmtDQuoteOpen.setText(CONFIG.fmtDQuoteOpen)
732
+ self.btnDQuoteOpen = NIconToolButton(self, iSz, "quote")
733
+ self.btnDQuoteOpen.clicked.connect(self._changeDoubleQuoteOpen)
734
+ self.mainForm.addRow(
735
+ self.tr("Double quote open style"), self.fmtDQuoteOpen,
712
736
  self.tr("The symbol to use for a leading double quote."),
713
- button=self.btnDoubleStyleO
737
+ button=self.btnDQuoteOpen
714
738
  )
715
739
 
716
- self.quoteSym["DC"] = QLineEdit(self)
717
- self.quoteSym["DC"].setMaxLength(1)
718
- self.quoteSym["DC"].setReadOnly(True)
719
- self.quoteSym["DC"].setFixedWidth(qWidth)
720
- self.quoteSym["DC"].setAlignment(QtAlignCenter)
721
- self.quoteSym["DC"].setText(CONFIG.fmtDQuoteClose)
722
- self.btnDoubleStyleC = NIconToolButton(self, iSz, "more")
723
- self.btnDoubleStyleC.clicked.connect(lambda: self._getQuote("DC"))
740
+ self.fmtDQuoteClose = QLineEdit(self)
741
+ self.fmtDQuoteClose.setMaxLength(1)
742
+ self.fmtDQuoteClose.setReadOnly(True)
743
+ self.fmtDQuoteClose.setFixedWidth(boxFixed)
744
+ self.fmtDQuoteClose.setAlignment(QtAlignCenter)
745
+ self.fmtDQuoteClose.setText(CONFIG.fmtDQuoteClose)
746
+ self.btnDQuoteClose = NIconToolButton(self, iSz, "quote")
747
+ self.btnDQuoteClose.clicked.connect(self._changeDoubleQuoteClose)
724
748
  self.mainForm.addRow(
725
- self.tr("Double quote close style"), self.quoteSym["DC"],
749
+ self.tr("Double quote close style"), self.fmtDQuoteClose,
726
750
  self.tr("The symbol to use for a trailing double quote."),
727
- button=self.btnDoubleStyleC
751
+ button=self.btnDQuoteClose
728
752
  )
729
753
 
730
754
  self.mainForm.finalise()
@@ -741,13 +765,14 @@ class GuiPreferences(QDialog):
741
765
  logger.debug("Close: GuiPreferences")
742
766
  self._saveWindowSize()
743
767
  event.accept()
744
- QApplication.processEvents()
745
- self.done(nwConst.DLG_FINISHED)
746
- self.deleteLater()
768
+ self.softDelete()
747
769
  return
748
770
 
749
771
  def keyPressEvent(self, event: QKeyEvent) -> None:
750
- """Overload keyPressEvent to block enter key to save."""
772
+ """Overload keyPressEvent and only accept escape. The main
773
+ purpose here is to prevent Enter/Return from closing the dialog
774
+ as it is used for the search box.
775
+ """
751
776
  if event.matches(QKeySequence.StandardKey.Cancel):
752
777
  self.close()
753
778
  event.ignore()
@@ -757,19 +782,6 @@ class GuiPreferences(QDialog):
757
782
  # Private Slots
758
783
  ##
759
784
 
760
- @pyqtSlot("QAbstractButton*")
761
- def _dialogButtonClicked(self, button: QAbstractButton) -> None:
762
- """Handle button clicks from the dialog button box."""
763
- role = self.buttonBox.buttonRole(button)
764
- if role == QtRoleApply:
765
- self._saveValues()
766
- elif role == QtRoleAccept:
767
- self._saveValues()
768
- self.close()
769
- elif role == QtRoleReject:
770
- self.close()
771
- return
772
-
773
785
  @pyqtSlot(int)
774
786
  def _sidebarClicked(self, section: int) -> None:
775
787
  """Process a user request to switch page."""
@@ -785,25 +797,21 @@ class GuiPreferences(QDialog):
785
797
  @pyqtSlot()
786
798
  def _selectGuiFont(self) -> None:
787
799
  """Open the QFontDialog and set a font for the font style."""
788
- current = QFont()
789
- current.setFamily(CONFIG.guiFont)
790
- current.setPointSize(CONFIG.guiFontSize)
791
- font, status = QFontDialog.getFont(current, self)
800
+ font, status = SHARED.getFont(self._guiFont, self.nativeFont.isChecked())
792
801
  if status:
793
- self.guiFont.setText(font.family())
794
- self.guiFontSize.setValue(font.pointSize())
802
+ self.guiFont.setText(describeFont(font))
803
+ self.guiFont.setCursorPosition(0)
804
+ self._guiFont = font
795
805
  return
796
806
 
797
807
  @pyqtSlot()
798
808
  def _selectTextFont(self) -> None:
799
809
  """Open the QFontDialog and set a font for the font style."""
800
- current = QFont()
801
- current.setFamily(CONFIG.textFont)
802
- current.setPointSize(CONFIG.textSize)
803
- font, status = QFontDialog.getFont(current, self)
810
+ font, status = SHARED.getFont(self._textFont, self.nativeFont.isChecked())
804
811
  if status:
805
- self.textFont.setText(font.family())
806
- self.textSize.setValue(font.pointSize())
812
+ self.textFont.setText(describeFont(font))
813
+ self.textFont.setCursorPosition(0)
814
+ self._textFont = font
807
815
  return
808
816
 
809
817
  @pyqtSlot()
@@ -823,13 +831,6 @@ class GuiPreferences(QDialog):
823
831
  self.askBeforeBackup.setEnabled(state)
824
832
  return
825
833
 
826
- @pyqtSlot(bool)
827
- def _toggleHighlightQuotes(self, state: bool) -> None:
828
- """Toggle switches controlled by the highlight quotes switch."""
829
- self.allowOpenSQuote.setEnabled(state)
830
- self.allowOpenDQuote.setEnabled(state)
831
- return
832
-
833
834
  @pyqtSlot(bool)
834
835
  def _toggleAutoReplaceMain(self, state: bool) -> None:
835
836
  """Toggle switches controlled by the auto replace switch."""
@@ -840,11 +841,36 @@ class GuiPreferences(QDialog):
840
841
  self.fmtPadThin.setEnabled(state)
841
842
  return
842
843
 
843
- def _getQuote(self, qType: str) -> None:
844
- """Dialog for single quote open."""
845
- quote, status = GuiQuoteSelect.getQuote(self, current=self.quoteSym[qType].text())
844
+ @pyqtSlot()
845
+ def _changeSingleQuoteOpen(self) -> None:
846
+ """Change single quote open style."""
847
+ quote, status = GuiQuoteSelect.getQuote(self, current=self.fmtSQuoteOpen.text())
848
+ if status:
849
+ self.fmtSQuoteOpen.setText(quote)
850
+ return
851
+
852
+ @pyqtSlot()
853
+ def _changeSingleQuoteClose(self) -> None:
854
+ """Change single quote close style."""
855
+ quote, status = GuiQuoteSelect.getQuote(self, current=self.fmtSQuoteClose.text())
856
+ if status:
857
+ self.fmtSQuoteClose.setText(quote)
858
+ return
859
+
860
+ @pyqtSlot()
861
+ def _changeDoubleQuoteOpen(self) -> None:
862
+ """Change double quote open style."""
863
+ quote, status = GuiQuoteSelect.getQuote(self, current=self.fmtDQuoteOpen.text())
846
864
  if status:
847
- self.quoteSym[qType].setText(quote)
865
+ self.fmtDQuoteOpen.setText(quote)
866
+ return
867
+
868
+ @pyqtSlot()
869
+ def _changeDoubleQuoteClose(self) -> None:
870
+ """Change double quote close style."""
871
+ quote, status = GuiQuoteSelect.getQuote(self, current=self.fmtDQuoteClose.text())
872
+ if status:
873
+ self.fmtDQuoteClose.setText(quote)
848
874
  return
849
875
 
850
876
  ##
@@ -856,7 +882,7 @@ class GuiPreferences(QDialog):
856
882
  CONFIG.setPreferencesWinSize(self.width(), self.height())
857
883
  return
858
884
 
859
- def _saveValues(self) -> None:
885
+ def _doSave(self) -> None:
860
886
  """Save the values set in the form."""
861
887
  updateTheme = False
862
888
  needsRestart = False
@@ -864,22 +890,19 @@ class GuiPreferences(QDialog):
864
890
  refreshTree = False
865
891
 
866
892
  # Appearance
867
- guiLocale = self.guiLocale.currentData()
868
- guiTheme = self.guiTheme.currentData()
869
- guiFont = self.guiFont.text()
870
- guiFontSize = self.guiFontSize.value()
893
+ guiLocale = self.guiLocale.currentData()
894
+ guiTheme = self.guiTheme.currentData()
871
895
 
872
896
  updateTheme |= CONFIG.guiTheme != guiTheme
873
897
  needsRestart |= CONFIG.guiLocale != guiLocale
874
- needsRestart |= CONFIG.guiFont != guiFont
875
- needsRestart |= CONFIG.guiFontSize != guiFontSize
898
+ needsRestart |= CONFIG.guiFont != self._guiFont
876
899
 
877
900
  CONFIG.guiLocale = guiLocale
878
901
  CONFIG.guiTheme = guiTheme
879
- CONFIG.guiFont = guiFont
880
- CONFIG.guiFontSize = guiFontSize
881
902
  CONFIG.hideVScroll = self.hideVScroll.isChecked()
882
903
  CONFIG.hideHScroll = self.hideHScroll.isChecked()
904
+ CONFIG.nativeFont = self.nativeFont.isChecked()
905
+ CONFIG.setGuiFont(self._guiFont)
883
906
 
884
907
  # Document Style
885
908
  guiSyntax = self.guiSyntax.currentData()
@@ -892,7 +915,7 @@ class GuiPreferences(QDialog):
892
915
  CONFIG.emphLabels = emphLabels
893
916
  CONFIG.showFullPath = self.showFullPath.isChecked()
894
917
  CONFIG.incNotesWCount = self.incNotesWCount.isChecked()
895
- CONFIG.setTextFont(self.textFont.text(), self.textSize.value())
918
+ CONFIG.setTextFont(self._textFont)
896
919
 
897
920
  # Auto Save
898
921
  CONFIG.autoSaveDoc = self.autoSaveDoc.value()
@@ -927,19 +950,32 @@ class GuiPreferences(QDialog):
927
950
  CONFIG.scrollPastEnd = self.scrollPastEnd.isChecked()
928
951
 
929
952
  # Text Highlighting
930
- highlightQuotes = self.highlightQuotes.isChecked()
953
+ dialogueStyle = self.dialogStyle.currentData()
954
+ allowOpenDial = self.allowOpenDial.isChecked()
955
+ narratorBreak = self.narratorBreak.text()
956
+ dialogueLine = self.dialogLine.text()
957
+ altDialogOpen = self.altDialogOpen.text()
958
+ altDialogClose = self.altDialogClose.text()
931
959
  highlightEmph = self.highlightEmph.isChecked()
932
960
  showMultiSpaces = self.showMultiSpaces.isChecked()
933
961
 
934
- updateSyntax |= CONFIG.highlightQuotes != highlightQuotes
962
+ updateSyntax |= CONFIG.dialogStyle != dialogueStyle
963
+ updateSyntax |= CONFIG.allowOpenDial != allowOpenDial
964
+ updateSyntax |= CONFIG.narratorBreak != narratorBreak
965
+ updateSyntax |= CONFIG.dialogLine != dialogueLine
966
+ updateSyntax |= CONFIG.altDialogOpen != altDialogOpen
967
+ updateSyntax |= CONFIG.altDialogClose != altDialogClose
935
968
  updateSyntax |= CONFIG.highlightEmph != highlightEmph
936
969
  updateSyntax |= CONFIG.showMultiSpaces != showMultiSpaces
937
970
 
938
- CONFIG.highlightQuotes = highlightQuotes
971
+ CONFIG.dialogStyle = dialogueStyle
972
+ CONFIG.allowOpenDial = allowOpenDial
973
+ CONFIG.narratorBreak = narratorBreak
974
+ CONFIG.dialogLine = dialogueLine
975
+ CONFIG.altDialogOpen = altDialogOpen
976
+ CONFIG.altDialogClose = altDialogClose
939
977
  CONFIG.highlightEmph = highlightEmph
940
978
  CONFIG.showMultiSpaces = showMultiSpaces
941
- CONFIG.allowOpenSQuote = self.allowOpenSQuote.isChecked()
942
- CONFIG.allowOpenDQuote = self.allowOpenDQuote.isChecked()
943
979
 
944
980
  # Text Automation
945
981
  CONFIG.doReplace = self.doReplace.isChecked()
@@ -952,15 +988,15 @@ class GuiPreferences(QDialog):
952
988
  CONFIG.fmtPadThin = self.fmtPadThin.isChecked()
953
989
 
954
990
  # Quotation Style
955
- CONFIG.fmtSQuoteOpen = self.quoteSym["SO"].text()
956
- CONFIG.fmtSQuoteClose = self.quoteSym["SC"].text()
957
- CONFIG.fmtDQuoteOpen = self.quoteSym["DO"].text()
958
- CONFIG.fmtDQuoteClose = self.quoteSym["DC"].text()
991
+ CONFIG.fmtSQuoteOpen = self.fmtSQuoteOpen.text()
992
+ CONFIG.fmtSQuoteClose = self.fmtSQuoteClose.text()
993
+ CONFIG.fmtDQuoteOpen = self.fmtDQuoteOpen.text()
994
+ CONFIG.fmtDQuoteClose = self.fmtDQuoteClose.text()
959
995
 
960
996
  # Finalise
961
997
  CONFIG.saveConfig()
962
998
  self.newPreferencesReady.emit(needsRestart, refreshTree, updateTheme, updateSyntax)
963
999
 
964
- return
1000
+ self.close()
965
1001
 
966
- # END Class GuiPreferences
1002
+ return