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
novelwriter/gui/search.py CHANGED
@@ -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
@@ -50,6 +50,7 @@ logger = logging.getLogger(__name__)
50
50
 
51
51
 
52
52
  class GuiProjectSearch(QWidget):
53
+ """GUI: Project Search Panel."""
53
54
 
54
55
  C_NAME = 0
55
56
  C_RESULT = 0
@@ -106,7 +107,7 @@ class GuiProjectSearch(QWidget):
106
107
 
107
108
  # Search Box
108
109
  self.searchAction = QAction("", self)
109
- self.searchAction.setIcon(SHARED.theme.getIcon("search", "blue"))
110
+ self.searchAction.setIcon(SHARED.theme.getIcon("search", "apply"))
110
111
  self.searchAction.triggered.connect(self._processSearch)
111
112
 
112
113
  self.searchText = QLineEdit(self)
@@ -151,14 +152,14 @@ class GuiProjectSearch(QWidget):
151
152
 
152
153
  logger.debug("Ready: GuiProjectSearch")
153
154
 
154
- return
155
-
156
155
  ##
157
156
  # Methods
158
157
  ##
159
158
 
160
159
  def updateTheme(self) -> None:
161
160
  """Update theme elements."""
161
+ logger.debug("Theme Update: GuiProjectSearch")
162
+
162
163
  palette = QApplication.palette()
163
164
  colBase = palette.base().color().name(QtHexArgb)
164
165
  colFocus = palette.highlight().color().name(QtHexArgb)
@@ -169,12 +170,10 @@ class GuiProjectSearch(QWidget):
169
170
  f"QLineEdit:focus {{border: 1px solid {colFocus};}} "
170
171
  )
171
172
 
172
- self.searchAction.setIcon(SHARED.theme.getIcon("search", "blue"))
173
- self.toggleCase.setIcon(SHARED.theme.getIcon("search_case"))
174
- self.toggleWord.setIcon(SHARED.theme.getIcon("search_word"))
175
- self.toggleRegEx.setIcon(SHARED.theme.getIcon("search_regex"))
176
-
177
- return
173
+ self.searchAction.setIcon(SHARED.theme.getIcon("search", "apply"))
174
+ self.toggleCase.setIcon(SHARED.theme.getIcon("search_case", "tool"))
175
+ self.toggleWord.setIcon(SHARED.theme.getIcon("search_word", "tool"))
176
+ self.toggleRegEx.setIcon(SHARED.theme.getIcon("search_regex", "tool"))
178
177
 
179
178
  def processReturn(self) -> None:
180
179
  """Process a return keypress forwarded from the main GUI."""
@@ -189,7 +188,6 @@ class GuiProjectSearch(QWidget):
189
188
  self.openDocumentSelectRequest.emit(
190
189
  str(data[0]), checkInt(data[1], -1), checkInt(data[2], -1), False
191
190
  )
192
- return
193
191
 
194
192
  def beginSearch(self, text: str = "") -> None:
195
193
  """Focus the search box and select its text, if any."""
@@ -198,20 +196,17 @@ class GuiProjectSearch(QWidget):
198
196
  if text:
199
197
  self.searchText.setText(text.partition("\n")[0])
200
198
  self.searchText.selectAll()
201
- return
202
199
 
203
200
  def closeProjectTasks(self) -> None:
204
201
  """Run close project tasks."""
205
202
  self._map = {}
206
203
  self.searchText.clear()
207
204
  self.searchResult.clear()
208
- return
209
205
 
210
206
  def refreshCurrentSearch(self) -> None:
211
207
  """Refresh the search if there is one."""
212
208
  if self.searchResult.topLevelItemCount() > 0:
213
209
  self._processSearch()
214
- return
215
210
 
216
211
  ##
217
212
  # Events
@@ -238,7 +233,6 @@ class GuiProjectSearch(QWidget):
238
233
  self.searchText.setFocus()
239
234
  else:
240
235
  super().keyPressEvent(event)
241
- return
242
236
 
243
237
  ##
244
238
  # Public Slots
@@ -252,7 +246,6 @@ class GuiProjectSearch(QWidget):
252
246
  results, capped = self._search.searchText(SHARED.mainGui.docEditor.getText())
