novelWriter 2.6.3__py3-none-any.whl → 2.7b1__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 (321) hide show
  1. novelwriter/__init__.py +84 -74
  2. novelwriter/assets/i18n/project_en_GB.json +1 -0
  3. novelwriter/assets/icons/font_awesome.icons +109 -0
  4. novelwriter/assets/icons/material_filled_bold.icons +109 -0
  5. novelwriter/assets/icons/material_filled_normal.icons +109 -0
  6. novelwriter/assets/icons/material_filled_thin.icons +109 -0
  7. novelwriter/assets/icons/material_rounded_bold.icons +109 -0
  8. novelwriter/assets/icons/material_rounded_normal.icons +109 -0
  9. novelwriter/assets/icons/material_rounded_thin.icons +109 -0
  10. novelwriter/assets/icons/remix_filled.icons +108 -0
  11. novelwriter/assets/icons/remix_outline.icons +108 -0
  12. novelwriter/assets/manual.pdf +0 -0
  13. novelwriter/assets/{manual_fr_FR.pdf → manual_fr.pdf} +0 -0
  14. novelwriter/assets/sample.zip +0 -0
  15. novelwriter/assets/syntax/cyberpunk_night.conf +1 -1
  16. novelwriter/assets/text/credits_en.htm +6 -6
  17. novelwriter/assets/themes/cyberpunk_night.conf +23 -7
  18. novelwriter/assets/themes/default_dark.conf +20 -4
  19. novelwriter/assets/themes/default_light.conf +21 -5
  20. novelwriter/assets/themes/dracula.conf +20 -4
  21. novelwriter/assets/themes/solarized_dark.conf +24 -8
  22. novelwriter/assets/themes/solarized_light.conf +22 -6
  23. novelwriter/common.py +33 -26
  24. novelwriter/config.py +118 -127
  25. novelwriter/constants.py +50 -36
  26. novelwriter/core/buildsettings.py +23 -16
  27. novelwriter/core/coretools.py +11 -7
  28. novelwriter/core/docbuild.py +19 -13
  29. novelwriter/core/document.py +2 -2
  30. novelwriter/core/index.py +142 -432
  31. novelwriter/core/indexdata.py +403 -0
  32. novelwriter/core/item.py +35 -28
  33. novelwriter/core/itemmodel.py +27 -26
  34. novelwriter/core/novelmodel.py +223 -0
  35. novelwriter/core/options.py +1 -1
  36. novelwriter/core/project.py +10 -11
  37. novelwriter/core/projectdata.py +5 -5
  38. novelwriter/core/projectxml.py +1 -1
  39. novelwriter/core/sessions.py +3 -2
  40. novelwriter/core/spellcheck.py +4 -3
  41. novelwriter/core/status.py +12 -15
  42. novelwriter/core/storage.py +1 -1
  43. novelwriter/core/tree.py +46 -8
  44. novelwriter/dialogs/about.py +19 -22
  45. novelwriter/dialogs/docmerge.py +21 -23
  46. novelwriter/dialogs/docsplit.py +20 -23
  47. novelwriter/dialogs/editlabel.py +9 -13
  48. novelwriter/dialogs/preferences.py +111 -48
  49. novelwriter/dialogs/projectsettings.py +48 -54
  50. novelwriter/dialogs/quotes.py +14 -19
  51. novelwriter/dialogs/wordlist.py +25 -30
  52. novelwriter/enum.py +8 -0
  53. novelwriter/error.py +16 -16
  54. novelwriter/extensions/configlayout.py +18 -18
  55. novelwriter/extensions/eventfilters.py +9 -5
  56. novelwriter/extensions/modified.py +34 -15
  57. novelwriter/extensions/novelselector.py +18 -5
  58. novelwriter/extensions/pagedsidebar.py +39 -49
  59. novelwriter/extensions/progressbars.py +10 -8
  60. novelwriter/extensions/statusled.py +6 -13
  61. novelwriter/extensions/switch.py +19 -30
  62. novelwriter/extensions/switchbox.py +7 -3
  63. novelwriter/extensions/versioninfo.py +4 -4
  64. novelwriter/formats/shared.py +1 -1
  65. novelwriter/formats/todocx.py +14 -10
  66. novelwriter/formats/tohtml.py +7 -5
  67. novelwriter/formats/tokenizer.py +36 -33
  68. novelwriter/formats/tomarkdown.py +6 -2
  69. novelwriter/formats/toodt.py +27 -22
  70. novelwriter/formats/toqdoc.py +19 -14
  71. novelwriter/formats/toraw.py +6 -2
  72. novelwriter/gui/doceditor.py +216 -265
  73. novelwriter/gui/dochighlight.py +46 -45
  74. novelwriter/gui/docviewer.py +102 -104
  75. novelwriter/gui/docviewerpanel.py +47 -51
  76. novelwriter/gui/editordocument.py +8 -5
  77. novelwriter/gui/itemdetails.py +11 -14
  78. novelwriter/gui/mainmenu.py +146 -145
  79. novelwriter/gui/noveltree.py +239 -405
  80. novelwriter/gui/outline.py +133 -72
  81. novelwriter/gui/projtree.py +138 -132
  82. novelwriter/gui/search.py +33 -31
  83. novelwriter/gui/sidebar.py +13 -18
  84. novelwriter/gui/statusbar.py +13 -15
  85. novelwriter/gui/theme.py +533 -430
  86. novelwriter/guimain.py +27 -29
  87. novelwriter/shared.py +32 -23
  88. novelwriter/text/comments.py +70 -0
  89. novelwriter/text/patterns.py +4 -4
  90. novelwriter/tools/dictionaries.py +20 -29
  91. novelwriter/tools/lipsum.py +16 -17
  92. novelwriter/tools/manusbuild.py +39 -42
  93. novelwriter/tools/manuscript.py +101 -114
  94. novelwriter/tools/manussettings.py +78 -83
  95. novelwriter/tools/noveldetails.py +51 -64
  96. novelwriter/tools/welcome.py +56 -75
  97. novelwriter/tools/writingstats.py +44 -57
  98. novelwriter/types.py +5 -7
  99. {novelWriter-2.6.3.dist-info → novelwriter-2.7b1.dist-info}/METADATA +6 -6
  100. novelwriter-2.7b1.dist-info/RECORD +159 -0
  101. {novelWriter-2.6.3.dist-info → novelwriter-2.7b1.dist-info}/WHEEL +1 -1
  102. novelWriter-2.6.3.dist-info/RECORD +0 -363
  103. novelwriter/assets/icons/typicons_dark/README.md +0 -29
  104. novelwriter/assets/icons/typicons_dark/icons.conf +0 -134
  105. novelwriter/assets/icons/typicons_dark/mixed_copy.svg +0 -4
  106. novelwriter/assets/icons/typicons_dark/mixed_document-chapter.svg +0 -12
  107. novelwriter/assets/icons/typicons_dark/mixed_document-new.svg +0 -6
  108. novelwriter/assets/icons/typicons_dark/mixed_document-note.svg +0 -12
  109. novelwriter/assets/icons/typicons_dark/mixed_document-scene.svg +0 -12
  110. novelwriter/assets/icons/typicons_dark/mixed_document-section.svg +0 -12
  111. novelwriter/assets/icons/typicons_dark/mixed_document-title.svg +0 -12
  112. novelwriter/assets/icons/typicons_dark/mixed_edit.svg +0 -4
  113. novelwriter/assets/icons/typicons_dark/mixed_import.svg +0 -5
  114. novelwriter/assets/icons/typicons_dark/mixed_input-checked.svg +0 -5
  115. novelwriter/assets/icons/typicons_dark/mixed_input-none.svg +0 -5
  116. novelwriter/assets/icons/typicons_dark/mixed_input-unchecked.svg +0 -5
  117. novelwriter/assets/icons/typicons_dark/mixed_margin-bottom.svg +0 -6
  118. novelwriter/assets/icons/typicons_dark/mixed_margin-left.svg +0 -6
  119. novelwriter/assets/icons/typicons_dark/mixed_margin-right.svg +0 -6
  120. novelwriter/assets/icons/typicons_dark/mixed_margin-top.svg +0 -6
  121. novelwriter/assets/icons/typicons_dark/mixed_search-replace.svg +0 -6
  122. novelwriter/assets/icons/typicons_dark/mixed_size-height.svg +0 -6
  123. novelwriter/assets/icons/typicons_dark/mixed_size-width.svg +0 -6
  124. novelwriter/assets/icons/typicons_dark/nw_deco-h0.svg +0 -4
  125. novelwriter/assets/icons/typicons_dark/nw_deco-h1.svg +0 -4
  126. novelwriter/assets/icons/typicons_dark/nw_deco-h2-narrow.svg +0 -4
  127. novelwriter/assets/icons/typicons_dark/nw_deco-h2.svg +0 -4
  128. novelwriter/assets/icons/typicons_dark/nw_deco-h3-narrow.svg +0 -4
  129. novelwriter/assets/icons/typicons_dark/nw_deco-h3.svg +0 -4
  130. novelwriter/assets/icons/typicons_dark/nw_deco-h4-narrow.svg +0 -4
  131. novelwriter/assets/icons/typicons_dark/nw_deco-h4.svg +0 -4
  132. novelwriter/assets/icons/typicons_dark/nw_deco-note.svg +0 -4
  133. novelwriter/assets/icons/typicons_dark/nw_deco-noveltree-more.svg +0 -4
  134. novelwriter/assets/icons/typicons_dark/nw_font.svg +0 -4
  135. novelwriter/assets/icons/typicons_dark/nw_panel.svg +0 -4
  136. novelwriter/assets/icons/typicons_dark/nw_quote.svg +0 -4
  137. novelwriter/assets/icons/typicons_dark/nw_search-case.svg +0 -4
  138. novelwriter/assets/icons/typicons_dark/nw_search-preserve.svg +0 -4
  139. novelwriter/assets/icons/typicons_dark/nw_search-regex.svg +0 -4
  140. novelwriter/assets/icons/typicons_dark/nw_search-word.svg +0 -4
  141. novelwriter/assets/icons/typicons_dark/nw_tb-bold-md.svg +0 -4
  142. novelwriter/assets/icons/typicons_dark/nw_tb-bold.svg +0 -6
  143. novelwriter/assets/icons/typicons_dark/nw_tb-italic-md.svg +0 -4
  144. novelwriter/assets/icons/typicons_dark/nw_tb-italic.svg +0 -6
  145. novelwriter/assets/icons/typicons_dark/nw_tb-mark.svg +0 -7
  146. novelwriter/assets/icons/typicons_dark/nw_tb-strike-md.svg +0 -4
  147. novelwriter/assets/icons/typicons_dark/nw_tb-strike.svg +0 -6
  148. novelwriter/assets/icons/typicons_dark/nw_tb-subscript.svg +0 -7
  149. novelwriter/assets/icons/typicons_dark/nw_tb-superscript.svg +0 -7
  150. novelwriter/assets/icons/typicons_dark/nw_tb-underline.svg +0 -7
  151. novelwriter/assets/icons/typicons_dark/nw_toolbar.svg +0 -5
  152. novelwriter/assets/icons/typicons_dark/typ_arrow-down-thick-grey.svg +0 -4
  153. novelwriter/assets/icons/typicons_dark/typ_arrow-forward.svg +0 -4
  154. novelwriter/assets/icons/typicons_dark/typ_arrow-maximise.svg +0 -4
  155. novelwriter/assets/icons/typicons_dark/typ_arrow-minimise.svg +0 -4
  156. novelwriter/assets/icons/typicons_dark/typ_arrow-repeat-grey.svg +0 -4
  157. novelwriter/assets/icons/typicons_dark/typ_book-grey.svg +0 -4
  158. novelwriter/assets/icons/typicons_dark/typ_book.svg +0 -6
  159. novelwriter/assets/icons/typicons_dark/typ_bookmark.svg +0 -4
  160. novelwriter/assets/icons/typicons_dark/typ_calendar.svg +0 -4
  161. novelwriter/assets/icons/typicons_dark/typ_cancel-grey.svg +0 -4
  162. novelwriter/assets/icons/typicons_dark/typ_cancel.svg +0 -4
  163. novelwriter/assets/icons/typicons_dark/typ_chart-bar-grey.svg +0 -4
  164. novelwriter/assets/icons/typicons_dark/typ_chevron-down.svg +0 -4
  165. novelwriter/assets/icons/typicons_dark/typ_chevron-left.svg +0 -4
  166. novelwriter/assets/icons/typicons_dark/typ_chevron-right.svg +0 -4
  167. novelwriter/assets/icons/typicons_dark/typ_chevron-up.svg +0 -4
  168. novelwriter/assets/icons/typicons_dark/typ_cog.svg +0 -4
  169. novelwriter/assets/icons/typicons_dark/typ_delete-full.svg +0 -4
  170. novelwriter/assets/icons/typicons_dark/typ_delete.svg +0 -4
  171. novelwriter/assets/icons/typicons_dark/typ_directions-full.svg +0 -4
  172. novelwriter/assets/icons/typicons_dark/typ_document-add.svg +0 -4
  173. novelwriter/assets/icons/typicons_dark/typ_document-text.svg +0 -8
  174. novelwriter/assets/icons/typicons_dark/typ_document.svg +0 -4
  175. novelwriter/assets/icons/typicons_dark/typ_export-grey.svg +0 -4
  176. novelwriter/assets/icons/typicons_dark/typ_export.svg +0 -4
  177. novelwriter/assets/icons/typicons_dark/typ_eye.svg +0 -4
  178. novelwriter/assets/icons/typicons_dark/typ_flag.svg +0 -4
  179. novelwriter/assets/icons/typicons_dark/typ_folder-open.svg +0 -4
  180. novelwriter/assets/icons/typicons_dark/typ_folder.svg +0 -5
  181. novelwriter/assets/icons/typicons_dark/typ_globe-grey.svg +0 -4
  182. novelwriter/assets/icons/typicons_dark/typ_key.svg +0 -4
  183. novelwriter/assets/icons/typicons_dark/typ_lightbulb-full.svg +0 -4
  184. novelwriter/assets/icons/typicons_dark/typ_location.svg +0 -4
  185. novelwriter/assets/icons/typicons_dark/typ_media-pause-grey.svg +0 -4
  186. novelwriter/assets/icons/typicons_dark/typ_media-record-outline.svg +0 -4
  187. novelwriter/assets/icons/typicons_dark/typ_media-record.svg +0 -4
  188. novelwriter/assets/icons/typicons_dark/typ_minus.svg +0 -4
  189. novelwriter/assets/icons/typicons_dark/typ_pencil.svg +0 -5
  190. novelwriter/assets/icons/typicons_dark/typ_pin-outline.svg +0 -4
  191. novelwriter/assets/icons/typicons_dark/typ_pin.svg +0 -4
  192. novelwriter/assets/icons/typicons_dark/typ_plus.svg +0 -4
  193. novelwriter/assets/icons/typicons_dark/typ_puzzle-outline.svg +0 -4
  194. novelwriter/assets/icons/typicons_dark/typ_puzzle.svg +0 -4
  195. novelwriter/assets/icons/typicons_dark/typ_refresh-flipped.svg +0 -4
  196. novelwriter/assets/icons/typicons_dark/typ_refresh.svg +0 -4
  197. novelwriter/assets/icons/typicons_dark/typ_search-grey.svg +0 -4
  198. novelwriter/assets/icons/typicons_dark/typ_search.svg +0 -4
  199. novelwriter/assets/icons/typicons_dark/typ_star.svg +0 -4
  200. novelwriter/assets/icons/typicons_dark/typ_stopwatch-grey.svg +0 -4
  201. novelwriter/assets/icons/typicons_dark/typ_th-dot-menu.svg +0 -4
  202. novelwriter/assets/icons/typicons_dark/typ_th-dot-more.svg +0 -4
  203. novelwriter/assets/icons/typicons_dark/typ_th-list-grey.svg +0 -4
  204. novelwriter/assets/icons/typicons_dark/typ_th-list.svg +0 -9
  205. novelwriter/assets/icons/typicons_dark/typ_times.svg +0 -4
  206. novelwriter/assets/icons/typicons_dark/typ_trash.svg +0 -5
  207. novelwriter/assets/icons/typicons_dark/typ_unfold-hidden.svg +0 -4
  208. novelwriter/assets/icons/typicons_dark/typ_unfold-visible.svg +0 -4
  209. novelwriter/assets/icons/typicons_dark/typ_user.svg +0 -5
  210. novelwriter/assets/icons/typicons_dark/typ_warning-full.svg +0 -4
  211. novelwriter/assets/icons/typicons_light/README.md +0 -29
  212. novelwriter/assets/icons/typicons_light/icons.conf +0 -134
  213. novelwriter/assets/icons/typicons_light/mixed_copy.svg +0 -4
  214. novelwriter/assets/icons/typicons_light/mixed_document-chapter.svg +0 -12
  215. novelwriter/assets/icons/typicons_light/mixed_document-new.svg +0 -6
  216. novelwriter/assets/icons/typicons_light/mixed_document-note.svg +0 -12
  217. novelwriter/assets/icons/typicons_light/mixed_document-scene.svg +0 -12
  218. novelwriter/assets/icons/typicons_light/mixed_document-section.svg +0 -12
  219. novelwriter/assets/icons/typicons_light/mixed_document-title.svg +0 -12
  220. novelwriter/assets/icons/typicons_light/mixed_edit.svg +0 -4
  221. novelwriter/assets/icons/typicons_light/mixed_import.svg +0 -5
  222. novelwriter/assets/icons/typicons_light/mixed_input-checked.svg +0 -5
  223. novelwriter/assets/icons/typicons_light/mixed_input-none.svg +0 -5
  224. novelwriter/assets/icons/typicons_light/mixed_input-unchecked.svg +0 -5
  225. novelwriter/assets/icons/typicons_light/mixed_margin-bottom.svg +0 -6
  226. novelwriter/assets/icons/typicons_light/mixed_margin-left.svg +0 -6
  227. novelwriter/assets/icons/typicons_light/mixed_margin-right.svg +0 -6
  228. novelwriter/assets/icons/typicons_light/mixed_margin-top.svg +0 -6
  229. novelwriter/assets/icons/typicons_light/mixed_search-replace.svg +0 -6
  230. novelwriter/assets/icons/typicons_light/mixed_size-height.svg +0 -6
  231. novelwriter/assets/icons/typicons_light/mixed_size-width.svg +0 -6
  232. novelwriter/assets/icons/typicons_light/nw_deco-h0.svg +0 -4
  233. novelwriter/assets/icons/typicons_light/nw_deco-h1.svg +0 -4
  234. novelwriter/assets/icons/typicons_light/nw_deco-h2-narrow.svg +0 -4
  235. novelwriter/assets/icons/typicons_light/nw_deco-h2.svg +0 -4
  236. novelwriter/assets/icons/typicons_light/nw_deco-h3-narrow.svg +0 -4
  237. novelwriter/assets/icons/typicons_light/nw_deco-h3.svg +0 -4
  238. novelwriter/assets/icons/typicons_light/nw_deco-h4-narrow.svg +0 -4
  239. novelwriter/assets/icons/typicons_light/nw_deco-h4.svg +0 -4
  240. novelwriter/assets/icons/typicons_light/nw_deco-note.svg +0 -4
  241. novelwriter/assets/icons/typicons_light/nw_deco-noveltree-more.svg +0 -4
  242. novelwriter/assets/icons/typicons_light/nw_font.svg +0 -4
  243. novelwriter/assets/icons/typicons_light/nw_panel.svg +0 -4
  244. novelwriter/assets/icons/typicons_light/nw_quote.svg +0 -4
  245. novelwriter/assets/icons/typicons_light/nw_search-case.svg +0 -4
  246. novelwriter/assets/icons/typicons_light/nw_search-preserve.svg +0 -4
  247. novelwriter/assets/icons/typicons_light/nw_search-regex.svg +0 -4
  248. novelwriter/assets/icons/typicons_light/nw_search-word.svg +0 -4
  249. novelwriter/assets/icons/typicons_light/nw_tb-bold-md.svg +0 -4
  250. novelwriter/assets/icons/typicons_light/nw_tb-bold.svg +0 -6
  251. novelwriter/assets/icons/typicons_light/nw_tb-italic-md.svg +0 -4
  252. novelwriter/assets/icons/typicons_light/nw_tb-italic.svg +0 -6
  253. novelwriter/assets/icons/typicons_light/nw_tb-mark.svg +0 -7
  254. novelwriter/assets/icons/typicons_light/nw_tb-strike-md.svg +0 -4
  255. novelwriter/assets/icons/typicons_light/nw_tb-strike.svg +0 -6
  256. novelwriter/assets/icons/typicons_light/nw_tb-subscript.svg +0 -7
  257. novelwriter/assets/icons/typicons_light/nw_tb-superscript.svg +0 -7
  258. novelwriter/assets/icons/typicons_light/nw_tb-underline.svg +0 -7
  259. novelwriter/assets/icons/typicons_light/nw_toolbar.svg +0 -5
  260. novelwriter/assets/icons/typicons_light/typ_arrow-down-thick-grey.svg +0 -4
  261. novelwriter/assets/icons/typicons_light/typ_arrow-forward.svg +0 -4
  262. novelwriter/assets/icons/typicons_light/typ_arrow-maximise.svg +0 -4
  263. novelwriter/assets/icons/typicons_light/typ_arrow-minimise.svg +0 -4
  264. novelwriter/assets/icons/typicons_light/typ_arrow-repeat-grey.svg +0 -4
  265. novelwriter/assets/icons/typicons_light/typ_book-grey.svg +0 -4
  266. novelwriter/assets/icons/typicons_light/typ_book.svg +0 -6
  267. novelwriter/assets/icons/typicons_light/typ_bookmark.svg +0 -4
  268. novelwriter/assets/icons/typicons_light/typ_calendar.svg +0 -4
  269. novelwriter/assets/icons/typicons_light/typ_cancel-grey.svg +0 -4
  270. novelwriter/assets/icons/typicons_light/typ_cancel.svg +0 -4
  271. novelwriter/assets/icons/typicons_light/typ_chart-bar-grey.svg +0 -4
  272. novelwriter/assets/icons/typicons_light/typ_chevron-down.svg +0 -4
  273. novelwriter/assets/icons/typicons_light/typ_chevron-left.svg +0 -4
  274. novelwriter/assets/icons/typicons_light/typ_chevron-right.svg +0 -4
  275. novelwriter/assets/icons/typicons_light/typ_chevron-up.svg +0 -4
  276. novelwriter/assets/icons/typicons_light/typ_cog.svg +0 -4
  277. novelwriter/assets/icons/typicons_light/typ_delete-full.svg +0 -4
  278. novelwriter/assets/icons/typicons_light/typ_delete.svg +0 -4
  279. novelwriter/assets/icons/typicons_light/typ_directions-full.svg +0 -4
  280. novelwriter/assets/icons/typicons_light/typ_document-add.svg +0 -4
  281. novelwriter/assets/icons/typicons_light/typ_document-text.svg +0 -5
  282. novelwriter/assets/icons/typicons_light/typ_document.svg +0 -4
  283. novelwriter/assets/icons/typicons_light/typ_export-grey.svg +0 -4
  284. novelwriter/assets/icons/typicons_light/typ_export.svg +0 -4
  285. novelwriter/assets/icons/typicons_light/typ_eye.svg +0 -4
  286. novelwriter/assets/icons/typicons_light/typ_flag.svg +0 -4
  287. novelwriter/assets/icons/typicons_light/typ_folder-open.svg +0 -4
  288. novelwriter/assets/icons/typicons_light/typ_folder.svg +0 -5
  289. novelwriter/assets/icons/typicons_light/typ_globe-grey.svg +0 -4
  290. novelwriter/assets/icons/typicons_light/typ_key.svg +0 -4
  291. novelwriter/assets/icons/typicons_light/typ_lightbulb-full.svg +0 -4
  292. novelwriter/assets/icons/typicons_light/typ_location.svg +0 -4
  293. novelwriter/assets/icons/typicons_light/typ_media-pause-grey.svg +0 -4
  294. novelwriter/assets/icons/typicons_light/typ_media-record-outline.svg +0 -4
  295. novelwriter/assets/icons/typicons_light/typ_media-record.svg +0 -4
  296. novelwriter/assets/icons/typicons_light/typ_minus.svg +0 -4
  297. novelwriter/assets/icons/typicons_light/typ_pencil.svg +0 -5
  298. novelwriter/assets/icons/typicons_light/typ_pin-outline.svg +0 -4
  299. novelwriter/assets/icons/typicons_light/typ_pin.svg +0 -4
  300. novelwriter/assets/icons/typicons_light/typ_plus.svg +0 -4
  301. novelwriter/assets/icons/typicons_light/typ_puzzle-outline.svg +0 -4
  302. novelwriter/assets/icons/typicons_light/typ_puzzle.svg +0 -4
  303. novelwriter/assets/icons/typicons_light/typ_refresh-flipped.svg +0 -4
  304. novelwriter/assets/icons/typicons_light/typ_refresh.svg +0 -4
  305. novelwriter/assets/icons/typicons_light/typ_search-grey.svg +0 -4
  306. novelwriter/assets/icons/typicons_light/typ_search.svg +0 -4
  307. novelwriter/assets/icons/typicons_light/typ_star.svg +0 -4
  308. novelwriter/assets/icons/typicons_light/typ_stopwatch-grey.svg +0 -4
  309. novelwriter/assets/icons/typicons_light/typ_th-dot-menu.svg +0 -4
  310. novelwriter/assets/icons/typicons_light/typ_th-dot-more.svg +0 -4
  311. novelwriter/assets/icons/typicons_light/typ_th-list-grey.svg +0 -4
  312. novelwriter/assets/icons/typicons_light/typ_th-list.svg +0 -9
  313. novelwriter/assets/icons/typicons_light/typ_times.svg +0 -4
  314. novelwriter/assets/icons/typicons_light/typ_trash.svg +0 -5
  315. novelwriter/assets/icons/typicons_light/typ_unfold-hidden.svg +0 -4
  316. novelwriter/assets/icons/typicons_light/typ_unfold-visible.svg +0 -4
  317. novelwriter/assets/icons/typicons_light/typ_user.svg +0 -5
  318. novelwriter/assets/icons/typicons_light/typ_warning-full.svg +0 -4
  319. {novelWriter-2.6.3.dist-info → novelwriter-2.7b1.dist-info}/entry_points.txt +0 -0
  320. {novelWriter-2.6.3.dist-info → novelwriter-2.7b1.dist-info/licenses}/LICENSE.md +0 -0
  321. {novelWriter-2.6.3.dist-info → novelwriter-2.7b1.dist-info}/top_level.txt +0 -0
