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
@@ -21,7 +21,7 @@ General Public License for more details.
21
21
 
22
22
  You should have received a copy of the GNU General Public License
23
23
  along with this program. If not, see <https://www.gnu.org/licenses/>.
24
- """
24
+ """ # noqa
25
25
  from __future__ import annotations
26
26
 
27
27
  import json
@@ -211,7 +211,7 @@ class FilterMode(Enum):
211
211
 
212
212
 
213
213
  class BuildSettings:
214
- """Core: Build Settings Class
214
+ """Core: Build Settings Class.
215
215
 
216
216
  This class manages the build settings for a Manuscript build job.
217
217
  The settings can be packed/unpacked to/from a dictionary for JSON.
@@ -229,7 +229,6 @@ class BuildSettings:
229
229
  self._included = set()
230
230
  self._settings = {k: v[1] for k, v in SETTINGS_TEMPLATE.items()}
231
231
  self._changed = False
232
- return
233
232
 
234
233
  @classmethod
235
234
  def fromDict(cls, data: dict) -> BuildSettings:
@@ -315,7 +314,6 @@ class BuildSettings:
315
314
  def setName(self, name: str) -> None:
316
315
  """Set the build setting display name."""
317
316
  self._name = str(name)
318
- return
319
317
 
320
318
  def setBuildID(self, value: str | uuid.UUID) -> None:
321
319
  """Set a UUID build ID."""
@@ -324,13 +322,11 @@ class BuildSettings:
324
322
  self._uuid = str(uuid.uuid4())
325
323
  elif value != self._uuid:
326
324
  self._uuid = value
327
- return
328
325
 
329
326
  def setOrder(self, value: int) -> None:
330
327
  """Set the build order."""
331
328
  if isinstance(value, int):
332
329
  self._order = value
333
- return
334
330
 
335
331
  def setLastBuildPath(self, path: Path | str | None) -> None:
336
332
  """Set the last used build path."""
@@ -341,41 +337,35 @@ class BuildSettings:
341
337
  else:
342
338
  self._path = CONFIG.homePath()
343
339
  self._changed = True
344
- return
345
340
 
346
341
  def setLastBuildName(self, name: str) -> None:
347
342
  """Set the last used build name."""
348
343
  self._build = str(name).strip()
349
344
  self._changed = True
350
- return
351
345
 
352
346
  def setLastFormat(self, value: nwBuildFmt) -> None:
353
347
  """Set the last used build format."""
354
348
  if isinstance(value, nwBuildFmt):
355
349
  self._format = value
356
350
  self._changed = True
357
- return
358
351
 
359
352
  def setFiltered(self, tHandle: str) -> None:
360
353
  """Set an item as filtered."""
361
354
  self._excluded.discard(tHandle)
362
355
  self._included.discard(tHandle)
363
356
  self._changed = True
364
- return
365
357
 
366
358
  def setIncluded(self, tHandle: str) -> None:
367
359
  """Set an item as explicitly included."""
368
360
  self._excluded.discard(tHandle)
369
361
  self._included.add(tHandle)
370
362
  self._changed = True
371
- return
372
363
 
373
364
  def setExcluded(self, tHandle: str) -> None:
374
365
  """Set an item as explicitly excluded."""
375
366
  self._excluded.add(tHandle)
376
367
  self._included.discard(tHandle)
377
368
  self._changed = True
378
- return
379
369
 
380
370
  def setAllowRoot(self, tHandle: str, state: bool) -> None:
381
371
  """Set a specific root folder as allowed or not."""
@@ -385,14 +375,12 @@ class BuildSettings:
385
375
  elif state is False:
386
376
  self._skipRoot.add(tHandle)
387
377
  self._changed = True
388
- return
389
378
 
390
379
  def setValue(self, key: str, value: T_BuildValue) -> None:
391
380
  """Set a specific value for a build setting."""
392
381
  if (d := SETTINGS_TEMPLATE.get(key)) and len(d) == 2 and isinstance(value, d[0]):
393
382
  self._changed |= (value != self._settings[key])
394
383
  self._settings[key] = value
395
- return
396
384
 
397
385
  ##
398
386
  # Methods
@@ -463,7 +451,6 @@ class BuildSettings:
463
451
  called when the changes have been safely saved or passed on.