253
247
  self._displayResultSet(SHARED.project.tree[tHandle], results, capped)
254
248
  logger.debug("Updated search for '%s' in %.3f ms", tHandle, 1000*(time() - start))
255
- return
256
249
 
257
250
  ##
258
251
  # Private Slots
@@ -278,7 +271,6 @@ class GuiProjectSearch(QWidget):
278
271
  self._time = time()
279
272
  QApplication.restoreOverrideCursor()
280
273
  self._blocked = False
281
- return
282
274
 
283
275
  @pyqtSlot()
284
276
  def _searchResultSelected(self) -> None:
@@ -288,7 +280,6 @@ class GuiProjectSearch(QWidget):
288
280
  self.selectedItemChanged.emit(str(data[0]))
289
281
  elif data := items[0].data(0, self.D_HANDLE):
290
282
  self.selectedItemChanged.emit(str(data))
291
- return
292
283
 
293
284
  @pyqtSlot("QTreeWidgetItem*", int)
294
285
  def _searchResultDoubleClicked(self, item: QTreeWidgetItem, column: int) -> None:
@@ -297,28 +288,24 @@ class GuiProjectSearch(QWidget):
297
288
  self.openDocumentSelectRequest.emit(
298
289
  str(data[0]), checkInt(data[1], -1), checkInt(data[2], -1), True
299
290
  )
300
- return
301
291
 
302
292
  @pyqtSlot(bool)
303
293
  def _toggleCase(self, state: bool) -> None:
304
294
  """Enable/disable case sensitive mode."""
305
295
  CONFIG.searchProjCase = state
306
296
  self.refreshCurrentSearch()
307
- return
308
297
 
309
298
  @pyqtSlot(bool)
310
299
  def _toggleWord(self, state: bool) -> None:
311
300
  """Enable/disable whole word search mode."""
312
301
  CONFIG.searchProjWord = state
313
302
  self.refreshCurrentSearch()
314
- return
315
303
 
316
304
  @pyqtSlot(bool)
317
305
  def _toggleRegEx(self, state: bool) -> None:
318
306
  """Enable/disable regular expression search mode."""
319
307
  CONFIG.searchProjRegEx = state
320
308
  self.refreshCurrentSearch()
321
- return
322
309
 
323
310
  ##
324
311
  # Internal Functions
@@ -360,5 +347,3 @@ class GuiProjectSearch(QWidget):
360
347
  self.searchResult.setFirstColumnSpanned(i, parent, True)
361
348
 
362
349
  QApplication.processEvents()
363
-
364
- return
@@ -20,19 +20,20 @@ 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
27
27
 
28
28
  from typing import TYPE_CHECKING
29
29
 
30
- from PyQt6.QtCore import QEvent, QPoint, QSize, pyqtSignal
30
+ from PyQt6.QtCore import QEvent, QPoint, pyqtSignal, pyqtSlot
31
31
  from PyQt6.QtWidgets import QMenu, QVBoxLayout, QWidget
32
32
 
33
- from novelwriter import SHARED
33
+ from novelwriter import CONFIG, SHARED
34
34
  from novelwriter.common import qtLambda
35
- from novelwriter.enum import nwView
35
+ from novelwriter.constants import nwLabels, trConst
36
+ from novelwriter.enum import nwTheme, nwView
36
37
  from novelwriter.extensions.eventfilters import StatusTipFilter
37
38
  from novelwriter.extensions.modified import NIconToolButton
38
39
  from novelwriter.gui.theme import STYLES_BIG_TOOLBUTTON
@@ -44,6 +45,7 @@ logger = logging.getLogger(__name__)
44
45
 
45
46
 
46
47
  class GuiSideBar(QWidget):
48
+ """GUI: Main Window SideBar."""
47
49
 
48
50
  requestViewChange = pyqtSignal(nwView)
49
51
 
@@ -54,8 +56,7 @@ class GuiSideBar(QWidget):
54
56
 
55
57
  self.mainGui = mainGui
56
58
 
57
- iPx = int(1.25*SHARED.theme.baseButtonHeight)
58
- iSz = QSize(iPx, iPx)
59
+ iSz = SHARED.theme.sidebarIconSize
59
60
 