novelwriter/constants.py CHANGED
@@ -23,7 +23,9 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
23
23
  """
24
24
  from __future__ import annotations
25
25
 
26
- from PyQt5.QtCore import QT_TRANSLATE_NOOP, QCoreApplication
26
+ from typing import Final
27
+
28
+ from PyQt6.QtCore import QT_TRANSLATE_NOOP, QCoreApplication
27
29
 
28
30
  from novelwriter.enum import (
29
31
  nwBuildFmt, nwComment, nwItemClass, nwItemLayout, nwOutline, nwStatusShape
@@ -99,7 +101,7 @@ class nwShortcode:
99
101
  FOOTNOTE_B = "[footnote:"
100
102
  FIELD_B = "[field:"
101
103
 
102
- COMMENT_STYLES = {
104
+ COMMENT_STYLES: Final[dict[nwComment, str]] = {
103
105
  nwComment.FOOTNOTE: "[footnote:{0}]",
104
106
  nwComment.COMMENT: "[comment:{0}]",
105
107
  }
@@ -110,13 +112,13 @@ class nwShortcode:
110
112
  class nwStyles:
111
113
 
112
114
  H_VALID = ("H0", "H1", "H2", "H3", "H4")
113
- H_LEVEL = {"H0": 0, "H1": 1, "H2": 2, "H3": 3, "H4": 4}
114
- H_SIZES = {0: 2.50, 1: 2.00, 2: 1.75, 3: 1.50, 4: 1.25}
115
+ H_LEVEL: Final[dict[str, int]] = {"H0": 0, "H1": 1, "H2": 2, "H3": 3, "H4": 4}
116
+ H_SIZES: Final[dict[int, float]] = {0: 2.50, 1: 2.00, 2: 1.75, 3: 1.50, 4: 1.25}
115
117
 
116
118
  T_NORMAL = 1.0
117
119
  T_SMALL = 0.8
118
120
 
119
- T_LABEL = {
121
+ T_LABEL: Final[dict[str, str]] = {
120
122
  "H0": QT_TRANSLATE_NOOP("Constant", "Title"),
121
123
  "H1": QT_TRANSLATE_NOOP("Constant", "Heading 1 (Partition)"),
122
124
  "H2": QT_TRANSLATE_NOOP("Constant", "Heading 2 (Chapter)"),
@@ -125,7 +127,7 @@ class nwStyles:
125
127
  "TT": QT_TRANSLATE_NOOP("Constant", "Text Paragraph"),
126
128
  "SP": QT_TRANSLATE_NOOP("Constant", "Scene Separator"),
127
129
  }
128
- T_MARGIN = {
130
+ T_MARGIN: Final[dict[str, tuple[float, float]]] = {
129
131
  "H0": (1.50, 0.60), # Title margins (top, bottom)
130
132
  "H1": (1.50, 0.60), # Heading 1 margins (top, bottom)
131
133
  "H2": (1.50, 0.60), # Heading 2 margins (top, bottom)
@@ -174,20 +176,20 @@ class nwKeyWords:
174
176
  MENTION_KEY = "@mention"
175
177
 
176
178
  # Note: The order here affects the order of menu entries
177
- ALL_KEYS = [
179
+ ALL_KEYS: Final[list[str]] = [
178
180
  TAG_KEY, POV_KEY, FOCUS_KEY, CHAR_KEY, PLOT_KEY, TIME_KEY, WORLD_KEY,
179
181
  OBJECT_KEY, ENTITY_KEY, CUSTOM_KEY, STORY_KEY, MENTION_KEY,
180
182
  ]
181
- CAN_CREATE = [
183
+ CAN_CREATE: Final[list[str]] = [
182
184
  POV_KEY, FOCUS_KEY, CHAR_KEY, PLOT_KEY, TIME_KEY, WORLD_KEY,
183
185
  OBJECT_KEY, ENTITY_KEY, CUSTOM_KEY,
184
186
  ]
185
187
 
186
188
  # Set of Valid Keys
187
- VALID_KEYS = set(ALL_KEYS)
189
+ VALID_KEYS: Final[set[str]] = set(ALL_KEYS)
188
190
 
189
191
  # Map from Keys to Item Class
190
- KEY_CLASS = {
192
+ KEY_CLASS: Final[dict[str, nwItemClass]] = {
191
193
  POV_KEY: nwItemClass.CHARACTER,
192
194
  FOCUS_KEY: nwItemClass.CHARACTER,
193
195
  CHAR_KEY: nwItemClass.CHARACTER,
@@ -203,7 +205,7 @@ class nwKeyWords:
203
205
 
204
206
  class nwLists:
205
207
 
206
- USER_CLASSES = [
208
+ USER_CLASSES: Final[list[nwItemClass]] = [
207
209
  nwItemClass.CHARACTER,
208
210
  nwItemClass.PLOT,
209
211
  nwItemClass.WORLD,
@@ -229,7 +231,7 @@ class nwStats:
229
231
  WORDS_TITLE = "titleWords"
230
232
 
231
233
  # Note: The order here affects the order of menu entries
232
- ALL_FIELDS = [
234
+ ALL_FIELDS: Final[list[str]] = [
233
235
  WORDS, WORDS_TEXT, WORDS_TITLE,
234
236
  CHARS, CHARS_TEXT, CHARS_TITLE,
235
237
  WCHARS_ALL, WCHARS_TEXT, WCHARS_TITLE,
@@ -239,7 +241,7 @@ class nwStats:
239
241
 
240
242
  class nwLabels:
241
243
 
242
- CLASS_NAME = {
244
+ CLASS_NAME: Final[dict[nwItemClass, str]] = {
243
245
  nwItemClass.NO_CLASS: QT_TRANSLATE_NOOP("Constant", "None"),
244
246
  nwItemClass.NOVEL: QT_TRANSLATE_NOOP("Constant", "Novel"),
245
247
  nwItemClass.PLOT: QT_TRANSLATE_NOOP("Constant", "Plot"),
@@ -253,7 +255,7 @@ class nwLabels:
253
255
  nwItemClass.TEMPLATE: QT_TRANSLATE_NOOP("Constant", "Templates"),
254
256
  nwItemClass.TRASH: QT_TRANSLATE_NOOP("Constant", "Trash"),
255
257
  }
256
- CLASS_ICON = {
258
+ CLASS_ICON: Final[dict[nwItemClass, str]] = {
257
259
  nwItemClass.NO_CLASS: "cls_none",
258
260
  nwItemClass.NOVEL: "cls_novel",
259
261
  nwItemClass.PLOT: "cls_plot",
@@ -267,12 +269,12 @@ class nwLabels:
267
269
  nwItemClass.TEMPLATE: "cls_template",
268
270
  nwItemClass.TRASH: "cls_trash",
269
271
  }
270
- LAYOUT_NAME = {
272
+ LAYOUT_NAME: Final[dict[nwItemLayout, str]] = {
271
273
  nwItemLayout.NO_LAYOUT: QT_TRANSLATE_NOOP("Constant", "None"),
272
274
  nwItemLayout.DOCUMENT: QT_TRANSLATE_NOOP("Constant", "Novel Document"),
273
275
  nwItemLayout.NOTE: QT_TRANSLATE_NOOP("Constant", "Project Note"),
274
276
  }
275
- ITEM_DESCRIPTION = {
277
+ ITEM_DESCRIPTION: Final[dict[str, str]] = {
276
278
  "none": QT_TRANSLATE_NOOP("Constant", "None"),
277
279
  "root": QT_TRANSLATE_NOOP("Constant", "Root Folder"),
278
280
  "folder": QT_TRANSLATE_NOOP("Constant", "Folder"),
@@ -283,11 +285,11 @@ class nwLabels:
283
285
  "doc_h4": QT_TRANSLATE_NOOP("Constant", "Novel Section"),
284
286
  "note": QT_TRANSLATE_NOOP("Constant", "Project Note"),
285
287
  }
286
- ACTIVE_NAME = {
288
+ ACTIVE_NAME: Final[dict[str, str]] = {
287
289
  "checked": QT_TRANSLATE_NOOP("Constant", "Active"),
288
290
  "unchecked": QT_TRANSLATE_NOOP("Constant", "Inactive"),
289
291
  }
290
- KEY_NAME = {
292
+ KEY_NAME: Final[dict[str, str]] = {
291
293
  nwKeyWords.TAG_KEY: QT_TRANSLATE_NOOP("Constant", "Tag"),
292
294
  nwKeyWords.POV_KEY: QT_TRANSLATE_NOOP("Constant", "Point of View"),
293
295
  nwKeyWords.FOCUS_KEY: QT_TRANSLATE_NOOP("Constant", "Focus"),
@@ -301,7 +303,7 @@ class nwLabels:
301
303
  nwKeyWords.STORY_KEY: QT_TRANSLATE_NOOP("Constant", "Story"),
302
304
  nwKeyWords.MENTION_KEY: QT_TRANSLATE_NOOP("Constant", "Mentions"),
303
305
  }
304
- KEY_SHORTCUT = {
306
+ KEY_SHORTCUT: Final[dict[str, str]] = {
305
307
  nwKeyWords.TAG_KEY: "Ctrl+K, G",
306
308
  nwKeyWords.POV_KEY: "Ctrl+K, V",
307
309
  nwKeyWords.FOCUS_KEY: "Ctrl+K, F",
@@ -315,7 +317,7 @@ class nwLabels:
315
317
  nwKeyWords.STORY_KEY: "Ctrl+K, N",
316
318
  nwKeyWords.MENTION_KEY: "Ctrl+K, M",
317
319
  }
318
- OUTLINE_COLS = {
320
+ OUTLINE_COLS: Final[dict[nwOutline, str]] = {
319
321
  nwOutline.TITLE: QT_TRANSLATE_NOOP("Constant", "Title"),
320
322
  nwOutline.LEVEL: QT_TRANSLATE_NOOP("Constant", "Level"),
321
323
  nwOutline.LABEL: QT_TRANSLATE_NOOP("Constant", "Document"),
@@ -337,7 +339,7 @@ class nwLabels:
337
339
  nwOutline.MENTION: KEY_NAME[nwKeyWords.MENTION_KEY],
338
340
  nwOutline.SYNOP: QT_TRANSLATE_NOOP("Constant", "Synopsis"),
339
341
  }
340
- STATS_NAME = {
342
+ STATS_NAME: Final[dict[str, str]] = {
341
343
  nwStats.CHARS: QT_TRANSLATE_NOOP("Stats", "Characters"),
342
344
  nwStats.CHARS_TEXT: QT_TRANSLATE_NOOP("Stats", "Characters in Text"),
343
345
  nwStats.CHARS_TITLE: QT_TRANSLATE_NOOP("Stats", "Characters in Headings"),
@@ -350,7 +352,7 @@ class nwLabels:
350
352
  nwStats.WORDS_TEXT: QT_TRANSLATE_NOOP("Stats", "Words in Text"),
351
353
  nwStats.WORDS_TITLE: QT_TRANSLATE_NOOP("Stats", "Words in Headings"),
352
354
  }
353
- BUILD_FMT = {
355
+ BUILD_FMT: Final[dict[nwBuildFmt, str]] = {
354
356
  nwBuildFmt.ODT: QT_TRANSLATE_NOOP("Constant", "Open Document (.odt)"),
355
357
  nwBuildFmt.FODT: QT_TRANSLATE_NOOP("Constant", "Flat Open Document (.fodt)"),
356
358
  nwBuildFmt.DOCX: QT_TRANSLATE_NOOP("Constant", "Microsoft Word Document (.docx)"),
@@ -362,7 +364,7 @@ class nwLabels:
362
364
  nwBuildFmt.J_HTML: QT_TRANSLATE_NOOP("Constant", "JSON + HTML 5 (.json)"),
363
365
  nwBuildFmt.J_NWD: QT_TRANSLATE_NOOP("Constant", "JSON + novelWriter Markup (.json)"),
364
366
  }
365
- BUILD_EXT = {
367
+ BUILD_EXT: Final[dict[nwBuildFmt, str]] = {
366
368
  nwBuildFmt.ODT: ".odt",
367
369
  nwBuildFmt.FODT: ".fodt",
368
370
  nwBuildFmt.DOCX: ".docx",
@@ -374,7 +376,7 @@ class nwLabels:
374
376
  nwBuildFmt.J_HTML: ".json",
375
377
  nwBuildFmt.J_NWD: ".json",
376
378
  }
377
- SHAPES_PLAIN = {
379
+ SHAPES_PLAIN: Final[dict[nwStatusShape, str]] = {
378
380
  nwStatusShape.SQUARE: QT_TRANSLATE_NOOP("Constant", "Square"),
379
381
  nwStatusShape.TRIANGLE: QT_TRANSLATE_NOOP("Constant", "Triangle"),
380
382
  nwStatusShape.NABLA: QT_TRANSLATE_NOOP("Constant", "Nabla"),
@@ -384,42 +386,42 @@ class nwLabels:
384
386
  nwStatusShape.STAR: QT_TRANSLATE_NOOP("Constant", "Star"),
385
387
  nwStatusShape.PACMAN: QT_TRANSLATE_NOOP("Constant", "Pacman"),
386
388
  }
387
- SHAPES_CIRCLE = {
389
+ SHAPES_CIRCLE: Final[dict[nwStatusShape, str]] = {
388
390
  nwStatusShape.CIRCLE_Q: QT_TRANSLATE_NOOP("Constant", "1/4 Circle"),
389
391
  nwStatusShape.CIRCLE_H: QT_TRANSLATE_NOOP("Constant", "Half Circle"),
390
392
  nwStatusShape.CIRCLE_T: QT_TRANSLATE_NOOP("Constant", "3/4 Circle"),
391
393
  nwStatusShape.CIRCLE: QT_TRANSLATE_NOOP("Constant", "Full Circle"),
392
394
  }
393
- SHAPES_BARS = {
395
+ SHAPES_BARS: Final[dict[nwStatusShape, str]] = {
394
396
  nwStatusShape.BARS_1: QT_TRANSLATE_NOOP("Constant", "1 Bar"),
395
397
  nwStatusShape.BARS_2: QT_TRANSLATE_NOOP("Constant", "2 Bars"),
396
398
  nwStatusShape.BARS_3: QT_TRANSLATE_NOOP("Constant", "3 Bars"),
397
399
  nwStatusShape.BARS_4: QT_TRANSLATE_NOOP("Constant", "4 Bars"),
398
400
  }
399
- SHAPES_BLOCKS = {
401
+ SHAPES_BLOCKS: Final[dict[nwStatusShape, str]] = {
400
402
  nwStatusShape.BLOCK_1: QT_TRANSLATE_NOOP("Constant", "1 Block"),
401
403
  nwStatusShape.BLOCK_2: QT_TRANSLATE_NOOP("Constant", "2 Blocks"),
402
404
  nwStatusShape.BLOCK_3: QT_TRANSLATE_NOOP("Constant", "3 Blocks"),
403
405
  nwStatusShape.BLOCK_4: QT_TRANSLATE_NOOP("Constant", "4 Blocks"),
404
406
  }
405
- FILE_FILTERS = {
407
+ FILE_FILTERS: Final[dict[str, str]] = {
406
408
  "*.txt": QT_TRANSLATE_NOOP("Constant", "Text files"),
407
409
  "*.md": QT_TRANSLATE_NOOP("Constant", "Markdown files"),
408
410
  "*.nwd": QT_TRANSLATE_NOOP("Constant", "novelWriter files"),
409
411
  "*.csv": QT_TRANSLATE_NOOP("Constant", "CSV files"),
410
412
  "*": QT_TRANSLATE_NOOP("Constant", "All files"),
411
413
  }
412
- UNIT_NAME = {
414
+ UNIT_NAME: Final[dict[str, str]] = {
413
415
  "mm": QT_TRANSLATE_NOOP("Constant", "Millimetres"),
414
416
  "cm": QT_TRANSLATE_NOOP("Constant", "Centimetres"),
415
417
  "in": QT_TRANSLATE_NOOP("Constant", "Inches"),
416
418
  }
417
- UNIT_SCALE = {
419
+ UNIT_SCALE: Final[dict[str, float]] = {
418
420
  "mm": 1.0,
419
421
  "cm": 10.0,
420
422
  "in": 25.4,
421
423
  }
422
- PAPER_NAME = {
424
+ PAPER_NAME: Final[dict[str, str]] = {
423
425
  "A4": QT_TRANSLATE_NOOP("Constant", "A4"),
424
426
  "A5": QT_TRANSLATE_NOOP("Constant", "A5"),
425
427
  "A6": QT_TRANSLATE_NOOP("Constant", "A6"),
@@ -427,7 +429,7 @@ class nwLabels:
427
429
  "Letter": QT_TRANSLATE_NOOP("Constant", "US Letter"),
428
430
  "Custom": QT_TRANSLATE_NOOP("Constant", "Custom"),
429
431
  }
430
- PAPER_SIZE = {
432
+ PAPER_SIZE: Final[dict[str, tuple[float, float]]] = {
431
433
  "A4": (210.0, 297.0),
432
434
  "A5": (148.0, 210.0),
433
435
  "A6": (105.0, 148.0),
@@ -435,6 +437,18 @@ class nwLabels:
435
437
  "Letter": (215.9, 279.4),
436
438
  "Custom": (-1.0, -1.0),
437
439
  }
440
+ THEME_COLORS: Final[dict[str, str]] = {
441
+ "theme": QT_TRANSLATE_NOOP("Constant", "Theme Colours"),
442
+ "default": QT_TRANSLATE_NOOP("Constant", "Foreground Colour"),
443
+ "faded": QT_TRANSLATE_NOOP("Constant", "Faded Colour"),
444
+ "red": QT_TRANSLATE_NOOP("Constant", "Red"),
445
+ "orange": QT_TRANSLATE_NOOP("Constant", "Orange"),
446
+ "yellow": QT_TRANSLATE_NOOP("Constant", "Yellow"),
447
+ "green": QT_TRANSLATE_NOOP("Constant", "Green"),
448
+ "aqua": QT_TRANSLATE_NOOP("Constant", "Aqua"),
449
+ "blue": QT_TRANSLATE_NOOP("Constant", "Blue"),
450
+ "purple": QT_TRANSLATE_NOOP("Constant", "Purple"),
451
+ }
438
452
 
439
453
 
440
454
  class nwHeadFmt:
@@ -450,7 +464,7 @@ class nwHeadFmt:
450
464
  CHAR_POV = "{Char:POV}"
451
465
  CHAR_FOCUS = "{Char:Focus}"
452
466
 
453
- PAGE_HEADERS = [
467
+ PAGE_HEADERS: Final[list[str]] = [
454
468
  TITLE, CH_NUM, CH_WORD, CH_ROMU, CH_ROML, SC_NUM, SC_ABS,
455
469
  CHAR_POV, CHAR_FOCUS
456
470
  ]
@@ -466,7 +480,7 @@ class nwQuotes:
466
480
  """Allowed quotation marks.