464
452
  """
465
453
  self._changed = False
466
- return
467
454
 
468
455
  def pack(self) -> dict:
469
456
  """Pack all content into a JSON compatible dictionary."""
@@ -516,8 +503,6 @@ class BuildSettings:
516
503
 
517
504
  self._changed = False
518
505
 
519
- return
520
-
521
506
  @classmethod
522
507
  def duplicate(cls, source: BuildSettings) -> BuildSettings:
523
508
  """Make a copy of another build."""
@@ -529,7 +514,7 @@ class BuildSettings:
529
514
 
530
515
 
531
516
  class BuildCollection:
532
- """Core: Build Collection Class
517
+ """Core: Build Collection Class.
533
518
 
534
519
  This object holds all the build setting objects defined by the given
535
520
  project. The build settings are saved as a single JSON file in the
@@ -542,7 +527,6 @@ class BuildCollection:
542
527
  self._defaultBuild = ""
543
528
  self._builds: dict[str, BuildSettings] = {}
544
529
  self._loadCollection()
545
- return
546
530
 
547
531
  def __len__(self) -> int:
548
532
  """Return the number of builds."""
@@ -581,21 +565,18 @@ class BuildCollection:
581
565
  build.setOrder(i)
582
566
  self._lastBuild = lastBuild
583
567
  self._saveCollection()
584
- return
585
568
 
586
569
  def setDefaultBuild(self, buildID: str) -> None:
587
570
  """Set the default build id."""
588
571
  if buildID != self._defaultBuild:
589
572
  self._defaultBuild = buildID
590
573
  self._saveCollection()
591
- return
592
574
 
593
575
  def setBuild(self, build: BuildSettings) -> None:
594
576
  """Set build settings data in the collection."""
595
577
  if isinstance(build, BuildSettings):
596
578
  self._builds[build.buildID] = build
597
579
  self._saveCollection()
598
- return
599
580
 
600
581
  ##
601
582
  # Methods
@@ -605,7 +586,6 @@ class BuildCollection:
605
586
  """Remove a build from the collection."""
606
587
  self._builds.pop(buildID, None)
607
588
  self._saveCollection()
608
- return
609
589
 
610
590
  def builds(self) -> Iterable[tuple[str, str]]:
611
591
  """Iterate over all available builds."""
@@ -23,7 +23,7 @@ General Public License for more details.
23
23
 
24
24
  You should have received a copy of the GNU General Public License
25
25
  along with this program. If not, see <https://www.gnu.org/licenses/>.
26
- """
26
+ """ # noqa
27
27
  from __future__ import annotations
28
28
 
29
29
  import logging
@@ -52,7 +52,9 @@ logger = logging.getLogger(__name__)
52
52
 
53
53
 
54
54
  class DocMerger:
55
- """Document tool for merging a set of documents into a single new
55
+ """Tool: Merge Documents.
56
+
57
+ Document tool for merging a set of documents into a single new
56
58
  document. The parameters are defined by the user using the
57
59
  GuiDocMerge dialog.
58
60
  """
@@ -62,7 +64,6 @@ class DocMerger:
62
64
  self._error = ""
63
65
  self._target = None
64
66
  self._text = []
65
- return
66
67
 
67
68
  @property
68
69
  def targetHandle(self) -> str | None:
@@ -85,7 +86,6 @@ class DocMerger:
85
86
  """
86
87
  self._target = self._project.tree[tHandle]
87
88
  self._text = []
88
- return
89
89
 
90
90
  def newTargetDoc(self, sHandle: str, label: str) -> None:
91
91
  """Create a brand new target document based on a source handle
@@ -101,7 +101,6 @@ class DocMerger:
101
101
  nwItem.notifyToRefresh()
102
102
  self._target = nwItem
103
103
  self._text = []
104
- return
105
104
 
106
105
  def appendText(self, sHandle: str, addComment: bool, cmtPrefix: str) -> None:
107
106
  """Append text from an existing document to the text buffer."""
@@ -112,7 +111,6 @@ class DocMerger:
112
111
  status, _ = item.getImportStatus()
113
112
  text = f"% {cmtPrefix} {info}: {item.itemName} [{status}]\n\n{text}"
114
113
  self._text.append(text)
115
- return
116
114
 
117
115
  def writeTargetDoc(self) -> bool:
118
116
  """Write the accumulated text into the designated target
@@ -158,7 +156,8 @@ class DocSplitter:
158
156
  self._srcHandle = sHandle
159
157
  self._srcItem = srcItem
160
158
 
161
- return
159
+ def __len__(self) -> int:
160
+ return len(self._rawData)
162
161
 
163
162
  ##
164
163
  # Methods
@@ -174,7 +173,6 @@ class DocSplitter:
174
173
  """
175
174
  self._parHandle = pHandle
176
175
  self._inFolder = False
177
- return
178
176
 
179
177
  def newParentFolder(self, pHandle: str, folderLabel: str) -> None:
180
178
  """Create a new folder that will be the top level parent item
@@ -188,7 +186,6 @@ class DocSplitter:
188
186
  nwItem.notifyToRefresh()
189
187
  self._parHandle = nHandle
190
188
  self._inFolder = True
191
- return
192
189
 
193
190
  def splitDocument(self, splitData: list, splitText: list[str]) -> None:
194
191
  """Loop through the split data record and perform the split job
@@ -200,12 +197,9 @@ class DocSplitter:
200
197
  chunk = buffer[lineNo:]
201
198
  buffer = buffer[:lineNo]
202
199
  self._rawData.insert(0, (chunk, hLevel, hLabel))
203
- return
204
200
 
205
201
  def writeDocuments(self, docHierarchy: bool) -> Iterable[bool]:
206
- """An iterator that will write each document in the buffer, and
207
- return its new handle, parent handle, and sibling handle.
208
- """
202
+ """Write each document in the buffer and yield if successful."""
209
203
  if self._srcHandle and self._srcItem and self._parHandle:
210
204
  pHandle = self._parHandle
211
205
  hHandle = [self._parHandle, None, None, None, None]
@@ -256,7 +250,6 @@ class DocDuplicator:
256
250
 
257
251
  def __init__(self, project: NWProject) -> None:
258
252
  self._project = project
259
- return
260
253
 
261
254
  ##
262
255
  # Methods
@@ -270,7 +263,9 @@ class DocDuplicator:
270
263
  after = True
271
264
  if items:
272
265
  hMap: dict[str, str | None] = {t: None for t in items}
266
+ SHARED.initMainProgress(len(items))
273
267
  for tHandle in items:
268
+ SHARED.incMainProgress()
274
269
  if oldItem := self._project.tree[tHandle]:
275
270
  pHandle = hMap.get(oldItem.itemParent or "") or oldItem.itemParent
276
271
  if newItem := self._project.tree.duplicate(tHandle, pHandle, after):
@@ -282,17 +277,21 @@ class DocDuplicator:
282
277
  after = False
283
278
  else:
284
279
  break
280
+ SHARED.clearMainProgress()
285
281
  return result
286
282
 
287
283
 
288
284
  class DocSearch:
285
+ """Tool: Search Documents.
286
+
287
+ A global document search class.
288
+ """
289
289
 
290
290
  def __init__(self) -> None:
291
291
  self._regEx = re.compile(r"")
292
- self._opts = re.UNICODE | re.IGNORECASE
292
+ self._opts = re.IGNORECASE
293
293
  self._words = False
294
294
  self._escape = True
295
- return
296
295
 
297
296
  ##
298
297
  # Methods
@@ -300,32 +299,30 @@ class DocSearch:
300
299
 
301
300
  def setCaseSensitive(self, state: bool) -> None:
302
301
  """Set the case sensitive search flag."""
303
- self._opts = re.UNICODE
304
- if not state:
305
- self._opts |= re.IGNORECASE
306
- return
302
+ self._opts = 0 if state else re.IGNORECASE
307
303
 
308
304
  def setWholeWords(self, state: bool) -> None:
309
305
  """Set the whole words search flag."""
310
306
  self._words = state
311
- return
312
307
 
313
308
  def setUserRegEx(self, state: bool) -> None:
314
309
  """Set the escape flag to the opposite state."""
315
310
  self._escape = not state
316
- return
317
311
 
318
312
  def iterSearch(
319
313
  self, project: NWProject, search: str
320
314
  ) -> Iterable[tuple[NWItem, list[tuple[int, int, str]], bool]]:
321
- """Iteratively search through documents in a project."""
315
+ """Iterate through documents in a project and apply search."""
322
316
  self._regEx = re.compile(self._buildPattern(search), self._opts)
323
317
  logger.debug("Searching with pattern '%s'", self._regEx.pattern)
324
318
  storage = project.storage
319
+ SHARED.initMainProgress(len(project.tree))
325
320
  for item in project.tree:
