novelWriter 2.7.4__py3-none-any.whl → 2.8b1__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 (196) hide show
  1. novelwriter/__init__.py +8 -7
  2. novelwriter/assets/icons/font_awesome.icons +22 -4
  3. novelwriter/assets/icons/material_filled_normal.icons +20 -2
  4. novelwriter/assets/icons/material_filled_thin.icons +20 -2
  5. novelwriter/assets/icons/material_rounded_normal.icons +20 -2
  6. novelwriter/assets/icons/material_rounded_thin.icons +20 -2
  7. novelwriter/assets/icons/material_sharp_normal.icons +20 -2
  8. novelwriter/assets/icons/material_sharp_thin.icons +20 -2
  9. novelwriter/assets/icons/remix_filled.icons +20 -2
  10. novelwriter/assets/icons/remix_outline.icons +20 -2
  11. novelwriter/assets/images/welcome.webp +0 -0
  12. novelwriter/assets/manual.pdf +0 -0
  13. novelwriter/assets/manual_fr.pdf +0 -0
  14. novelwriter/assets/sample.zip +0 -0
  15. novelwriter/assets/text/credits_en.htm +61 -11
  16. novelwriter/assets/themes/aura.conf +97 -0
  17. novelwriter/assets/themes/aura_bright.conf +95 -0
  18. novelwriter/assets/themes/aura_soft.conf +97 -0
  19. novelwriter/assets/themes/b2t_garden_dark.conf +97 -0
  20. novelwriter/assets/themes/b2t_garden_light.conf +97 -0
  21. novelwriter/assets/themes/b2t_suburb_dark.conf +97 -0
  22. novelwriter/assets/themes/b2t_suburb_light.conf +97 -0
  23. novelwriter/assets/themes/b4t_classic_o_dark.conf +97 -0
  24. novelwriter/assets/themes/b4t_classic_o_light.conf +97 -0
  25. novelwriter/assets/themes/b4t_modern_c_dark.conf +97 -0
  26. novelwriter/assets/themes/b4t_modern_c_light.conf +97 -0
  27. novelwriter/assets/themes/blue_streak_dark.conf +97 -0
  28. novelwriter/assets/themes/blue_streak_light.conf +97 -0
  29. novelwriter/assets/themes/castle_day.conf +95 -0
  30. novelwriter/assets/themes/castle_night.conf +95 -0
  31. novelwriter/assets/themes/catppuccin_latte.conf +97 -0
  32. novelwriter/assets/themes/catppuccin_mocha.conf +97 -0
  33. novelwriter/assets/themes/chalky_soil.conf +95 -0
  34. novelwriter/assets/themes/chernozem.conf +95 -0
  35. novelwriter/assets/themes/cyberpunk_night.conf +88 -40
  36. novelwriter/assets/themes/default_dark.conf +89 -41
  37. novelwriter/assets/themes/default_light.conf +89 -41
  38. novelwriter/assets/themes/dracula.conf +91 -42
  39. novelwriter/assets/themes/espresso.conf +97 -0
  40. novelwriter/assets/themes/everforest_dark.conf +97 -0
  41. novelwriter/assets/themes/everforest_light.conf +97 -0
  42. novelwriter/assets/themes/floral_daydream.conf +95 -0
  43. novelwriter/assets/themes/floral_midnight.conf +95 -0
  44. novelwriter/assets/themes/full_moon.conf +95 -0
  45. novelwriter/assets/themes/grey_dark.conf +97 -0
  46. novelwriter/assets/themes/grey_light.conf +97 -0
  47. novelwriter/assets/themes/horizon_dark.conf +97 -0
  48. novelwriter/assets/themes/horizon_light.conf +97 -0
  49. novelwriter/assets/themes/jewel_case_dark.conf +95 -0
  50. novelwriter/assets/themes/jewel_case_light.conf +95 -0
  51. novelwriter/assets/themes/lcars.conf +97 -0
  52. novelwriter/assets/themes/light_owl.conf +117 -0
  53. novelwriter/assets/themes/new_moon.conf +97 -0
  54. novelwriter/assets/themes/night_owl.conf +117 -0
  55. novelwriter/assets/themes/noctis.conf +129 -0
  56. novelwriter/assets/themes/noctis_lux.conf +129 -0
  57. novelwriter/assets/themes/nord.conf +97 -0
  58. novelwriter/assets/themes/nordlicht.conf +95 -0
  59. novelwriter/assets/themes/otium_dark.conf +95 -0
  60. novelwriter/assets/themes/otium_light.conf +95 -0
  61. novelwriter/assets/themes/paragon.conf +96 -0
  62. novelwriter/assets/themes/primer_light.conf +97 -0
  63. novelwriter/assets/themes/primer_night.conf +97 -0
  64. novelwriter/assets/themes/rose_pine.conf +97 -0
  65. novelwriter/assets/themes/rose_pine_dawn.conf +97 -0
  66. novelwriter/assets/themes/ruby_day.conf +95 -0
  67. novelwriter/assets/themes/ruby_night.conf +95 -0
  68. novelwriter/assets/themes/selenium_dark.conf +95 -0
  69. novelwriter/assets/themes/selenium_light.conf +95 -0
  70. novelwriter/assets/themes/sepia_dark.conf +95 -0
  71. novelwriter/assets/themes/sepia_light.conf +95 -0
  72. novelwriter/assets/themes/snazzy.conf +102 -40
  73. novelwriter/assets/themes/solarized_dark.conf +108 -40
  74. novelwriter/assets/themes/solarized_light.conf +108 -40
  75. novelwriter/assets/themes/sultana_light.conf +95 -0
  76. novelwriter/assets/themes/sultana_night.conf +95 -0
  77. novelwriter/assets/themes/tango_dark.conf +111 -0
  78. novelwriter/assets/themes/tango_light.conf +111 -0
  79. novelwriter/assets/themes/tomorrow.conf +117 -0
  80. novelwriter/assets/themes/tomorrow_night.conf +117 -0
  81. novelwriter/assets/themes/tomorrow_night_blue.conf +117 -0
  82. novelwriter/assets/themes/tomorrow_night_bright.conf +117 -0
  83. novelwriter/assets/themes/tomorrow_night_eighties.conf +117 -0
  84. novelwriter/assets/themes/vivid_black_green.conf +97 -0
  85. novelwriter/assets/themes/vivid_black_red.conf +97 -0
  86. novelwriter/assets/themes/vivid_white_green.conf +97 -0
  87. novelwriter/assets/themes/vivid_white_red.conf +97 -0
  88. novelwriter/assets/themes/warpgate.conf +96 -0
  89. novelwriter/assets/themes/waterlily_dark.conf +95 -0
  90. novelwriter/assets/themes/waterlily_light.conf +95 -0
  91. novelwriter/common.py +47 -17
  92. novelwriter/config.py +57 -62
  93. novelwriter/constants.py +32 -6
  94. novelwriter/core/buildsettings.py +3 -23
  95. novelwriter/core/coretools.py +21 -25
  96. novelwriter/core/docbuild.py +4 -9
  97. novelwriter/core/document.py +2 -6
  98. novelwriter/core/index.py +33 -53
  99. novelwriter/core/indexdata.py +17 -22
  100. novelwriter/core/item.py +11 -35
  101. novelwriter/core/itemmodel.py +5 -21
  102. novelwriter/core/novelmodel.py +3 -7
  103. novelwriter/core/options.py +3 -4
  104. novelwriter/core/project.py +31 -21
  105. novelwriter/core/projectdata.py +2 -21
  106. novelwriter/core/projectxml.py +13 -21
  107. novelwriter/core/sessions.py +2 -4
  108. novelwriter/core/spellcheck.py +12 -13
  109. novelwriter/core/status.py +27 -20
  110. novelwriter/core/storage.py +5 -10
  111. novelwriter/core/tree.py +6 -15
  112. novelwriter/dialogs/about.py +9 -10
  113. novelwriter/dialogs/docmerge.py +17 -14
  114. novelwriter/dialogs/docsplit.py +18 -14
  115. novelwriter/dialogs/editlabel.py +15 -9
  116. novelwriter/dialogs/preferences.py +69 -68
  117. novelwriter/dialogs/projectsettings.py +88 -67
  118. novelwriter/dialogs/quotes.py +15 -10
  119. novelwriter/dialogs/wordlist.py +18 -21
  120. novelwriter/enum.py +75 -30
  121. novelwriter/error.py +6 -11
  122. novelwriter/extensions/configlayout.py +8 -34
  123. novelwriter/extensions/eventfilters.py +3 -3
  124. novelwriter/extensions/modified.py +87 -32
  125. novelwriter/extensions/novelselector.py +13 -12
  126. novelwriter/extensions/pagedsidebar.py +10 -18
  127. novelwriter/extensions/progressbars.py +5 -11
  128. novelwriter/extensions/statusled.py +3 -6
  129. novelwriter/extensions/switch.py +8 -11
  130. novelwriter/extensions/switchbox.py +2 -11
  131. novelwriter/extensions/versioninfo.py +6 -7
  132. novelwriter/formats/shared.py +10 -2
  133. novelwriter/formats/todocx.py +15 -37
  134. novelwriter/formats/tohtml.py +52 -61
  135. novelwriter/formats/tokenizer.py +33 -64
  136. novelwriter/formats/tomarkdown.py +4 -11
  137. novelwriter/formats/toodt.py +12 -71
  138. novelwriter/formats/toqdoc.py +11 -21
  139. novelwriter/formats/toraw.py +2 -6
  140. novelwriter/gui/doceditor.py +207 -245
  141. novelwriter/gui/dochighlight.py +142 -101
  142. novelwriter/gui/docviewer.py +53 -84
  143. novelwriter/gui/docviewerpanel.py +18 -41
  144. novelwriter/gui/editordocument.py +12 -17
  145. novelwriter/gui/itemdetails.py +5 -14
  146. novelwriter/gui/mainmenu.py +24 -32
  147. novelwriter/gui/noveltree.py +13 -51
  148. novelwriter/gui/outline.py +20 -61
  149. novelwriter/gui/projtree.py +40 -96
  150. novelwriter/gui/search.py +9 -24
  151. novelwriter/gui/sidebar.py +54 -22
  152. novelwriter/gui/statusbar.py +7 -22
  153. novelwriter/gui/theme.py +482 -368
  154. novelwriter/guimain.py +87 -101
  155. novelwriter/shared.py +79 -48
  156. novelwriter/splash.py +9 -5
  157. novelwriter/text/comments.py +1 -1
  158. novelwriter/text/counting.py +9 -5
  159. novelwriter/text/patterns.py +20 -15
  160. novelwriter/tools/dictionaries.py +18 -16
  161. novelwriter/tools/lipsum.py +15 -17
  162. novelwriter/tools/manusbuild.py +25 -45
  163. novelwriter/tools/manuscript.py +94 -95
  164. novelwriter/tools/manussettings.py +149 -104
  165. novelwriter/tools/noveldetails.py +10 -24
  166. novelwriter/tools/welcome.py +24 -72
  167. novelwriter/tools/writingstats.py +17 -26
  168. novelwriter/types.py +25 -13
  169. {novelwriter-2.7.4.dist-info → novelwriter-2.8b1.dist-info}/METADATA +7 -7
  170. novelwriter-2.8b1.dist-info/RECORD +212 -0
  171. novelwriter/assets/images/welcome-dark.jpg +0 -0
  172. novelwriter/assets/images/welcome-light.jpg +0 -0
  173. novelwriter/assets/syntax/cyberpunk_night.conf +0 -28
  174. novelwriter/assets/syntax/default_dark.conf +0 -42
  175. novelwriter/assets/syntax/default_light.conf +0 -42
  176. novelwriter/assets/syntax/dracula.conf +0 -44
  177. novelwriter/assets/syntax/grey_dark.conf +0 -29
  178. novelwriter/assets/syntax/grey_light.conf +0 -29
  179. novelwriter/assets/syntax/light_owl.conf +0 -49
  180. novelwriter/assets/syntax/night_owl.conf +0 -49
  181. novelwriter/assets/syntax/snazzy.conf +0 -42
  182. novelwriter/assets/syntax/solarized_dark.conf +0 -29
  183. novelwriter/assets/syntax/solarized_light.conf +0 -29
  184. novelwriter/assets/syntax/tango.conf +0 -39
  185. novelwriter/assets/syntax/tomorrow.conf +0 -49
  186. novelwriter/assets/syntax/tomorrow_night.conf +0 -49
  187. novelwriter/assets/syntax/tomorrow_night_blue.conf +0 -49
  188. novelwriter/assets/syntax/tomorrow_night_bright.conf +0 -49
  189. novelwriter/assets/syntax/tomorrow_night_eighties.conf +0 -49
  190. novelwriter/assets/themes/default.conf +0 -3
  191. novelwriter-2.7.4.dist-info/RECORD +0 -163
  192. {novelwriter-2.7.4.dist-info → novelwriter-2.8b1.dist-info}/WHEEL +0 -0
  193. {novelwriter-2.7.4.dist-info → novelwriter-2.8b1.dist-info}/entry_points.txt +0 -0
  194. {novelwriter-2.7.4.dist-info → novelwriter-2.8b1.dist-info}/licenses/LICENSE.md +0 -0
  195. {novelwriter-2.7.4.dist-info → novelwriter-2.8b1.dist-info}/licenses/setup/LICENSE-Apache-2.0.txt +0 -0
  196. {novelwriter-2.7.4.dist-info → novelwriter-2.8b1.dist-info}/top_level.txt +0 -0