467
481
  Source: https://en.wikipedia.org/wiki/Quotation_mark
468
482
  """
469
- SYMBOLS = {
483
+ SYMBOLS: Final[dict[str, str]] = {
470
484
  "\u0027": QT_TRANSLATE_NOOP("Constant", "Straight single quotation mark"),
471
485
  "\u0022": QT_TRANSLATE_NOOP("Constant", "Straight double quotation mark"),
472
486
 
@@ -631,9 +645,9 @@ class nwUnicode:
631
645
  H_LTRIS = "&#9666;"
632
646
 
633
647
 
634
- class nwHtmlUnicode():
648
+ class nwHtmlUnicode:
635
649
 
636
- U_TO_H = {
650
+ U_TO_H: Final[dict[str, str]] = {
637
651
  # Quotes
638
652
  nwUnicode.U_QUOT: nwUnicode.H_QUOT,
639
653
  nwUnicode.U_APOS: nwUnicode.H_APOS,
@@ -28,11 +28,11 @@ import json
28
28
  import logging
29
29
  import uuid
30
30
 
31
- from collections.abc import Iterable
32
31
  from enum import Enum
33
32
  from pathlib import Path
33
+ from typing import TYPE_CHECKING
34
34
 
35
- from PyQt5.QtCore import QT_TRANSLATE_NOOP, QCoreApplication
35
+ from PyQt6.QtCore import QT_TRANSLATE_NOOP, QCoreApplication
36
36
 
37
37
  from novelwriter import CONFIG
38
38
  from novelwriter.common import checkUuid, isHandle, jsonEncode
@@ -41,13 +41,18 @@ from novelwriter.core.project import NWProject
41
41
  from novelwriter.enum import nwBuildFmt
42
42
  from novelwriter.error import logException
43
43
 
44
+ if TYPE_CHECKING:
45
+ from collections.abc import Iterable
46
+
44
47
  logger = logging.getLogger(__name__)
45
48
 
49
+ T_BuildValue = str | int | float | bool
50
+
46
51
  # The Settings Template
47
52
  # =====================
48
53
  # Each entry contains a tuple on the form: (type, default)
49
54
 
50
- SETTINGS_TEMPLATE: dict[str, tuple[type, str | int | float | bool]] = {
55
+ SETTINGS_TEMPLATE: dict[str, tuple[type, T_BuildValue]] = {
51
56
  "filter.includeNovel": (bool, True),
52
57
  "filter.includeNotes": (bool, False),
53
58
  "filter.includeInactive": (bool, False),
@@ -73,6 +78,7 @@ SETTINGS_TEMPLATE: dict[str, tuple[type, str | int | float | bool]] = {
73
78
  "headings.breakScene": (bool, False),
74
79
  "text.includeSynopsis": (bool, False),
75
80
  "text.includeComments": (bool, False),
81
+ "text.includeStory": (bool, False),
76
82
  "text.includeKeywords": (bool, False),
77
83
  "text.includeBodyText": (bool, True),
78
84
  "text.ignoredKeywords": (str, ""),
@@ -139,6 +145,7 @@ SETTINGS_LABELS = {
139
145
  "text.grpContent": QT_TRANSLATE_NOOP("Builds", "Text Content"),
140
146
  "text.includeSynopsis": QT_TRANSLATE_NOOP("Builds", "Include Synopsis"),
141
147
  "text.includeComments": QT_TRANSLATE_NOOP("Builds", "Include Comments"),
148
+ "text.includeStory": QT_TRANSLATE_NOOP("Builds", "Include Story Structure"),
142
149
  "text.includeKeywords": QT_TRANSLATE_NOOP("Builds", "Include Keywords"),
143
150
  "text.includeBodyText": QT_TRANSLATE_NOOP("Builds", "Include Body Text"),
144
151
  "text.ignoredKeywords": QT_TRANSLATE_NOOP("Builds", "Ignore These Keywords"),
@@ -185,7 +192,6 @@ SETTINGS_LABELS = {
185
192
  }
186
193
 
187
194
  RENAMED = {
188
- "odt.addColours": "doc.addColours",
189
195
  "odt.pageHeader": "doc.pageHeader",
190
196
  "odt.pageCountOffset": "doc.pageCountOffset",
191
197
  }
@@ -226,9 +232,9 @@ class BuildSettings:
226
232
  @classmethod
227
233
  def fromDict(cls, data: dict) -> BuildSettings:
228
234
  """Create a build settings object from a dict."""
229
- cls = BuildSettings()
230
- cls.unpack(data)
231
- return cls
235
+ new = cls()
236
+ new.unpack(data)
237
+ return new
232
238
 
233
239
  ##
234
240
  # Properties
@@ -293,12 +299,12 @@ class BuildSettings:
293
299
  def getInt(self, key: str) -> int:
294
300
  """Type safe value access for integers."""
295
301
  value = self._settings.get(key, SETTINGS_TEMPLATE.get(key, (None, None))[1])
296
- return int(value) if isinstance(value, (int, float)) else 0
302
+ return int(value) if isinstance(value, int | float) else 0
297
303
 
298
304
  def getFloat(self, key: str) -> float:
299
305
  """Type safe value access for floats."""
300
306
  value = self._settings.get(key, SETTINGS_TEMPLATE.get(key, (None, None))[1])
301
- return float(value) if isinstance(value, (int, float)) else 0.0
307
+ return float(value) if isinstance(value, int | float) else 0.0
302
308
 
303
309
  ##
304
310
  # Setters
@@ -379,7 +385,7 @@ class BuildSettings:
379
385
  self._changed = True
380
386
  return
381
387
 
382
- def setValue(self, key: str, value: str | int | float | bool) -> None:
388
+ def setValue(self, key: str, value: T_BuildValue) -> None:
383
389
  """Set a specific value for a build setting."""
384
390
  if (d := SETTINGS_TEMPLATE.get(key)) and len(d) == 2 and isinstance(value, d[0]):
385
391
  self._changed = value != self._settings[key]
@@ -503,7 +509,8 @@ class BuildSettings:
503
509
  self._settings = {k: v[1] for k, v in SETTINGS_TEMPLATE.items()}
504
510
  if isinstance(settings, dict):
505
511
  for key, value in settings.items():
506
- self.setValue(RENAMED.get(key, key), value)
512
+ if isinstance(key, str) and isinstance(value, T_BuildValue):
513
+ self.setValue(RENAMED.get(key, key), value)
507
514
 
508
515
  self._changed = False
509
516
 
@@ -512,11 +519,11 @@ class BuildSettings:
512
519
  @classmethod
513
520
  def duplicate(cls, source: BuildSettings) -> BuildSettings:
514
521
  """Make a copy of another build."""
515
- cls = BuildSettings()
516
- cls.unpack(source.pack())
517
- cls._uuid = str(uuid.uuid4())
518
- cls._name = f"{source.name} 2"
519
- return cls
522
+ new = cls()
523
+ new.unpack(source.pack())
524
+ new._uuid = str(uuid.uuid4())
525
+ new._name = f"{source.name} 2"
526
+ return new
520
527
 
521
528
 
522
529
  class BuildCollection:
@@ -30,20 +30,24 @@ import logging
30
30
  import re
31
31
  import shutil
32
32
 
33
- from collections.abc import Iterable
34
33
  from functools import partial
35
34
  from pathlib import Path
35
+ from typing import TYPE_CHECKING
36
36
  from zipfile import ZipFile, is_zipfile
37
37
 
38
- from PyQt5.QtCore import QCoreApplication
38
+ from PyQt6.QtCore import QCoreApplication
39
39
 
40
40
  from novelwriter import CONFIG, SHARED
41
41
  from novelwriter.common import isHandle, minmax, simplified
42
42
  from novelwriter.constants import nwConst, nwFiles, nwItemClass, nwStats
43
- from novelwriter.core.item import NWItem
44
43
  from novelwriter.core.project import NWProject
45
44
  from novelwriter.core.storage import NWStorageCreate
46
45
 
46
+ if TYPE_CHECKING:
47
+ from collections.abc import Iterable
48
+
49
+ from novelwriter.core.item import NWItem
50
+
47
51
  logger = logging.getLogger(__name__)
48
52
 
49
53
 
@@ -284,7 +288,7 @@ class DocDuplicator:
284
288
  class DocSearch:
285
289
 
286
290
  def __init__(self) -> None:
287
- self._regEx = re.compile("")
291
+ self._regEx = re.compile(r"")
288
292
  self._opts = re.UNICODE | re.IGNORECASE
289
293
  self._words = False
290
294
  self._escape = True
@@ -379,9 +383,9 @@ class ProjectBuilder:
379
383
  """Build or copy a project from a data dictionary."""
380
384
  if isinstance(data, dict):
381
385
  path = data.get("path", None) or None
382
- if isinstance(path, (str, Path)):
386
+ if isinstance(path, str | Path):
383
387
  self._path = Path(path).resolve()
384
- if data.get("sample", False):
388
+ if data.get("sample"):
385
389
  return self._extractSampleProject(self._path)
386
390
  elif data.get("template"):
387
391
  return self._copyProject(self._path, data)
@@ -509,7 +513,7 @@ class ProjectBuilder:
509
513
 
510
514
  # Also add the archive and trash folders
511
515
  project.newRoot(nwItemClass.ARCHIVE)
512
- project.tree.trash # Triggers the creation of Trash
516
+ _ = project.tree.trash # Triggers the creation of Trash
513
517
 
514
518
  project.saveProject()
515
519
  project.closeProject()
@@ -25,26 +25,30 @@ from __future__ import annotations
25
25
 
26
26
  import logging
27
27
 
28
- from collections.abc import Iterable
29
- from pathlib import Path
28
+ from typing import TYPE_CHECKING
30
29
 
31
- from PyQt5.QtGui import QFont
30
+ from PyQt6.QtGui import QFont
32
31
 
33
32
  from novelwriter import CONFIG
34
33
  from novelwriter.constants import nwLabels
35
- from novelwriter.core.buildsettings import BuildSettings
36
34
  from novelwriter.core.item import NWItem
37
- from novelwriter.core.project import NWProject
38
- from novelwriter.enum import nwBuildFmt
35
+ from novelwriter.enum import nwBuildFmt, nwComment
39
36
  from novelwriter.error import formatException, logException
40
37
  from novelwriter.formats.todocx import ToDocX
41
38
  from novelwriter.formats.tohtml import ToHtml
42
- from novelwriter.formats.tokenizer import Tokenizer
43
39
  from novelwriter.formats.tomarkdown import ToMarkdown
44
40
  from novelwriter.formats.toodt import ToOdt
45
41
  from novelwriter.formats.toqdoc import ToQTextDocument
46
42
  from novelwriter.formats.toraw import ToRaw
47
43
 
44
+ if TYPE_CHECKING:
45
+ from collections.abc import Iterable
46
+ from pathlib import Path
47
+
48
+ from novelwriter.core.buildsettings import BuildSettings
49
+ from novelwriter.core.project import NWProject
50
+ from novelwriter.formats.tokenizer import Tokenizer
51
+
48
52
  logger = logging.getLogger(__name__)
49
53
 
50
54
 
@@ -56,8 +60,8 @@ class NWBuildDocument:
56
60
  """