60
61
  self.setContentsMargins(0, 0, 0, 0)
61
62
  self.installEventFilter(StatusTipFilter(self.mainGui))
@@ -77,9 +78,9 @@ class GuiSideBar(QWidget):
77
78
  self.tbOutline.setToolTip("{0} [Ctrl+Shift+T]".format(self.tr("Novel Outline View")))
78
79
  self.tbOutline.clicked.connect(qtLambda(self.requestViewChange.emit, nwView.OUTLINE))
79
80
 
80
- self.tbBuild = NIconToolButton(self, iSz)
81
- self.tbBuild.setToolTip("{0} [F5]".format(self.tr("Build Manuscript")))
82
- self.tbBuild.clicked.connect(self.mainGui.showBuildManuscriptDialog)
81
+ self.tbTheme = NIconToolButton(self, iSz)
82
+ self.tbTheme.setToolTip(self.tr("Switch Colour Theme"))
83
+ self.tbTheme.clicked.connect(self._cycleColurTheme)
83
84
 
84
85
  self.tbDetails = NIconToolButton(self, iSz)
85
86
  self.tbDetails.setToolTip("{0} [Shift+F6]".format(self.tr("Novel Details")))
@@ -89,6 +90,10 @@ class GuiSideBar(QWidget):
89
90
  self.tbStats.setToolTip("{0} [F6]".format(self.tr("Writing Statistics")))
90
91
  self.tbStats.clicked.connect(self.mainGui.showWritingStatsDialog)
91
92
 
93
+ self.tbBuild = NIconToolButton(self, iSz)
94
+ self.tbBuild.setToolTip("{0} [F5]".format(self.tr("Build Manuscript")))
95
+ self.tbBuild.clicked.connect(self.mainGui.showBuildManuscriptDialog)
96
+
92
97
  # Settings Menu
93
98
  self.tbSettings = NIconToolButton(self, iSz)
94
99
  self.tbSettings.setToolTip(self.tr("Settings"))
@@ -111,6 +116,7 @@ class GuiSideBar(QWidget):
111
116
  self.outerBox.addStretch(1)
112
117
  self.outerBox.addWidget(self.tbDetails)
113
118
  self.outerBox.addWidget(self.tbStats)
119
+ self.outerBox.addWidget(self.tbTheme)
114
120
  self.outerBox.addWidget(self.tbSettings)
115
121
  self.outerBox.setContentsMargins(0, 0, 0, 0)
116
122
  self.outerBox.setSpacing(6)
@@ -120,12 +126,11 @@ class GuiSideBar(QWidget):
120
126
 
121
127
  logger.debug("Ready: GuiSideBar")
122
128
 
123
- return
124
-
125
129
  def updateTheme(self) -> None:
126
130
  """Initialise GUI elements that depend on specific settings."""
127
- buttonStyle = SHARED.theme.getStyleSheet(STYLES_BIG_TOOLBUTTON)
131
+ logger.debug("Theme Update: GuiSideBar")
128
132
 
133
+ buttonStyle = SHARED.theme.getStyleSheet(STYLES_BIG_TOOLBUTTON)
129
134
  self.tbProject.setStyleSheet(buttonStyle)
130
135
  self.tbNovel.setStyleSheet(buttonStyle)
131
136
  self.tbSearch.setStyleSheet(buttonStyle)
@@ -133,18 +138,45 @@ class GuiSideBar(QWidget):
133
138
  self.tbBuild.setStyleSheet(buttonStyle)
134
139
  self.tbDetails.setStyleSheet(buttonStyle)
135
140
  self.tbStats.setStyleSheet(buttonStyle)
141
+ self.tbTheme.setStyleSheet(buttonStyle)
136
142
  self.tbSettings.setStyleSheet(buttonStyle)
137
143
 