@@ -20,7 +20,7 @@ General Public License for more details.
20
20
 
21
21
  You should have received a copy of the GNU General Public License
22
22
  along with this program. If not, see <https://www.gnu.org/licenses/>.
23
- """
23
+ """ # noqa
24
24
  from __future__ import annotations
25
25
 
26
26
  import logging
@@ -36,9 +36,9 @@ from PyQt6.QtGui import (
36
36
  from PyQt6.QtPrintSupport import QPrinter, QPrintPreviewDialog
37
37
  from PyQt6.QtWidgets import (
38
38
  QAbstractItemView, QApplication, QFormLayout, QGridLayout, QHBoxLayout,
39
- QLabel, QListWidget, QListWidgetItem, QPushButton, QSplitter,
40
- QStackedWidget, QTabWidget, QTextBrowser, QTreeWidget, QTreeWidgetItem,
41
- QVBoxLayout, QWidget
39
+ QLabel, QListWidget, QListWidgetItem, QSplitter, QStackedWidget,
40
+ QTabWidget, QTextBrowser, QTreeWidget, QTreeWidgetItem, QVBoxLayout,
41
+ QWidget
42
42
  )
43
43
 
44
44
  from novelwriter import CONFIG, SHARED
@@ -46,6 +46,7 @@ from novelwriter.common import fuzzyTime, qtLambda
46
46
  from novelwriter.constants import nwHeadFmt, nwLabels, nwStats, nwUnicode, trStats
47
47
  from novelwriter.core.buildsettings import BuildCollection, BuildSettings
48
48
  from novelwriter.core.docbuild import NWBuildDocument
49
+ from novelwriter.enum import nwStandardButton
49
50
  from novelwriter.extensions.modified import NIconToggleButton, NIconToolButton, NToolDialog
50
51
  from novelwriter.extensions.progressbars import NProgressCircle
51
52
  from novelwriter.extensions.switch import NSwitch
@@ -66,7 +67,7 @@ logger = logging.getLogger(__name__)
66
67
 
67
68
 
68
69
  class GuiManuscript(NToolDialog):
69
- """GUI Tools: Manuscript Tool
70
+ """GUI Tools: Manuscript Tool.
70
71
 
71
72
  The dialog displays all the users build definitions, a preview panel
72
73
  for the manuscript, and can trigger the actual build dialog to build
@@ -91,39 +92,29 @@ class GuiManuscript(NToolDialog):
91
92
  iPx = SHARED.theme.baseIconHeight
92
93
  iSz = SHARED.theme.baseIconSize
93
94
 
94
- pOptions = SHARED.project.options
95
+ options = SHARED.project.options
95
96
  self.resize(
96
- pOptions.getInt("GuiManuscript", "winWidth", 900),
97
- pOptions.getInt("GuiManuscript", "winHeight", 600),
97
+ options.getInt("GuiManuscript", "winWidth", 900),
98
+ options.getInt("GuiManuscript", "winHeight", 600),
98
99
  )
99
100
 
100
101
  # Build Controls
101
102
  # ==============
102
103
 
103
- qPalette = self.palette()
104
- qPalette.setBrush(QPalette.ColorRole.Window, qPalette.base())
105
- self.setPalette(qPalette)
106
-
107
- buttonStyle = SHARED.theme.getStyleSheet(STYLES_MIN_TOOLBUTTON)
108
-
109
- self.tbAdd = NIconToolButton(self, iSz, "add", "green")
104
+ self.tbAdd = NIconToolButton(self, iSz)
110
105
  self.tbAdd.setToolTip(self.tr("Add New Build"))
111
- self.tbAdd.setStyleSheet(buttonStyle)
112
106
  self.tbAdd.clicked.connect(self._createNewBuild)
113
107
 
114
- self.tbDel = NIconToolButton(self, iSz, "remove", "red")
108
+ self.tbDel = NIconToolButton(self, iSz)
115
109
  self.tbDel.setToolTip(self.tr("Delete Selected Build"))
116
- self.tbDel.setStyleSheet(buttonStyle)
117
110
  self.tbDel.clicked.connect(self._deleteSelectedBuild)
118
111
 
119
- self.tbCopy = NIconToolButton(self, iSz, "copy", "blue")
112
+ self.tbCopy = NIconToolButton(self, iSz)
120
113
  self.tbCopy.setToolTip(self.tr("Duplicate Selected Build"))
121
- self.tbCopy.setStyleSheet(buttonStyle)
122
114
  self.tbCopy.clicked.connect(self._copySelectedBuild)
123
115
 
124
- self.tbEdit = NIconToolButton(self, iSz, "edit", "green")
116
+ self.tbEdit = NIconToolButton(self, iSz)
125
117
  self.tbEdit.setToolTip(self.tr("Edit Selected Build"))
126
- self.tbEdit.setStyleSheet(buttonStyle)
127
118
  self.tbEdit.clicked.connect(self._editSelectedBuild)
128
119
 
129
120
  self.lblBuilds = QLabel("<b>{0}</b>".format(self.tr("Builds")), self)
@@ -151,36 +142,35 @@ class GuiManuscript(NToolDialog):
151
142
  # ============
152
143
 
153
144
  self.buildDetails = _DetailsWidget(self)
154
- self.buildDetails.setColumnWidth(pOptions.getInt("GuiManuscript", "detailsWidth", 100))
145
+ self.buildDetails.setColumnWidth(options.getInt("GuiManuscript", "detailsWidth", 100))
155
146
 
156
147
  self.buildOutline = _OutlineWidget(self)
157
148
 
158
149
  self.detailsTabs = QTabWidget(self)
159
150
  self.detailsTabs.addTab(self.buildDetails, self.tr("Details"))
160
151
  self.detailsTabs.addTab(self.buildOutline, self.tr("Outline"))
161
- self.detailsTabs.setStyleSheet(SHARED.theme.getStyleSheet(STYLES_FLAT_TABS))
162
152
 
163
153
  self.buildSplit = QSplitter(Qt.Orientation.Vertical, self)
164
154
  self.buildSplit.addWidget(self.buildList)
165
155
  self.buildSplit.addWidget(self.detailsTabs)
166
156
  self.buildSplit.setSizes([
167
- pOptions.getInt("GuiManuscript", "listHeight", 50),
168
- pOptions.getInt("GuiManuscript", "detailsHeight", 50),
157
+ options.getInt("GuiManuscript", "listHeight", 50),
158
+ options.getInt("GuiManuscript", "detailsHeight", 50),
169
159
  ])
170
160
 
171
161
  # Process Controls
172
162
  # ================
173
163
 
174
- self.btnPreview = QPushButton(self.tr("Preview"), self)
164
+ self.btnPreview = SHARED.theme.getStandardButton(nwStandardButton.PREVIEW, self)
175
165
  self.btnPreview.clicked.connect(self._generatePreview)
176
166
 
177
- self.btnPrint = QPushButton(self.tr("Print"), self)
167
+ self.btnPrint = SHARED.theme.getStandardButton(nwStandardButton.PRINT, self)
178
168
  self.btnPrint.clicked.connect(self._printDocument)
179
169
 
180
- self.btnBuild = QPushButton(self.tr("Build"), self)
170
+ self.btnBuild = SHARED.theme.getStandardButton(nwStandardButton.BUILD, self)
181
171
  self.btnBuild.clicked.connect(self._buildManuscript)
182
172
 
183
- self.btnClose = QPushButton(self.tr("Close"), self)
173
+ self.btnClose = SHARED.theme.getStandardButton(nwStandardButton.CLOSE, self)
184
174
  self.btnClose.clicked.connect(qtLambda(self.close))
185
175
 
186
176
  self.processBox = QGridLayout()
@@ -193,7 +183,7 @@ class GuiManuscript(NToolDialog):
193
183
  # ===============
194
184
 
195
185
  self.swtNewPage = NSwitch(self, height=iPx)
196
- self.swtNewPage.setChecked(pOptions.getBool("GuiManuscript", "showNewPage", True))
186
+ self.swtNewPage.setChecked(options.getBool("GuiManuscript", "showNewPage", True))
197
187
  self.swtNewPage.clicked.connect(self._generatePreview)
198
188
 
199
189
  self.lblNewPage = QLabel(self.tr("Show Page Breaks"), self)
@@ -236,8 +226,8 @@ class GuiManuscript(NToolDialog):
236
226
  self.mainSplit.setStretchFactor(0, 0)
237
227
  self.mainSplit.setStretchFactor(1, 1)
238
228
  self.mainSplit.setSizes([
239
- pOptions.getInt("GuiManuscript", "optsWidth", 225),
240
- pOptions.getInt("GuiManuscript", "viewWidth", 675),
229
+ options.getInt("GuiManuscript", "optsWidth", 225),
230
+ options.getInt("GuiManuscript", "viewWidth", 675),
241
231
  ])
242
232
 
243
233
  self.outerBox = QVBoxLayout()
@@ -246,16 +236,15 @@ class GuiManuscript(NToolDialog):
246
236
  self.setLayout(self.outerBox)
247
237
  self.setSizeGripEnabled(True)
248
238
 
239
+ self.updateTheme(init=True)
240
+
249
241
  # Signals
250
242
  self.buildOutline.outlineEntryClicked.connect(self.docPreview.navigateTo)
251
243
 
252
244
  logger.debug("Ready: GuiManuscript")
253
245
 
254
- return
255
-
256
246
  def __del__(self) -> None: # pragma: no cover
257
247
  logger.debug("Delete: GuiManuscript")
258
- return
259
248
 
260
249
  def loadContent(self) -> None:
261
250
  """Load dialog content from project data."""
@@ -272,7 +261,36 @@ class GuiManuscript(NToolDialog):
272
261
  self.buildList.setCurrentItem(self._buildMap[selected])
273
262
  QTimer.singleShot(200, self._generatePreview)
274
263
 
275
- return
264
+ def updateTheme(self, *, init: bool = False) -> None:
265
+ """Update theme elements."""
266
+ logger.debug("Theme Update: GuiManuscript, init=%s", init)
267
+
268
+ if not init:
269
+ self.btnPreview.updateIcon()
270
+ self.btnPrint.updateIcon()
271
+ self.btnBuild.updateIcon()
272
+ self.btnClose.updateIcon()
273
+
274
+ self.tbAdd.setThemeIcon("add", "add")
275
+ self.tbDel.setThemeIcon("remove", "remove")
276
+ self.tbCopy.setThemeIcon("copy", "action")
277
+ self.tbEdit.setThemeIcon("edit", "change")
278
+
279
+ buttonStyle = SHARED.theme.getStyleSheet(STYLES_MIN_TOOLBUTTON)
280
+ self.tbAdd.setStyleSheet(buttonStyle)
281
+ self.tbDel.setStyleSheet(buttonStyle)
282
+ self.tbCopy.setStyleSheet(buttonStyle)
283
+ self.tbEdit.setStyleSheet(buttonStyle)
284
+
285
+ self.detailsTabs.setStyleSheet(SHARED.theme.getStyleSheet(STYLES_FLAT_TABS))
286
+
287
+ self.buildDetails.updateTheme()
288
+ self.buildOutline.updateTheme()
289
+ self.docPreview.updateTheme()
290
+
291
+ for obj in SHARED.mainGui.children():
292
+ if isinstance(obj, GuiBuildSettings):
293
+ obj.updateTheme()
276
294
 
277
295
  ##
278
296
  # Events
@@ -290,7 +308,6 @@ class GuiManuscript(NToolDialog):
290
308
  obj.close()
291
309
  event.accept()
292
310
  self.softDelete()
293
- return
294
311
 
295
312
  ##
296
313
  # Private Slots
@@ -302,14 +319,12 @@ class GuiManuscript(NToolDialog):
302
319
  build = BuildSettings()
303
320
  build.setName(self.tr("My Manuscript"))
304
321
  self._openSettingsDialog(build)
305
- return
306
322
 
307
323
  @pyqtSlot()
308
324
  def _editSelectedBuild(self) -> None:
309
325
  """Edit the currently selected build settings entry."""
310
326
  if build := self._getSelectedBuild():
311
327
  self._openSettingsDialog(build)
312
- return
313
328
 
314
329
  @pyqtSlot()
315
330
  def _copySelectedBuild(self) -> None:
@@ -320,14 +335,12 @@ class GuiManuscript(NToolDialog):
320
335
  self._updateBuildsList()
321
336
  if item := self._buildMap.get(new.buildID):
322
337
  item.setSelected(True)
323
- return
324
338
 
325
339
  @pyqtSlot("QListWidgetItem*", "QListWidgetItem*")
326
340
  def _updateBuildDetails(self, current: QListWidgetItem, previous: QListWidgetItem) -> None:
327
341
  """Process change of build selection to update the details."""
328
342
  if current and (build := self._builds.getBuild(current.data(self.D_KEY))):
329
343
  self.buildDetails.updateInfo(build)
330
- return
331
344
 
332
345
  @pyqtSlot()
333
346
  def _deleteSelectedBuild(self) -> None:
@@ -338,16 +351,17 @@ class GuiManuscript(NToolDialog):
338
351
  dialog.close()
339
352
  self._builds.removeBuild(build.buildID)
340
353
  self._updateBuildsList()
341
- return
342
354
 
343
- @pyqtSlot(BuildSettings)
344
- def _processNewSettings(self, build: BuildSettings) -> None:
355
+ @pyqtSlot(BuildSettings, bool)
356
+ def _processNewSettings(self, build: BuildSettings, refreshPreview: bool) -> None:
345
357
  """Process new build settings from the settings dialog."""
346
358
  self._builds.setBuild(build)
347
359
  self._updateBuildItem(build)
348
- if (current := self.buildList.currentItem()) and current.data(self.D_KEY) == build.buildID:
349
- self._updateBuildDetails(current, current)
350
- return
360
+ if refreshPreview:
361
+ self.buildList.setCurrentItem(self._buildMap[build.buildID])
362
+ self._generatePreview()
363
+ elif (item := self.buildList.currentItem()) and item.data(self.D_KEY) == build.buildID:
364
+ self._updateBuildDetails(item, item)
351
365
 
352
366
  @pyqtSlot()
353
367
  def _generatePreview(self) -> None:
@@ -399,15 +413,12 @@ class GuiManuscript(NToolDialog):
399
413
  if build.changed:
400
414
  self._builds.setBuild(build)
401
415
 
402
- return
403
-
404
416
  @pyqtSlot()
405
417
  def _printDocument(self) -> None:
406
418
  """Open the print preview dialog."""
407
419
  preview = QPrintPreviewDialog(self)
408
420
  preview.paintRequested.connect(self.docPreview.printPreview)
409
421
  preview.exec()
410
- return
411
422
 
412
423
  ##
413
424
  # Internal Functions
@@ -456,8 +467,6 @@ class GuiManuscript(NToolDialog):
456
467
  pOptions.setValue("GuiManuscript", "showNewPage", showNewPage)
457
468
  pOptions.saveSettings()
458
469
 
459
- return
460
-
461
470
  def _openSettingsDialog(self, build: BuildSettings) -> None:
462
471
  """Open the build settings dialog."""
463
472
  if dialog := self._findSettingsDialog(build.buildID):
@@ -478,11 +487,10 @@ class GuiManuscript(NToolDialog):
478
487
  for key, name in self._builds.builds():
479
488
  bItem = QListWidgetItem()
480
489
  bItem.setText(name)
481
- bItem.setIcon(SHARED.theme.getIcon("build_settings", "blue"))
490
+ bItem.setIcon(SHARED.theme.getIcon("build_settings", "action"))
482
491
  bItem.setData(self.D_KEY, key)
483
492
  self.buildList.addItem(bItem)
484
493
  self._buildMap[key] = bItem
485
- return
486
494
 
487
495
  def _updateBuildItem(self, build: BuildSettings) -> None:
488
496
  """Update the entry of a specific build item."""
@@ -490,7 +498,6 @@ class GuiManuscript(NToolDialog):
490
498
  item.setText(build.name)
491
499
  else: # Probably a new item
492
500
  self._updateBuildsList()
493
- return
494
501
 
495
502
  def _findSettingsDialog(self, buildID: str) -> GuiBuildSettings | None:
496
503
  """Return an open build settings dialog for a given build, if
@@ -508,6 +515,7 @@ class _DetailsWidget(QWidget):
508
515
  super().__init__(parent=parent)
509
516
 
510
517
  self._initExpanded = True
518
+ self._build = None
511
519
 
512
520
  # Tree Widget
513
521
  self.listView = QTreeWidget(self)
@@ -521,8 +529,6 @@ class _DetailsWidget(QWidget):
521
529
  self.outerBox.setContentsMargins(0, 0, 0, 0)
522
530
  self.setLayout(self.outerBox)
523
531
 
524
- return
525
-
526
532
  ##
527
533
  # Getters
528
534
  ##
@@ -547,7 +553,6 @@ class _DetailsWidget(QWidget):
547
553
  def setColumnWidth(self, value: int) -> None:
548
554
  """Set the width of the first column."""
549
555
  self.listView.setColumnWidth(0, value)
550
- return
551
556
 
552
557
  def setExpandedState(self, state: list[bool]) -> None:
553
558
  """Set the expanded state of each top level item."""
@@ -556,7 +561,6 @@ class _DetailsWidget(QWidget):
556
561
  item = self.listView.topLevelItem(i)
557
562
  if isinstance(item, QTreeWidgetItem):
558
563
  item.setExpanded((state[i] if i < count else True) and item.childCount() > 0)
559
- return
560
564
 
561
565
  ##
562
566
  # Methods
@@ -573,8 +577,8 @@ class _DetailsWidget(QWidget):
573
577
 
574
578
  self.listView.clear()
575
579
 
576
- on = SHARED.theme.getIcon("bullet-on", "blue")
577
- off = SHARED.theme.getIcon("bullet-off", "blue")
580
+ on = SHARED.theme.getIcon("bullet-on", "action")
581
+ off = SHARED.theme.getIcon("bullet-off", "action")
578
582
 
579
583
  # Name
580
584
  item = QTreeWidgetItem()
@@ -634,10 +638,16 @@ class _DetailsWidget(QWidget):
634
638
  sub.setIcon(1, on if build.getBool(key) else off)
635
639
  item.addChild(sub)
636
640
 
641
+ self._build = build
642
+
637
643
  # Restore expanded state
638
644
  self.setExpandedState(expanded)
639
645
 
640
- return
646
+ def updateTheme(self) -> None:
647
+ """Update theme elements."""
648
+ if self._build:
649
+ logger.debug("Theme Update: _DetailsWidget")
650
+ self.updateInfo(self._build)
641
651
 
642
652
 
643
653
  class _OutlineWidget(QWidget):
@@ -663,11 +673,9 @@ class _OutlineWidget(QWidget):
663
673
  self.outerBox.setContentsMargins(0, 0, 0, 0)
664
674
  self.setLayout(self.outerBox)
665
675
 
666
- return
667
-
668
- def updateOutline(self, data: dict[str, str]) -> None:
676
+ def updateOutline(self, data: dict[str, str], *, force: bool = False) -> None:
669
677
  """Update the outline."""
670
- if isinstance(data, dict) and data != self._outline:
678
+ if isinstance(data, dict) and (data != self._outline or force):
671
679
  self.listView.clear()
672
680
 
673
681
  tFont = self.font()
@@ -705,7 +713,10 @@ class _OutlineWidget(QWidget):
705
713
  self.listView.setIndentation(SHARED.theme.baseIconHeight if indent else 4)
706
714
  self._outline = data
707
715
 
708
- return
716
+ def updateTheme(self) -> None:
717
+ """Update theme elements."""
718
+ logger.debug("Theme Update: _OutlineWidget")
719
+ self.updateOutline(self._outline, force=True)
709
720
 
710
721
  ##
711
722
  # Private Slots
@@ -714,7 +725,6 @@ class _OutlineWidget(QWidget):
714
725
  def _onItemClick(self, item: QTreeWidgetItem) -> None:
715
726
  """Process tree item click."""
716
727
  self.outlineEntryClicked.emit(str(item.data(0, self.D_LINE)))
717
- return
718
728
 
719
729
 
720
730
  class _PreviewWidget(QTextBrowser):
@@ -750,17 +760,12 @@ class _PreviewWidget(QTextBrowser):
750
760
  self.anchorClicked.connect(self._linkClicked)
751
761
 
752
762
  # Document Age
753
- aPalette = self.palette()
754
- aPalette.setColor(QPalette.ColorRole.Window, aPalette.toolTipBase().color())
755
- aPalette.setColor(QPalette.ColorRole.WindowText, aPalette.toolTipText().color())
756
-
757
763
  aFont = self.font()
758
764
  aFont.setPointSizeF(0.9*SHARED.theme.fontPointSize)
759
765
 
760
766
  self.ageLabel = QLabel("", self)
761
767
  self.ageLabel.setIndent(0)
762
768
  self.ageLabel.setFont(aFont)
763
- self.ageLabel.setPalette(aPalette)
764
769
  self.ageLabel.setAutoFillBackground(True)
765
770
  self.ageLabel.setAlignment(QtAlignCenter)
766
771
  self.ageLabel.setFixedHeight(int(2.1*SHARED.theme.fontPixelSize))
@@ -779,6 +784,7 @@ class _PreviewWidget(QTextBrowser):
779
784
  self._updateDocMargins()
780
785
  self._updateBuildAge()
781
786
 
787
+ self.updateTheme()
782
788
  self.setTextFont(CONFIG.textFont)
783
789
 
784
790
  # Age Timer
@@ -787,8 +793,6 @@ class _PreviewWidget(QTextBrowser):
787
793
  self.ageTimer.timeout.connect(self._updateBuildAge)
788
794
  self.ageTimer.start()
789
795
 
790
- return
791
-
792
796
  ##
793
797
  # Setters
794
798
  ##
@@ -797,7 +801,6 @@ class _PreviewWidget(QTextBrowser):
797
801
  """Set the build name for the document label."""
798
802
  self._buildName = name
799
803
  self._updateBuildAge()
800
- return
801
804
 
802
805
  def setTextFont(self, font: QFont) -> None:
803
806
  """Set the text font properties and then reset for sub-widgets.
@@ -807,7 +810,6 @@ class _PreviewWidget(QTextBrowser):
807
810
  self.setFont(font)
808
811
  self.buildProgress.setFont(SHARED.theme.guiFont)
809
812
  self.ageLabel.setFont(SHARED.theme.guiFontSmall)
810
- return
811
813
 
812
814
  ##
813
815
  # Methods
@@ -823,13 +825,11 @@ class _PreviewWidget(QTextBrowser):
823
825
  self._scrollPos = vBar.value()
824
826
  self.setPlaceholderText("")
825
827
  self.clear()
826
- return
827
828
 
828
829
  def buildStep(self, value: int) -> None:
829
830
  """Update the progress bar value."""
830
831
  self.buildProgress.setValue(value)
831
832
  QApplication.processEvents()
832
- return
833
833
 
834
834
  def setContent(self, document: QTextDocument) -> None:
835
835
  """Set the content of the preview widget."""
@@ -850,7 +850,14 @@ class _PreviewWidget(QTextBrowser):
850
850
  QApplication.processEvents()
851
851
  QTimer.singleShot(300, self._postUpdate)
852
852
 
853
- return
853
+ def updateTheme(self) -> None:
854
+ """Update theme elements."""
855
+ logger.debug("Theme Update: _PreviewWidget")
856
+
857
+ palette = QApplication.palette()
858
+ palette.setColor(QPalette.ColorRole.Window, palette.toolTipBase().color())
859
+ palette.setColor(QPalette.ColorRole.WindowText, palette.toolTipText().color())
860
+ self.ageLabel.setPalette(palette)
854
861
 
855
862
  ##
856
863
  # Events
@@ -860,7 +867,6 @@ class _PreviewWidget(QTextBrowser):
860
867
  """Capture resize and update the document margins."""
861
868
  super().resizeEvent(event)
862
869
  self._updateDocMargins()
863
- return
864
870
 
865
871
  ##
866
872
  # Public Slots
@@ -874,14 +880,12 @@ class _PreviewWidget(QTextBrowser):
874
880
  printer.setPageOrientation(QPageLayout.Orientation.Portrait)
875
881
  document.print(printer)
876
882
  QApplication.restoreOverrideCursor()
877
- return
878
883
 
879
884
  @pyqtSlot(str)
880
885
  def navigateTo(self, anchor: str) -> None:
881
886
  """Go to a specific #link in the document."""
882
887
  logger.debug("Moving to anchor '#%s'", anchor)
883
888
  self.setSource(QUrl(f"#{anchor}"))
884
- return
885
889
 
886
890
  ##
887
891
  # Private Slots
@@ -896,7 +900,6 @@ class _PreviewWidget(QTextBrowser):
896
900
  self.navigateTo(link.lstrip("#"))
897
901
  elif link.startswith("http"):
898
902
  QDesktopServices.openUrl(QUrl(url))
899
- return
900
903
 
901
904
  @pyqtSlot()
902
905
  def _updateBuildAge(self) -> None:
@@ -909,7 +912,6 @@ class _PreviewWidget(QTextBrowser):
909
912
  ))