321
+ SHARED.incMainProgress()
326
322
  if item.isFileType():
327
323
  results, capped = self.searchText(storage.getDocumentText(item.itemHandle))
328
324
  yield item, results, capped
325
+ SHARED.clearMainProgress()
329
326
  return
330
327
 
331
328
  def searchText(self, text: str) -> tuple[list[tuple[int, int, str]], bool]:
@@ -368,7 +365,6 @@ class ProjectBuilder:
368
365
  def __init__(self) -> None:
369
366
  self._path = None
370
367
  self.tr = partial(QCoreApplication.translate, "ProjectBuilder")
371
- return
372
368
 
373
369
  @property
374
370
  def projPath(self) -> Path | None:
@@ -609,6 +605,6 @@ class ProjectBuilder:
609
605
  project.data.setSaveCount(0)
610
606
  project.data.setAutoCount(0)
611
607
  project.data.setEditTime(0)
608
+ project.index.rebuild()
612
609
  project.saveProject()
613
610
  project.closeProject()
614
- return
@@ -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
@@ -53,7 +53,7 @@ logger = logging.getLogger(__name__)
53
53
 
54
54
 
55
55
  class NWBuildDocument:
56
- """Core: Manuscript Document Build Class
56
+ """Core: Manuscript Document Build Class.
57
57
 
58
58
  This is the core tool that assembles a project and outputs a
59
59
  manuscript, based on a build definition object (BuildSettings).
@@ -72,7 +72,6 @@ class NWBuildDocument:
72
72
  self._cache = None
73
73
  self._count = False
74
74
  self._outline = False
75
- return
76
75
 
77
76
  ##
78
77
  # Properties
@@ -106,7 +105,6 @@ class NWBuildDocument:
106
105
  def addDocument(self, tHandle: str) -> None:
107
106
  """Add a document to the build queue manually."""
108
107
  self._queue.append(tHandle)
109
- return
110
108
 
111
109
  def queueAll(self) -> None:
112
110
  """Queue all document as defined by the build settings."""
@@ -115,7 +113,6 @@ class NWBuildDocument:
115
113
  for item in self._project.tree:
116
114
  if filtered.get(item.itemHandle, False):
117
115
  self._queue.append(item.itemHandle)
118
- return
119
116
 
120
117
  def iterBuildPreview(self, newPage: bool) -> Iterable[tuple[int, bool]]:
121
118
  """Build a preview QTextDocument."""
@@ -131,7 +128,7 @@ class NWBuildDocument:
131
128
  return
132
129
 
133
130
  def iterBuildDocument(self, path: Path, bFormat: nwBuildFmt) -> Iterable[tuple[int, bool]]:
134
- """Wrapper for builders based on format."""
131
+ """Select a builder based on format."""
135
132
  self._error = None
136
133
  self._cache = None
137
134
 
@@ -341,12 +338,10 @@ class NWBuildDocument:
341
338
  scale*self._build.getFloat("format.rightMargin"),
342
339
  )
343
340
 
344
- filtered = self._build.buildItemFilter(
341
+ return self._build.buildItemFilter(
345
342
  self._project, withRoots=self._build.getBool("text.addNoteHeadings")
346
343
  )
347
344
 
348
- return filtered
349
-
350
345
  def _doBuild(self, bldObj: Tokenizer, tHandle: str, convert: bool = True) -> bool:
351
346
  """Build a single document and add it to the build object."""
352
347
  tItem = self._project.tree[tHandle]
@@ -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 hashlib
@@ -42,7 +42,7 @@ logger = logging.getLogger(__name__)
42
42
 
43
43
 
44
44
  class NWDocument:
45
- """Core: Document Class
45
+ """Core: Document Class.
46
46
 
47
47
  A Class wrapping a single novelWriter document file. It represents
48
48
  a project item of nwItemType FILE. The file is not guaranteed to
@@ -68,8 +68,6 @@ class NWDocument:
68
68
  if self._handle is not None:
69
69
  self._item = self._project.tree[tHandle]
70
70
 
71
- return
72
-
73
71
  def __repr__(self) -> str:
74
72
  return f"<NWDocument handle={self._handle}>"
75
73
 
@@ -357,5 +355,3 @@ class NWDocument:
357
355
 
358
356
  else:
359
357
  logger.debug("Unknown meta data: '%s'", metaLine.strip())
360
-
361
- return