138
- self.tbProject.setThemeIcon("sb_project")
139
- self.tbNovel.setThemeIcon("sb_novel")
140
- self.tbSearch.setThemeIcon("sb_search")
141
- self.tbOutline.setThemeIcon("sb_outline")
142
- self.tbBuild.setThemeIcon("sb_build")
143
- self.tbDetails.setThemeIcon("sb_details")
144
- self.tbStats.setThemeIcon("sb_stats")
145
- self.tbSettings.setThemeIcon("settings")
146
-
147
- return
144
+ self.tbProject.setThemeIcon("sb_project", "sidebar")
145
+ self.tbNovel.setThemeIcon("sb_novel", "sidebar")
146
+ self.tbSearch.setThemeIcon("sb_search", "sidebar")
147
+ self.tbOutline.setThemeIcon("sb_outline", "sidebar")
148
+ self.tbBuild.setThemeIcon("sb_build", "sidebar")
149
+ self.tbDetails.setThemeIcon("sb_details", "sidebar")
150
+ self.tbStats.setThemeIcon("sb_stats", "sidebar")
151
+ self.tbSettings.setThemeIcon("settings", "sidebar")
152
+
153
+ self._setThemeModeIcon()
154
+
155
+ ##
156
+ # Private Slots
157
+ ##
158
+
159
+ @pyqtSlot()
160
+ def _cycleColurTheme(self) -> None:
161
+ """Go to nex colour theme."""
162
+ match CONFIG.themeMode:
163
+ case nwTheme.AUTO:
164
+ CONFIG.themeMode = nwTheme.LIGHT
165
+ case nwTheme.LIGHT:
166
+ CONFIG.themeMode = nwTheme.DARK
167
+ case nwTheme.DARK:
168
+ CONFIG.themeMode = nwTheme.AUTO
169
+ self.mainGui.checkThemeUpdate()
170
+ self._setThemeModeIcon()
171
+
172
+ ##
173
+ # Internal Functions
174
+ ##
175
+
176
+ def _setThemeModeIcon(self) -> None:
177
+ """Set the theme button icon."""
178
+ self.tbTheme.setThemeIcon(nwLabels.THEME_MODE_ICON[CONFIG.themeMode], "sidebar")
179
+ self.tbTheme.setToolTip(trConst(nwLabels.THEME_MODE_LABEL[CONFIG.themeMode]))
148
180
 
149
181
 
150
182
  class _PopRightMenu(QMenu):
@@ -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
@@ -41,6 +41,7 @@ logger = logging.getLogger(__name__)
41
41
 
42
42
 
43
43
  class GuiMainStatus(QStatusBar):
44
+ """GUI: Main Window Status Bar."""
44
45
 
45
46
  def __init__(self, parent: QWidget) -> None:
46
47
  super().__init__(parent=parent)
@@ -112,8 +113,6 @@ class GuiMainStatus(QStatusBar):
112
113
  self.updateTheme()
113
114
  self.clearStatus()
114
115
 
115
- return
116
-
117
116
  def initSettings(self) -> None:
118
117
  """Apply user settings."""
119
118
  if CONFIG.useCharCount:
@@ -122,7 +121,6 @@ class GuiMainStatus(QStatusBar):
122
121
  else:
123
122
  self._trStatsCount = trStats(nwLabels.STATS_DISPLAY[nwStats.WORDS])
124
123
  self._trStatsTip = self.tr("Total word count (session change)")
125
- return
126
124
 
127
125
  def clearStatus(self) -> None:
128
126
  """Reset all widgets on the status bar to default values."""
@@ -132,10 +130,11 @@ class GuiMainStatus(QStatusBar):
132
130
  self.setProjectStatus(None)
133
131
  self.setDocumentStatus(None)
134
132
  self.updateTime()
135
- return
136
133
 
137
134
  def updateTheme(self) -> None:
138
135
  """Update theme elements."""
136
+ logger.debug("Theme Update: GuiMainStatus")
137
+
139
138
  iPx = SHARED.theme.baseIconHeight
140
139
  self.langIcon.setPixmap(SHARED.theme.getPixmap("language", (iPx, iPx)))
141
140
  self.statsIcon.setPixmap(SHARED.theme.getPixmap("stats", (iPx, iPx)))
@@ -143,14 +142,12 @@ class GuiMainStatus(QStatusBar):
143
142
  self.idlePixmap = SHARED.theme.getPixmap("timer_off", (iPx, iPx))
144
143
  self.timeIcon.setPixmap(self.timePixmap)
145
144
 