910
913
  else:
911
914
  self.ageLabel.setText("<b>{0}</b>".format(self.tr("No Preview")))
912
- return
913
915
 
914
916
  @pyqtSlot()
915
917
  def _postUpdate(self) -> None:
@@ -917,7 +919,6 @@ class _PreviewWidget(QTextBrowser):
917
919
  self.buildProgress.setVisible(False)
918
920
  if vBar := self.verticalScrollBar():
919
921
  vBar.setValue(self._scrollPos)
920
- return
921
922
 
922
923
  ##
923
924
  # Internal Functions
@@ -936,7 +937,6 @@ class _PreviewWidget(QTextBrowser):
936
937
  self.ageLabel.setGeometry(tB, tB, vW, tH)
937
938
  self.setViewportMargins(0, tH, 0, 0)
938
939
  self.buildProgress.move((vW-pS)//2, (vH-pS)//2)
939
- return
940
940
 
941
941
 
942
942
  class _StatsWidget(QWidget):
@@ -951,7 +951,7 @@ class _StatsWidget(QWidget):
951
951
  self.minWidget = QWidget(self)
952
952
  self.maxWidget = QWidget(self)
953
953
 
954
- self.toggleButton = NIconToggleButton(self, SHARED.theme.baseIconSize, "unfold")
954
+ self.toggleButton = NIconToggleButton(self, SHARED.theme.baseIconSize)
955
955
  self.toggleButton.toggled.connect(self._toggleView)
956
956
 
957
957
  self._buildBottomPanel()
@@ -966,11 +966,10 @@ class _StatsWidget(QWidget):
966
966
  self.outerBox.setContentsMargins(0, 0, 0, 0)
967
967
 
968
968
  self.setLayout(self.outerBox)
969
+ self.updateTheme()
969
970
 
970
971
  self._toggleView(False)
971
972
 
972
- return
973
-
974
973
  def updateStats(self, data: dict[str, int]) -> None:
975
974
  """Update the stats values from a Tokenizer stats dict."""
976
975
  # Minimal
@@ -992,7 +991,10 @@ class _StatsWidget(QWidget):
992
991
  self.maxHeadWordChars.setText(f"{data.get(nwStats.WCHARS_TITLE, 0):n}")
993
992
  self.maxTextWordChars.setText(f"{data.get(nwStats.WCHARS_TEXT, 0):n}")
994
993
 
995
- return
994
+ def updateTheme(self) -> None:
995
+ """Update theme elements."""
996
+ logger.debug("Theme Update: _StatsWidget")
997
+ self.toggleButton.setThemeIcon("unfold", "default")
996
998
 
997
999
  ##
998
1000
  # Private Slots
@@ -1013,7 +1015,6 @@ class _StatsWidget(QWidget):
1013
1015
  self.minWidget.adjustSize()
1014
1016
  self.mainStack.adjustSize()
1015
1017
  self.adjustSize()
1016
- return
1017
1018
 
1018
1019
  ##
1019
1020
  # Internal Functions
@@ -1105,5 +1106,3 @@ class _StatsWidget(QWidget):
1105
1106
 
1106
1107
  self.minWidget.setLayout(self.minLayout)
1107
1108
  self.maxWidget.setLayout(self.maxLayout)
1108
-
1109
- return