57
61
 
58
62
  __slots__ = (
59
- "_project", "_build", "_queue", "_error", "_cache", "_count",
60
- "_outline",
63
+ "_build", "_cache", "_count", "_error", "_outline", "_project",
64
+ "_queue",
61
65
  )
62
66
 
63
67
  def __init__(self, project: NWProject, build: BuildSettings) -> None:
@@ -307,22 +311,24 @@ class NWBuildDocument:
307
311
  )
308
312
 
309
313
  bldObj.setBodyText(self._build.getBool("text.includeBodyText"))
310
- bldObj.setSynopsis(self._build.getBool("text.includeSynopsis"))
311
- bldObj.setComments(self._build.getBool("text.includeComments"))
312
314
  bldObj.setKeywords(self._build.getBool("text.includeKeywords"))
313
315
  bldObj.setIgnoredKeywords(self._build.getStr("text.ignoredKeywords"))
316
+ bldObj.setCommentType(nwComment.PLAIN, self._build.getBool("text.includeComments"))
317
+ bldObj.setCommentType(nwComment.SYNOPSIS, self._build.getBool("text.includeSynopsis"))
318
+ bldObj.setCommentType(nwComment.SHORT, self._build.getBool("text.includeSynopsis"))
319
+ bldObj.setCommentType(nwComment.STORY, self._build.getBool("text.includeStory"))
314
320
 