146
- colNone = SHARED.theme.getIconColor("default").darker(150)
147
- colSaved = SHARED.theme.getIconColor("green").darker(150)
148
- colUnsaved = SHARED.theme.getIconColor("red").darker(150)
145
+ colNone = SHARED.theme.getBaseColor("default")
146
+ colSaved = SHARED.theme.getBaseColor("green")
147
+ colUnsaved = SHARED.theme.getBaseColor("red")
149
148
  self.docIcon.setColors(colNone, colSaved, colUnsaved)
150
149
  self.projIcon.setColors(colNone, colSaved, colUnsaved)
151
150
 
152
- return
153
-
154
151
  ##
155
152
  # Setters
156
153
  ##
@@ -158,17 +155,14 @@ class GuiMainStatus(QStatusBar):
158
155
  def setRefTime(self, refTime: float) -> None:
159
156
  """Set the reference time for the status bar clock."""
160
157
  self._refTime = refTime
161
- return
162
158
 
163
159
  def setProjectStatus(self, state: bool | None) -> None:
164
160
  """Set the project status colour icon."""
165
161
  self.projIcon.setState(state)
166
- return
167
162
 
168
163
  def setDocumentStatus(self, state: bool | None) -> None:
169
164
  """Set the document status colour icon."""
170
165
  self.docIcon.setState(state)
171
- return
172
166
 
173
167
  def setUserIdle(self, idle: bool) -> None:
174
168
  """Change the idle status icon."""
@@ -180,13 +174,11 @@ class GuiMainStatus(QStatusBar):
180
174
  else:
181
175
  self.timeIcon.setPixmap(self.timePixmap)
182
176
  self._userIdle = idle
183
- return
184
177
 
185
178
  def setProjectStats(self, pWC: int, sWC: int) -> None:
186
179
  """Update the current project statistics."""
187
180
  self.statsText.setText(self._trStatsCount.format(f"{pWC:n}", f"{sWC:+n}"))
188
181
  self.statsText.setToolTip(self._trStatsTip)
189
- return
190
182
 
191
183
  def updateTime(self, idleTime: float = 0.0) -> None:
192
184
  """Update the session clock."""
@@ -198,7 +190,6 @@ class GuiMainStatus(QStatusBar):
198
190
  else:
199
191
  sessTime = round(time() - self._refTime)
200
192
  self.timeText.setText(formatTime(sessTime))
201
- return
202
193
 
203
194
  ##
204
195
  # Public Slots
@@ -209,7 +200,6 @@ class GuiMainStatus(QStatusBar):
209
200
  """Set the status bar message to display."""
210
201
  self.showMessage(message, nwConst.STATUS_MSG_TIMEOUT)
211
202
  QApplication.processEvents()
212
- return
213
203
 
214
204
  @pyqtSlot(str, str)
215
205
  def setLanguage(self, language: str, provider: str) -> None:
@@ -220,19 +210,16 @@ class GuiMainStatus(QStatusBar):
220
210
  else:
221
211
  self.langText.setText(QLocale(language).nativeLanguageName().title())
222
212
  self.langText.setToolTip(f"{language} ({provider})" if provider else language)
223
- return
224
213
 
225
214
  @pyqtSlot(bool)
226
215
  def updateProjectStatus(self, status: bool) -> None:
227
216
  """Update the project status."""
228
217
  self.setProjectStatus(not status)
229
- return
230
218
 
231
219
  @pyqtSlot(bool)
232
220
  def updateDocumentStatus(self, status: bool) -> None:
233
221
  """Update the document status."""
234
222
  self.setDocumentStatus(not status)
235
- return
236
223
 
237
224
  ##
238
225
  # Private Slots
@@ -244,7 +231,6 @@ class GuiMainStatus(QStatusBar):
244
231
  state = not CONFIG.showSessionTime
245
232
  self.timeText.setVisible(state)
246
233
  CONFIG.showSessionTime = state
247
- return
248
234
 
249
235
  ##
250
236
  # Debug
@@ -279,4 +265,3 @@ class GuiMainStatus(QStatusBar):
279
265
  )
280
266
  self.showMessage(f"Debug [{stamp}] {message}", 6000)
281
267
  logger.debug("[MEMINFO] %s", message)
282
- return