315
321
  if isinstance(bldObj, ToHtml):
316
322
  bldObj.setStyles(self._build.getBool("html.addStyles"))
317
323
  bldObj.setReplaceUnicode(self._build.getBool("format.stripUnicode"))
318
324
 
319
- if isinstance(bldObj, (ToOdt, ToDocX)):
325
+ if isinstance(bldObj, ToOdt | ToDocX):
320
326
  bldObj.setHeaderFormat(
321
327
  self._build.getStr("doc.pageHeader"),
322
328
  self._build.getInt("doc.pageCountOffset"),
323
329
  )
324
330
 
325
- if isinstance(bldObj, (ToOdt, ToDocX, ToQTextDocument)):
331
+ if isinstance(bldObj, ToOdt | ToDocX | ToQTextDocument):
326
332
  scale = nwLabels.UNIT_SCALE.get(self._build.getStr("format.pageUnit"), 1.0)
327
333
  pW, pH = nwLabels.PAPER_SIZE.get(self._build.getStr("format.pageSize"), (-1.0, -1.0))
328
334
  bldObj.setPageLayout(
@@ -31,11 +31,11 @@ from time import time
31
31
  from typing import TYPE_CHECKING
32
32
 
33
33
  from novelwriter.common import formatTimeStamp, isHandle
34
- from novelwriter.core.item import NWItem
35
34
  from novelwriter.enum import nwItemClass, nwItemLayout
36
35
  from novelwriter.error import formatException, logException
37
36
 
38
- if TYPE_CHECKING: # pragma: no cover
37
+ if TYPE_CHECKING:
38
+ from novelwriter.core.item import NWItem
39
39
  from novelwriter.core.project import NWProject
40
40
 
41
41
  logger = logging.getLogger(__name__)