novelWriter 2.6.2__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 (334) hide show
  1. novelwriter/__init__.py +84 -74
  2. novelwriter/assets/i18n/nw_cs_CZ.qm +0 -0
  3. novelwriter/assets/i18n/nw_de_DE.qm +0 -0
  4. novelwriter/assets/i18n/nw_en_US.qm +0 -0
  5. novelwriter/assets/i18n/nw_es_419.qm +0 -0
  6. novelwriter/assets/i18n/nw_fr_FR.qm +0 -0
  7. novelwriter/assets/i18n/nw_it_IT.qm +0 -0
  8. novelwriter/assets/i18n/nw_ja_JP.qm +0 -0
  9. novelwriter/assets/i18n/nw_nb_NO.qm +0 -0
  10. novelwriter/assets/i18n/nw_nl_NL.qm +0 -0
  11. novelwriter/assets/i18n/nw_pl_PL.qm +0 -0
  12. novelwriter/assets/i18n/nw_pt_BR.qm +0 -0
  13. novelwriter/assets/i18n/nw_ru_RU.qm +0 -0
  14. novelwriter/assets/i18n/nw_zh_CN.qm +0 -0
  15. novelwriter/assets/i18n/project_en_GB.json +1 -0
  16. novelwriter/assets/icons/font_awesome.icons +109 -0
  17. novelwriter/assets/icons/material_filled_bold.icons +109 -0
  18. novelwriter/assets/icons/material_filled_normal.icons +109 -0
  19. novelwriter/assets/icons/material_filled_thin.icons +109 -0
  20. novelwriter/assets/icons/material_rounded_bold.icons +109 -0
  21. novelwriter/assets/icons/material_rounded_normal.icons +109 -0
  22. novelwriter/assets/icons/material_rounded_thin.icons +109 -0
  23. novelwriter/assets/icons/remix_filled.icons +108 -0
  24. novelwriter/assets/icons/remix_outline.icons +108 -0
  25. novelwriter/assets/manual.pdf +0 -0
  26. novelwriter/assets/{manual_fr_FR.pdf → manual_fr.pdf} +0 -0
  27. novelwriter/assets/sample.zip +0 -0
  28. novelwriter/assets/syntax/cyberpunk_night.conf +1 -1
  29. novelwriter/assets/text/credits_en.htm +6 -6
  30. novelwriter/assets/themes/cyberpunk_night.conf +23 -7
  31. novelwriter/assets/themes/default_dark.conf +20 -4
  32. novelwriter/assets/themes/default_light.conf +21 -5
  33. novelwriter/assets/themes/dracula.conf +20 -4
  34. novelwriter/assets/themes/solarized_dark.conf +24 -8
  35. novelwriter/assets/themes/solarized_light.conf +22 -6
  36. novelwriter/common.py +33 -26
  37. novelwriter/config.py +118 -127
  38. novelwriter/constants.py +75 -56
  39. novelwriter/core/buildsettings.py +23 -16
  40. novelwriter/core/coretools.py +11 -7
  41. novelwriter/core/docbuild.py +19 -13
  42. novelwriter/core/document.py +2 -2
  43. novelwriter/core/index.py +142 -432
  44. novelwriter/core/indexdata.py +403 -0
  45. novelwriter/core/item.py +35 -28
  46. novelwriter/core/itemmodel.py +27 -26
  47. novelwriter/core/novelmodel.py +223 -0
  48. novelwriter/core/options.py +1 -1
  49. novelwriter/core/project.py +10 -11
  50. novelwriter/core/projectdata.py +5 -5
  51. novelwriter/core/projectxml.py +1 -1
  52. novelwriter/core/sessions.py +3 -2
  53. novelwriter/core/spellcheck.py +4 -3
  54. novelwriter/core/status.py +12 -15
  55. novelwriter/core/storage.py +1 -1
  56. novelwriter/core/tree.py +46 -8
  57. novelwriter/dialogs/about.py +19 -22
  58. novelwriter/dialogs/docmerge.py +21 -23
  59. novelwriter/dialogs/docsplit.py +20 -23
  60. novelwriter/dialogs/editlabel.py +9 -13
  61. novelwriter/dialogs/preferences.py +111 -48
  62. novelwriter/dialogs/projectsettings.py +48 -54
  63. novelwriter/dialogs/quotes.py +14 -19
  64. novelwriter/dialogs/wordlist.py +25 -30
  65. novelwriter/enum.py +8 -0
  66. novelwriter/error.py +16 -16
  67. novelwriter/extensions/configlayout.py +18 -18
  68. novelwriter/extensions/eventfilters.py +9 -5
  69. novelwriter/extensions/modified.py +34 -15
  70. novelwriter/extensions/novelselector.py +18 -5
  71. novelwriter/extensions/pagedsidebar.py +39 -49
  72. novelwriter/extensions/progressbars.py +10 -8
  73. novelwriter/extensions/statusled.py +6 -13
  74. novelwriter/extensions/switch.py +19 -30
  75. novelwriter/extensions/switchbox.py +7 -3
  76. novelwriter/extensions/versioninfo.py +4 -4
  77. novelwriter/formats/shared.py +1 -1
  78. novelwriter/formats/todocx.py +14 -10
  79. novelwriter/formats/tohtml.py +7 -5
  80. novelwriter/formats/tokenizer.py +36 -33
  81. novelwriter/formats/tomarkdown.py +6 -2
  82. novelwriter/formats/toodt.py +27 -22
  83. novelwriter/formats/toqdoc.py +19 -14
  84. novelwriter/formats/toraw.py +6 -2
  85. novelwriter/gui/doceditor.py +216 -265
  86. novelwriter/gui/dochighlight.py +46 -45
  87. novelwriter/gui/docviewer.py +102 -104
  88. novelwriter/gui/docviewerpanel.py +47 -51
  89. novelwriter/gui/editordocument.py +8 -5
  90. novelwriter/gui/itemdetails.py +15 -18
  91. novelwriter/gui/mainmenu.py +147 -146
  92. novelwriter/gui/noveltree.py +239 -405
  93. novelwriter/gui/outline.py +137 -76
  94. novelwriter/gui/projtree.py +138 -132
  95. novelwriter/gui/search.py +33 -31
  96. novelwriter/gui/sidebar.py +13 -18
  97. novelwriter/gui/statusbar.py +13 -15
  98. novelwriter/gui/theme.py +533 -430
  99. novelwriter/guimain.py +27 -29
  100. novelwriter/shared.py +32 -23
  101. novelwriter/text/comments.py +70 -0
  102. novelwriter/text/patterns.py +4 -4
  103. novelwriter/tools/dictionaries.py +20 -29
  104. novelwriter/tools/lipsum.py +16 -17
  105. novelwriter/tools/manusbuild.py +39 -42
  106. novelwriter/tools/manuscript.py +113 -126
  107. novelwriter/tools/manussettings.py +78 -83
  108. novelwriter/tools/noveldetails.py +51 -64
  109. novelwriter/tools/welcome.py +56 -75
  110. novelwriter/tools/writingstats.py +44 -57
  111. novelwriter/types.py +5 -7
  112. {novelWriter-2.6.2.dist-info → novelwriter-2.7b1.dist-info}/METADATA +6 -6
  113. novelwriter-2.7b1.dist-info/RECORD +159 -0
  114. {novelWriter-2.6.2.dist-info → novelwriter-2.7b1.dist-info}/WHEEL +1 -1
  115. novelWriter-2.6.2.dist-info/RECORD +0 -363
  116. novelwriter/assets/icons/typicons_dark/README.md +0 -29
  117. novelwriter/assets/icons/typicons_dark/icons.conf +0 -134
  118. novelwriter/assets/icons/typicons_dark/mixed_copy.svg +0 -4
  119. novelwriter/assets/icons/typicons_dark/mixed_document-chapter.svg +0 -12
  120. novelwriter/assets/icons/typicons_dark/mixed_document-new.svg +0 -6
  121. novelwriter/assets/icons/typicons_dark/mixed_document-note.svg +0 -12
  122. novelwriter/assets/icons/typicons_dark/mixed_document-scene.svg +0 -12
  123. novelwriter/assets/icons/typicons_dark/mixed_document-section.svg +0 -12
  124. novelwriter/assets/icons/typicons_dark/mixed_document-title.svg +0 -12
  125. novelwriter/assets/icons/typicons_dark/mixed_edit.svg +0 -4
  126. novelwriter/assets/icons/typicons_dark/mixed_import.svg +0 -5
  127. novelwriter/assets/icons/typicons_dark/mixed_input-checked.svg +0 -5
  128. novelwriter/assets/icons/typicons_dark/mixed_input-none.svg +0 -5
  129. novelwriter/assets/icons/typicons_dark/mixed_input-unchecked.svg +0 -5
  130. novelwriter/assets/icons/typicons_dark/mixed_margin-bottom.svg +0 -6
  131. novelwriter/assets/icons/typicons_dark/mixed_margin-left.svg +0 -6
  132. novelwriter/assets/icons/typicons_dark/mixed_margin-right.svg +0 -6
  133. novelwriter/assets/icons/typicons_dark/mixed_margin-top.svg +0 -6
  134. novelwriter/assets/icons/typicons_dark/mixed_search-replace.svg +0 -6
  135. novelwriter/assets/icons/typicons_dark/mixed_size-height.svg +0 -6
  136. novelwriter/assets/icons/typicons_dark/mixed_size-width.svg +0 -6
  137. novelwriter/assets/icons/typicons_dark/nw_deco-h0.svg +0 -4
  138. novelwriter/assets/icons/typicons_dark/nw_deco-h1.svg +0 -4
  139. novelwriter/assets/icons/typicons_dark/nw_deco-h2-narrow.svg +0 -4
  140. novelwriter/assets/icons/typicons_dark/nw_deco-h2.svg +0 -4
  141. novelwriter/assets/icons/typicons_dark/nw_deco-h3-narrow.svg +0 -4
  142. novelwriter/assets/icons/typicons_dark/nw_deco-h3.svg +0 -4
  143. novelwriter/assets/icons/typicons_dark/nw_deco-h4-narrow.svg +0 -4
  144. novelwriter/assets/icons/typicons_dark/nw_deco-h4.svg +0 -4
  145. novelwriter/assets/icons/typicons_dark/nw_deco-note.svg +0 -4
  146. novelwriter/assets/icons/typicons_dark/nw_deco-noveltree-more.svg +0 -4
  147. novelwriter/assets/icons/typicons_dark/nw_font.svg +0 -4
  148. novelwriter/assets/icons/typicons_dark/nw_panel.svg +0 -4
  149. novelwriter/assets/icons/typicons_dark/nw_quote.svg +0 -4
  150. novelwriter/assets/icons/typicons_dark/nw_search-case.svg +0 -4
  151. novelwriter/assets/icons/typicons_dark/nw_search-preserve.svg +0 -4
  152. novelwriter/assets/icons/typicons_dark/nw_search-regex.svg +0 -4
  153. novelwriter/assets/icons/typicons_dark/nw_search-word.svg +0 -4
  154. novelwriter/assets/icons/typicons_dark/nw_tb-bold-md.svg +0 -4
  155. novelwriter/assets/icons/typicons_dark/nw_tb-bold.svg +0 -6
  156. novelwriter/assets/icons/typicons_dark/nw_tb-italic-md.svg +0 -4
  157. novelwriter/assets/icons/typicons_dark/nw_tb-italic.svg +0 -6
  158. novelwriter/assets/icons/typicons_dark/nw_tb-mark.svg +0 -7
  159. novelwriter/assets/icons/typicons_dark/nw_tb-strike-md.svg +0 -4
  160. novelwriter/assets/icons/typicons_dark/nw_tb-strike.svg +0 -6
  161. novelwriter/assets/icons/typicons_dark/nw_tb-subscript.svg +0 -7
  162. novelwriter/assets/icons/typicons_dark/nw_tb-superscript.svg +0 -7
  163. novelwriter/assets/icons/typicons_dark/nw_tb-underline.svg +0 -7
  164. novelwriter/assets/icons/typicons_dark/nw_toolbar.svg +0 -5
  165. novelwriter/assets/icons/typicons_dark/typ_arrow-down-thick-grey.svg +0 -4
  166. novelwriter/assets/icons/typicons_dark/typ_arrow-forward.svg +0 -4
  167. novelwriter/assets/icons/typicons_dark/typ_arrow-maximise.svg +0 -4
  168. novelwriter/assets/icons/typicons_dark/typ_arrow-minimise.svg +0 -4
  169. novelwriter/assets/icons/typicons_dark/typ_arrow-repeat-grey.svg +0 -4
  170. novelwriter/assets/icons/typicons_dark/typ_book-grey.svg +0 -4
  171. novelwriter/assets/icons/typicons_dark/typ_book.svg +0 -6
  172. novelwriter/assets/icons/typicons_dark/typ_bookmark.svg +0 -4
  173. novelwriter/assets/icons/typicons_dark/typ_calendar.svg +0 -4
  174. novelwriter/assets/icons/typicons_dark/typ_cancel-grey.svg +0 -4
  175. novelwriter/assets/icons/typicons_dark/typ_cancel.svg +0 -4
  176. novelwriter/assets/icons/typicons_dark/typ_chart-bar-grey.svg +0 -4
  177. novelwriter/assets/icons/typicons_dark/typ_chevron-down.svg +0 -4
  178. novelwriter/assets/icons/typicons_dark/typ_chevron-left.svg +0 -4
  179. novelwriter/assets/icons/typicons_dark/typ_chevron-right.svg +0 -4
  180. novelwriter/assets/icons/typicons_dark/typ_chevron-up.svg +0 -4
  181. novelwriter/assets/icons/typicons_dark/typ_cog.svg +0 -4
  182. novelwriter/assets/icons/typicons_dark/typ_delete-full.svg +0 -4
  183. novelwriter/assets/icons/typicons_dark/typ_delete.svg +0 -4
  184. novelwriter/assets/icons/typicons_dark/typ_directions-full.svg +0 -4
  185. novelwriter/assets/icons/typicons_dark/typ_document-add.svg +0 -4
  186. novelwriter/assets/icons/typicons_dark/typ_document-text.svg +0 -8
  187. novelwriter/assets/icons/typicons_dark/typ_document.svg +0 -4
  188. novelwriter/assets/icons/typicons_dark/typ_export-grey.svg +0 -4
  189. novelwriter/assets/icons/typicons_dark/typ_export.svg +0 -4
  190. novelwriter/assets/icons/typicons_dark/typ_eye.svg +0 -4
  191. novelwriter/assets/icons/typicons_dark/typ_flag.svg +0 -4
  192. novelwriter/assets/icons/typicons_dark/typ_folder-open.svg +0 -4
  193. novelwriter/assets/icons/typicons_dark/typ_folder.svg +0 -5
  194. novelwriter/assets/icons/typicons_dark/typ_globe-grey.svg +0 -4
  195. novelwriter/assets/icons/typicons_dark/typ_key.svg +0 -4
  196. novelwriter/assets/icons/typicons_dark/typ_lightbulb-full.svg +0 -4
  197. novelwriter/assets/icons/typicons_dark/typ_location.svg +0 -4
  198. novelwriter/assets/icons/typicons_dark/typ_media-pause-grey.svg +0 -4
  199. novelwriter/assets/icons/typicons_dark/typ_media-record-outline.svg +0 -4
  200. novelwriter/assets/icons/typicons_dark/typ_media-record.svg +0 -4
  201. novelwriter/assets/icons/typicons_dark/typ_minus.svg +0 -4
  202. novelwriter/assets/icons/typicons_dark/typ_pencil.svg +0 -5
  203. novelwriter/assets/icons/typicons_dark/typ_pin-outline.svg +0 -4
  204. novelwriter/assets/icons/typicons_dark/typ_pin.svg +0 -4
  205. novelwriter/assets/icons/typicons_dark/typ_plus.svg +0 -4
  206. novelwriter/assets/icons/typicons_dark/typ_puzzle-outline.svg +0 -4
  207. novelwriter/assets/icons/typicons_dark/typ_puzzle.svg +0 -4
  208. novelwriter/assets/icons/typicons_dark/typ_refresh-flipped.svg +0 -4
  209. novelwriter/assets/icons/typicons_dark/typ_refresh.svg +0 -4
  210. novelwriter/assets/icons/typicons_dark/typ_search-grey.svg +0 -4
  211. novelwriter/assets/icons/typicons_dark/typ_search.svg +0 -4
  212. novelwriter/assets/icons/typicons_dark/typ_star.svg +0 -4
  213. novelwriter/assets/icons/typicons_dark/typ_stopwatch-grey.svg +0 -4
  214. novelwriter/assets/icons/typicons_dark/typ_th-dot-menu.svg +0 -4
  215. novelwriter/assets/icons/typicons_dark/typ_th-dot-more.svg +0 -4
  216. novelwriter/assets/icons/typicons_dark/typ_th-list-grey.svg +0 -4
  217. novelwriter/assets/icons/typicons_dark/typ_th-list.svg +0 -9
  218. novelwriter/assets/icons/typicons_dark/typ_times.svg +0 -4
  219. novelwriter/assets/icons/typicons_dark/typ_trash.svg +0 -5
  220. novelwriter/assets/icons/typicons_dark/typ_unfold-hidden.svg +0 -4
  221. novelwriter/assets/icons/typicons_dark/typ_unfold-visible.svg +0 -4
  222. novelwriter/assets/icons/typicons_dark/typ_user.svg +0 -5
  223. novelwriter/assets/icons/typicons_dark/typ_warning-full.svg +0 -4
  224. novelwriter/assets/icons/typicons_light/README.md +0 -29
  225. novelwriter/assets/icons/typicons_light/icons.conf +0 -134
  226. novelwriter/assets/icons/typicons_light/mixed_copy.svg +0 -4
  227. novelwriter/assets/icons/typicons_light/mixed_document-chapter.svg +0 -12
  228. novelwriter/assets/icons/typicons_light/mixed_document-new.svg +0 -6
  229. novelwriter/assets/icons/typicons_light/mixed_document-note.svg +0 -12
  230. novelwriter/assets/icons/typicons_light/mixed_document-scene.svg +0 -12
  231. novelwriter/assets/icons/typicons_light/mixed_document-section.svg +0 -12
  232. novelwriter/assets/icons/typicons_light/mixed_document-title.svg +0 -12
  233. novelwriter/assets/icons/typicons_light/mixed_edit.svg +0 -4
  234. novelwriter/assets/icons/typicons_light/mixed_import.svg +0 -5
  235. novelwriter/assets/icons/typicons_light/mixed_input-checked.svg +0 -5
  236. novelwriter/assets/icons/typicons_light/mixed_input-none.svg +0 -5
  237. novelwriter/assets/icons/typicons_light/mixed_input-unchecked.svg +0 -5
  238. novelwriter/assets/icons/typicons_light/mixed_margin-bottom.svg +0 -6
  239. novelwriter/assets/icons/typicons_light/mixed_margin-left.svg +0 -6
  240. novelwriter/assets/icons/typicons_light/mixed_margin-right.svg +0 -6
  241. novelwriter/assets/icons/typicons_light/mixed_margin-top.svg +0 -6
  242. novelwriter/assets/icons/typicons_light/mixed_search-replace.svg +0 -6
  243. novelwriter/assets/icons/typicons_light/mixed_size-height.svg +0 -6
  244. novelwriter/assets/icons/typicons_light/mixed_size-width.svg +0 -6
  245. novelwriter/assets/icons/typicons_light/nw_deco-h0.svg +0 -4
  246. novelwriter/assets/icons/typicons_light/nw_deco-h1.svg +0 -4
  247. novelwriter/assets/icons/typicons_light/nw_deco-h2-narrow.svg +0 -4
  248. novelwriter/assets/icons/typicons_light/nw_deco-h2.svg +0 -4
  249. novelwriter/assets/icons/typicons_light/nw_deco-h3-narrow.svg +0 -4
  250. novelwriter/assets/icons/typicons_light/nw_deco-h3.svg +0 -4
  251. novelwriter/assets/icons/typicons_light/nw_deco-h4-narrow.svg +0 -4
  252. novelwriter/assets/icons/typicons_light/nw_deco-h4.svg +0 -4
  253. novelwriter/assets/icons/typicons_light/nw_deco-note.svg +0 -4
  254. novelwriter/assets/icons/typicons_light/nw_deco-noveltree-more.svg +0 -4
  255. novelwriter/assets/icons/typicons_light/nw_font.svg +0 -4
  256. novelwriter/assets/icons/typicons_light/nw_panel.svg +0 -4
  257. novelwriter/assets/icons/typicons_light/nw_quote.svg +0 -4
  258. novelwriter/assets/icons/typicons_light/nw_search-case.svg +0 -4
  259. novelwriter/assets/icons/typicons_light/nw_search-preserve.svg +0 -4
  260. novelwriter/assets/icons/typicons_light/nw_search-regex.svg +0 -4
  261. novelwriter/assets/icons/typicons_light/nw_search-word.svg +0 -4
  262. novelwriter/assets/icons/typicons_light/nw_tb-bold-md.svg +0 -4
  263. novelwriter/assets/icons/typicons_light/nw_tb-bold.svg +0 -6
  264. novelwriter/assets/icons/typicons_light/nw_tb-italic-md.svg +0 -4
  265. novelwriter/assets/icons/typicons_light/nw_tb-italic.svg +0 -6
  266. novelwriter/assets/icons/typicons_light/nw_tb-mark.svg +0 -7
  267. novelwriter/assets/icons/typicons_light/nw_tb-strike-md.svg +0 -4
  268. novelwriter/assets/icons/typicons_light/nw_tb-strike.svg +0 -6
  269. novelwriter/assets/icons/typicons_light/nw_tb-subscript.svg +0 -7
  270. novelwriter/assets/icons/typicons_light/nw_tb-superscript.svg +0 -7
  271. novelwriter/assets/icons/typicons_light/nw_tb-underline.svg +0 -7
  272. novelwriter/assets/icons/typicons_light/nw_toolbar.svg +0 -5
  273. novelwriter/assets/icons/typicons_light/typ_arrow-down-thick-grey.svg +0 -4
  274. novelwriter/assets/icons/typicons_light/typ_arrow-forward.svg +0 -4
  275. novelwriter/assets/icons/typicons_light/typ_arrow-maximise.svg +0 -4
  276. novelwriter/assets/icons/typicons_light/typ_arrow-minimise.svg +0 -4
  277. novelwriter/assets/icons/typicons_light/typ_arrow-repeat-grey.svg +0 -4
  278. novelwriter/assets/icons/typicons_light/typ_book-grey.svg +0 -4
  279. novelwriter/assets/icons/typicons_light/typ_book.svg +0 -6
  280. novelwriter/assets/icons/typicons_light/typ_bookmark.svg +0 -4
  281. novelwriter/assets/icons/typicons_light/typ_calendar.svg +0 -4
  282. novelwriter/assets/icons/typicons_light/typ_cancel-grey.svg +0 -4
  283. novelwriter/assets/icons/typicons_light/typ_cancel.svg +0 -4
  284. novelwriter/assets/icons/typicons_light/typ_chart-bar-grey.svg +0 -4
  285. novelwriter/assets/icons/typicons_light/typ_chevron-down.svg +0 -4
  286. novelwriter/assets/icons/typicons_light/typ_chevron-left.svg +0 -4
  287. novelwriter/assets/icons/typicons_light/typ_chevron-right.svg +0 -4
  288. novelwriter/assets/icons/typicons_light/typ_chevron-up.svg +0 -4
  289. novelwriter/assets/icons/typicons_light/typ_cog.svg +0 -4
  290. novelwriter/assets/icons/typicons_light/typ_delete-full.svg +0 -4
  291. novelwriter/assets/icons/typicons_light/typ_delete.svg +0 -4
  292. novelwriter/assets/icons/typicons_light/typ_directions-full.svg +0 -4
  293. novelwriter/assets/icons/typicons_light/typ_document-add.svg +0 -4
  294. novelwriter/assets/icons/typicons_light/typ_document-text.svg +0 -5
  295. novelwriter/assets/icons/typicons_light/typ_document.svg +0 -4
  296. novelwriter/assets/icons/typicons_light/typ_export-grey.svg +0 -4
  297. novelwriter/assets/icons/typicons_light/typ_export.svg +0 -4
  298. novelwriter/assets/icons/typicons_light/typ_eye.svg +0 -4
  299. novelwriter/assets/icons/typicons_light/typ_flag.svg +0 -4
  300. novelwriter/assets/icons/typicons_light/typ_folder-open.svg +0 -4
  301. novelwriter/assets/icons/typicons_light/typ_folder.svg +0 -5
  302. novelwriter/assets/icons/typicons_light/typ_globe-grey.svg +0 -4
  303. novelwriter/assets/icons/typicons_light/typ_key.svg +0 -4
  304. novelwriter/assets/icons/typicons_light/typ_lightbulb-full.svg +0 -4
  305. novelwriter/assets/icons/typicons_light/typ_location.svg +0 -4
  306. novelwriter/assets/icons/typicons_light/typ_media-pause-grey.svg +0 -4
  307. novelwriter/assets/icons/typicons_light/typ_media-record-outline.svg +0 -4
  308. novelwriter/assets/icons/typicons_light/typ_media-record.svg +0 -4
  309. novelwriter/assets/icons/typicons_light/typ_minus.svg +0 -4
  310. novelwriter/assets/icons/typicons_light/typ_pencil.svg +0 -5
  311. novelwriter/assets/icons/typicons_light/typ_pin-outline.svg +0 -4
  312. novelwriter/assets/icons/typicons_light/typ_pin.svg +0 -4
  313. novelwriter/assets/icons/typicons_light/typ_plus.svg +0 -4
  314. novelwriter/assets/icons/typicons_light/typ_puzzle-outline.svg +0 -4
  315. novelwriter/assets/icons/typicons_light/typ_puzzle.svg +0 -4
  316. novelwriter/assets/icons/typicons_light/typ_refresh-flipped.svg +0 -4
  317. novelwriter/assets/icons/typicons_light/typ_refresh.svg +0 -4
  318. novelwriter/assets/icons/typicons_light/typ_search-grey.svg +0 -4
  319. novelwriter/assets/icons/typicons_light/typ_search.svg +0 -4
  320. novelwriter/assets/icons/typicons_light/typ_star.svg +0 -4
  321. novelwriter/assets/icons/typicons_light/typ_stopwatch-grey.svg +0 -4
  322. novelwriter/assets/icons/typicons_light/typ_th-dot-menu.svg +0 -4
  323. novelwriter/assets/icons/typicons_light/typ_th-dot-more.svg +0 -4
  324. novelwriter/assets/icons/typicons_light/typ_th-list-grey.svg +0 -4
  325. novelwriter/assets/icons/typicons_light/typ_th-list.svg +0 -9
  326. novelwriter/assets/icons/typicons_light/typ_times.svg +0 -4
  327. novelwriter/assets/icons/typicons_light/typ_trash.svg +0 -5
  328. novelwriter/assets/icons/typicons_light/typ_unfold-hidden.svg +0 -4
  329. novelwriter/assets/icons/typicons_light/typ_unfold-visible.svg +0 -4
  330. novelwriter/assets/icons/typicons_light/typ_user.svg +0 -5
  331. novelwriter/assets/icons/typicons_light/typ_warning-full.svg +0 -4
  332. {novelWriter-2.6.2.dist-info → novelwriter-2.7b1.dist-info}/entry_points.txt +0 -0
  333. {novelWriter-2.6.2.dist-info → novelwriter-2.7b1.dist-info/licenses}/LICENSE.md +0 -0
  334. {novelWriter-2.6.2.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
@@ -35,6 +37,11 @@ def trConst(text: str) -> str:
35
37
  return QCoreApplication.translate("Constant", text)
36
38
 
37
39
 
40
+ def trStats(text: str) -> str:
41
+ """Wrapper function for locally translating stats constants."""
42
+ return QCoreApplication.translate("Stats", text)
43
+
44
+
38
45
  class nwConst:
39
46
 
40
47
  # Date and Time Formats
@@ -94,7 +101,7 @@ class nwShortcode:
94
101
  FOOTNOTE_B = "[footnote:"
95
102
  FIELD_B = "[field:"
96
103
 
97
- COMMENT_STYLES = {
104
+ COMMENT_STYLES: Final[dict[nwComment, str]] = {
98
105
  nwComment.FOOTNOTE: "[footnote:{0}]",
99
106
  nwComment.COMMENT: "[comment:{0}]",
100
107
  }
@@ -105,13 +112,13 @@ class nwShortcode:
105
112
  class nwStyles:
106
113
 
107
114
  H_VALID = ("H0", "H1", "H2", "H3", "H4")
108
- H_LEVEL = {"H0": 0, "H1": 1, "H2": 2, "H3": 3, "H4": 4}
109
- 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}
110
117
 
111
118
  T_NORMAL = 1.0
112
119
  T_SMALL = 0.8
113
120
 
114
- T_LABEL = {
121
+ T_LABEL: Final[dict[str, str]] = {
115
122
  "H0": QT_TRANSLATE_NOOP("Constant", "Title"),
116
123
  "H1": QT_TRANSLATE_NOOP("Constant", "Heading 1 (Partition)"),
117
124
  "H2": QT_TRANSLATE_NOOP("Constant", "Heading 2 (Chapter)"),
@@ -120,7 +127,7 @@ class nwStyles:
120
127
  "TT": QT_TRANSLATE_NOOP("Constant", "Text Paragraph"),
121
128
  "SP": QT_TRANSLATE_NOOP("Constant", "Scene Separator"),
122
129
  }
123
- T_MARGIN = {
130
+ T_MARGIN: Final[dict[str, tuple[float, float]]] = {
124
131
  "H0": (1.50, 0.60), # Title margins (top, bottom)
125
132
  "H1": (1.50, 0.60), # Heading 1 margins (top, bottom)
126
133
  "H2": (1.50, 0.60), # Heading 2 margins (top, bottom)
@@ -169,20 +176,20 @@ class nwKeyWords:
169
176
  MENTION_KEY = "@mention"
170
177
 
171
178
  # Note: The order here affects the order of menu entries
172
- ALL_KEYS = [
179
+ ALL_KEYS: Final[list[str]] = [
173
180
  TAG_KEY, POV_KEY, FOCUS_KEY, CHAR_KEY, PLOT_KEY, TIME_KEY, WORLD_KEY,
174
181
  OBJECT_KEY, ENTITY_KEY, CUSTOM_KEY, STORY_KEY, MENTION_KEY,
175
182
  ]
176
- CAN_CREATE = [
183
+ CAN_CREATE: Final[list[str]] = [
177
184
  POV_KEY, FOCUS_KEY, CHAR_KEY, PLOT_KEY, TIME_KEY, WORLD_KEY,
178
185
  OBJECT_KEY, ENTITY_KEY, CUSTOM_KEY,
179
186
  ]
180
187
 
181
188
  # Set of Valid Keys
182
- VALID_KEYS = set(ALL_KEYS)
189
+ VALID_KEYS: Final[set[str]] = set(ALL_KEYS)
183
190
 
184
191
  # Map from Keys to Item Class
185
- KEY_CLASS = {
192
+ KEY_CLASS: Final[dict[str, nwItemClass]] = {
186
193
  POV_KEY: nwItemClass.CHARACTER,
187
194
  FOCUS_KEY: nwItemClass.CHARACTER,
188
195
  CHAR_KEY: nwItemClass.CHARACTER,
@@ -198,7 +205,7 @@ class nwKeyWords:
198
205
 
199
206
  class nwLists:
200
207
 
201
- USER_CLASSES = [
208
+ USER_CLASSES: Final[list[nwItemClass]] = [
202
209
  nwItemClass.CHARACTER,
203
210
  nwItemClass.PLOT,
204
211
  nwItemClass.WORLD,
@@ -224,7 +231,7 @@ class nwStats:
224
231
  WORDS_TITLE = "titleWords"
225
232
 
226
233
  # Note: The order here affects the order of menu entries
227
- ALL_FIELDS = [
234
+ ALL_FIELDS: Final[list[str]] = [
228
235
  WORDS, WORDS_TEXT, WORDS_TITLE,
229
236
  CHARS, CHARS_TEXT, CHARS_TITLE,
230
237
  WCHARS_ALL, WCHARS_TEXT, WCHARS_TITLE,
@@ -234,7 +241,7 @@ class nwStats:
234
241
 
235
242
  class nwLabels:
236
243
 
237
- CLASS_NAME = {
244
+ CLASS_NAME: Final[dict[nwItemClass, str]] = {
238
245
  nwItemClass.NO_CLASS: QT_TRANSLATE_NOOP("Constant", "None"),
239
246
  nwItemClass.NOVEL: QT_TRANSLATE_NOOP("Constant", "Novel"),
240
247
  nwItemClass.PLOT: QT_TRANSLATE_NOOP("Constant", "Plot"),
@@ -248,7 +255,7 @@ class nwLabels:
248
255
  nwItemClass.TEMPLATE: QT_TRANSLATE_NOOP("Constant", "Templates"),
249
256
  nwItemClass.TRASH: QT_TRANSLATE_NOOP("Constant", "Trash"),
250
257
  }
251
- CLASS_ICON = {
258
+ CLASS_ICON: Final[dict[nwItemClass, str]] = {
252
259
  nwItemClass.NO_CLASS: "cls_none",
253
260
  nwItemClass.NOVEL: "cls_novel",
254
261
  nwItemClass.PLOT: "cls_plot",
@@ -262,12 +269,12 @@ class nwLabels:
262
269
  nwItemClass.TEMPLATE: "cls_template",
263
270
  nwItemClass.TRASH: "cls_trash",
264
271
  }
265
- LAYOUT_NAME = {
272
+ LAYOUT_NAME: Final[dict[nwItemLayout, str]] = {
266
273
  nwItemLayout.NO_LAYOUT: QT_TRANSLATE_NOOP("Constant", "None"),
267
274
  nwItemLayout.DOCUMENT: QT_TRANSLATE_NOOP("Constant", "Novel Document"),
268
275
  nwItemLayout.NOTE: QT_TRANSLATE_NOOP("Constant", "Project Note"),
269
276
  }
270
- ITEM_DESCRIPTION = {
277
+ ITEM_DESCRIPTION: Final[dict[str, str]] = {
271
278
  "none": QT_TRANSLATE_NOOP("Constant", "None"),
272
279
  "root": QT_TRANSLATE_NOOP("Constant", "Root Folder"),
273
280
  "folder": QT_TRANSLATE_NOOP("Constant", "Folder"),
@@ -278,11 +285,11 @@ class nwLabels:
278
285
  "doc_h4": QT_TRANSLATE_NOOP("Constant", "Novel Section"),
279
286
  "note": QT_TRANSLATE_NOOP("Constant", "Project Note"),
280
287
  }
281
- ACTIVE_NAME = {
288
+ ACTIVE_NAME: Final[dict[str, str]] = {
282
289
  "checked": QT_TRANSLATE_NOOP("Constant", "Active"),
283
290
  "unchecked": QT_TRANSLATE_NOOP("Constant", "Inactive"),
284
291
  }
285
- KEY_NAME = {
292
+ KEY_NAME: Final[dict[str, str]] = {
286
293
  nwKeyWords.TAG_KEY: QT_TRANSLATE_NOOP("Constant", "Tag"),
287
294
  nwKeyWords.POV_KEY: QT_TRANSLATE_NOOP("Constant", "Point of View"),
288
295
  nwKeyWords.FOCUS_KEY: QT_TRANSLATE_NOOP("Constant", "Focus"),
@@ -296,7 +303,7 @@ class nwLabels:
296
303
  nwKeyWords.STORY_KEY: QT_TRANSLATE_NOOP("Constant", "Story"),
297
304
  nwKeyWords.MENTION_KEY: QT_TRANSLATE_NOOP("Constant", "Mentions"),
298
305
  }
299
- KEY_SHORTCUT = {
306
+ KEY_SHORTCUT: Final[dict[str, str]] = {
300
307
  nwKeyWords.TAG_KEY: "Ctrl+K, G",
301
308
  nwKeyWords.POV_KEY: "Ctrl+K, V",
302
309
  nwKeyWords.FOCUS_KEY: "Ctrl+K, F",
@@ -310,7 +317,7 @@ class nwLabels:
310
317
  nwKeyWords.STORY_KEY: "Ctrl+K, N",
311
318
  nwKeyWords.MENTION_KEY: "Ctrl+K, M",
312
319
  }
313
- OUTLINE_COLS = {
320
+ OUTLINE_COLS: Final[dict[nwOutline, str]] = {
314
321
  nwOutline.TITLE: QT_TRANSLATE_NOOP("Constant", "Title"),
315
322
  nwOutline.LEVEL: QT_TRANSLATE_NOOP("Constant", "Level"),
316
323
  nwOutline.LABEL: QT_TRANSLATE_NOOP("Constant", "Document"),
@@ -332,7 +339,7 @@ class nwLabels:
332
339
  nwOutline.MENTION: KEY_NAME[nwKeyWords.MENTION_KEY],
333
340
  nwOutline.SYNOP: QT_TRANSLATE_NOOP("Constant", "Synopsis"),
334
341
  }
335
- STATS_NAME = {
342
+ STATS_NAME: Final[dict[str, str]] = {
336
343
  nwStats.CHARS: QT_TRANSLATE_NOOP("Stats", "Characters"),
337
344
  nwStats.CHARS_TEXT: QT_TRANSLATE_NOOP("Stats", "Characters in Text"),
338
345
  nwStats.CHARS_TITLE: QT_TRANSLATE_NOOP("Stats", "Characters in Headings"),
@@ -345,7 +352,7 @@ class nwLabels:
345
352
  nwStats.WORDS_TEXT: QT_TRANSLATE_NOOP("Stats", "Words in Text"),
346
353
  nwStats.WORDS_TITLE: QT_TRANSLATE_NOOP("Stats", "Words in Headings"),
347
354
  }
348
- BUILD_FMT = {
355
+ BUILD_FMT: Final[dict[nwBuildFmt, str]] = {
349
356
  nwBuildFmt.ODT: QT_TRANSLATE_NOOP("Constant", "Open Document (.odt)"),
350
357
  nwBuildFmt.FODT: QT_TRANSLATE_NOOP("Constant", "Flat Open Document (.fodt)"),
351
358
  nwBuildFmt.DOCX: QT_TRANSLATE_NOOP("Constant", "Microsoft Word Document (.docx)"),
@@ -357,7 +364,7 @@ class nwLabels:
357
364
  nwBuildFmt.J_HTML: QT_TRANSLATE_NOOP("Constant", "JSON + HTML 5 (.json)"),
358
365
  nwBuildFmt.J_NWD: QT_TRANSLATE_NOOP("Constant", "JSON + novelWriter Markup (.json)"),
359
366
  }
360
- BUILD_EXT = {
367
+ BUILD_EXT: Final[dict[nwBuildFmt, str]] = {
361
368
  nwBuildFmt.ODT: ".odt",
362
369
  nwBuildFmt.FODT: ".fodt",
363
370
  nwBuildFmt.DOCX: ".docx",
@@ -369,52 +376,52 @@ class nwLabels:
369
376
  nwBuildFmt.J_HTML: ".json",
370
377
  nwBuildFmt.J_NWD: ".json",
371
378
  }
372
- SHAPES_PLAIN = {
373
- nwStatusShape.SQUARE: QT_TRANSLATE_NOOP("Shape", "Square"),
374
- nwStatusShape.TRIANGLE: QT_TRANSLATE_NOOP("Shape", "Triangle"),
375
- nwStatusShape.NABLA: QT_TRANSLATE_NOOP("Shape", "Nabla"),
376
- nwStatusShape.DIAMOND: QT_TRANSLATE_NOOP("Shape", "Diamond"),
377
- nwStatusShape.PENTAGON: QT_TRANSLATE_NOOP("Shape", "Pentagon"),
378
- nwStatusShape.HEXAGON: QT_TRANSLATE_NOOP("Shape", "Hexagon"),
379
- nwStatusShape.STAR: QT_TRANSLATE_NOOP("Shape", "Star"),
380
- nwStatusShape.PACMAN: QT_TRANSLATE_NOOP("Shape", "Pacman"),
379
+ SHAPES_PLAIN: Final[dict[nwStatusShape, str]] = {
380
+ nwStatusShape.SQUARE: QT_TRANSLATE_NOOP("Constant", "Square"),
381
+ nwStatusShape.TRIANGLE: QT_TRANSLATE_NOOP("Constant", "Triangle"),
382
+ nwStatusShape.NABLA: QT_TRANSLATE_NOOP("Constant", "Nabla"),
383
+ nwStatusShape.DIAMOND: QT_TRANSLATE_NOOP("Constant", "Diamond"),
384
+ nwStatusShape.PENTAGON: QT_TRANSLATE_NOOP("Constant", "Pentagon"),
385
+ nwStatusShape.HEXAGON: QT_TRANSLATE_NOOP("Constant", "Hexagon"),
386
+ nwStatusShape.STAR: QT_TRANSLATE_NOOP("Constant", "Star"),
387
+ nwStatusShape.PACMAN: QT_TRANSLATE_NOOP("Constant", "Pacman"),
381
388
  }
382
- SHAPES_CIRCLE = {
383
- nwStatusShape.CIRCLE_Q: QT_TRANSLATE_NOOP("Shape", "1/4 Circle"),
384
- nwStatusShape.CIRCLE_H: QT_TRANSLATE_NOOP("Shape", "Half Circle"),
385
- nwStatusShape.CIRCLE_T: QT_TRANSLATE_NOOP("Shape", "3/4 Circle"),
386
- nwStatusShape.CIRCLE: QT_TRANSLATE_NOOP("Shape", "Full Circle"),
389
+ SHAPES_CIRCLE: Final[dict[nwStatusShape, str]] = {
390
+ nwStatusShape.CIRCLE_Q: QT_TRANSLATE_NOOP("Constant", "1/4 Circle"),
391
+ nwStatusShape.CIRCLE_H: QT_TRANSLATE_NOOP("Constant", "Half Circle"),
392
+ nwStatusShape.CIRCLE_T: QT_TRANSLATE_NOOP("Constant", "3/4 Circle"),
393
+ nwStatusShape.CIRCLE: QT_TRANSLATE_NOOP("Constant", "Full Circle"),
387
394
  }
388
- SHAPES_BARS = {
389
- nwStatusShape.BARS_1: QT_TRANSLATE_NOOP("Shape", "1 Bar"),
390
- nwStatusShape.BARS_2: QT_TRANSLATE_NOOP("Shape", "2 Bars"),
391
- nwStatusShape.BARS_3: QT_TRANSLATE_NOOP("Shape", "3 Bars"),
392
- nwStatusShape.BARS_4: QT_TRANSLATE_NOOP("Shape", "4 Bars"),
395
+ SHAPES_BARS: Final[dict[nwStatusShape, str]] = {
396
+ nwStatusShape.BARS_1: QT_TRANSLATE_NOOP("Constant", "1 Bar"),
397
+ nwStatusShape.BARS_2: QT_TRANSLATE_NOOP("Constant", "2 Bars"),
398
+ nwStatusShape.BARS_3: QT_TRANSLATE_NOOP("Constant", "3 Bars"),
399
+ nwStatusShape.BARS_4: QT_TRANSLATE_NOOP("Constant", "4 Bars"),
393
400
  }
394
- SHAPES_BLOCKS = {
395
- nwStatusShape.BLOCK_1: QT_TRANSLATE_NOOP("Shape", "1 Block"),
396
- nwStatusShape.BLOCK_2: QT_TRANSLATE_NOOP("Shape", "2 Blocks"),
397
- nwStatusShape.BLOCK_3: QT_TRANSLATE_NOOP("Shape", "3 Blocks"),
398
- nwStatusShape.BLOCK_4: QT_TRANSLATE_NOOP("Shape", "4 Blocks"),
401
+ SHAPES_BLOCKS: Final[dict[nwStatusShape, str]] = {
402
+ nwStatusShape.BLOCK_1: QT_TRANSLATE_NOOP("Constant", "1 Block"),
403
+ nwStatusShape.BLOCK_2: QT_TRANSLATE_NOOP("Constant", "2 Blocks"),
404
+ nwStatusShape.BLOCK_3: QT_TRANSLATE_NOOP("Constant", "3 Blocks"),
405
+ nwStatusShape.BLOCK_4: QT_TRANSLATE_NOOP("Constant", "4 Blocks"),
399
406
  }
400
- FILE_FILTERS = {
407
+ FILE_FILTERS: Final[dict[str, str]] = {
401
408
  "*.txt": QT_TRANSLATE_NOOP("Constant", "Text files"),
402
409
  "*.md": QT_TRANSLATE_NOOP("Constant", "Markdown files"),
403
410
  "*.nwd": QT_TRANSLATE_NOOP("Constant", "novelWriter files"),
404
411
  "*.csv": QT_TRANSLATE_NOOP("Constant", "CSV files"),
405
412
  "*": QT_TRANSLATE_NOOP("Constant", "All files"),
406
413
  }
407
- UNIT_NAME = {
414
+ UNIT_NAME: Final[dict[str, str]] = {
408
415
  "mm": QT_TRANSLATE_NOOP("Constant", "Millimetres"),
409
416
  "cm": QT_TRANSLATE_NOOP("Constant", "Centimetres"),
410
417
  "in": QT_TRANSLATE_NOOP("Constant", "Inches"),
411
418
  }
412
- UNIT_SCALE = {
419
+ UNIT_SCALE: Final[dict[str, float]] = {
413
420
  "mm": 1.0,
414
421
  "cm": 10.0,
415
422
  "in": 25.4,
416
423
  }
417
- PAPER_NAME = {
424
+ PAPER_NAME: Final[dict[str, str]] = {
418
425
  "A4": QT_TRANSLATE_NOOP("Constant", "A4"),
419
426
  "A5": QT_TRANSLATE_NOOP("Constant", "A5"),
420
427
  "A6": QT_TRANSLATE_NOOP("Constant", "A6"),
@@ -422,7 +429,7 @@ class nwLabels:
422
429
  "Letter": QT_TRANSLATE_NOOP("Constant", "US Letter"),
423
430
  "Custom": QT_TRANSLATE_NOOP("Constant", "Custom"),
424
431
  }
425
- PAPER_SIZE = {
432
+ PAPER_SIZE: Final[dict[str, tuple[float, float]]] = {
426
433
  "A4": (210.0, 297.0),
427
434
  "A5": (148.0, 210.0),
428
435
  "A6": (105.0, 148.0),
@@ -430,6 +437,18 @@ class nwLabels:
430
437
  "Letter": (215.9, 279.4),
431
438
  "Custom": (-1.0, -1.0),
432
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
+ }
433
452
 
434
453
 
435
454
  class nwHeadFmt:
@@ -445,7 +464,7 @@ class nwHeadFmt:
445
464
  CHAR_POV = "{Char:POV}"
446
465
  CHAR_FOCUS = "{Char:Focus}"
447
466
 
448
- PAGE_HEADERS = [
467
+ PAGE_HEADERS: Final[list[str]] = [
449
468
  TITLE, CH_NUM, CH_WORD, CH_ROMU, CH_ROML, SC_NUM, SC_ABS,
450
469
  CHAR_POV, CHAR_FOCUS
451
470
  ]
@@ -461,7 +480,7 @@ class nwQuotes:
461
480
  """Allowed quotation marks.
462
481
  Source: https://en.wikipedia.org/wiki/Quotation_mark
463
482
  """
464
- SYMBOLS = {
483
+ SYMBOLS: Final[dict[str, str]] = {
465
484
  "\u0027": QT_TRANSLATE_NOOP("Constant", "Straight single quotation mark"),
466
485
  "\u0022": QT_TRANSLATE_NOOP("Constant", "Straight double quotation mark"),
467
486
 
@@ -626,9 +645,9 @@ class nwUnicode:
626
645
  H_LTRIS = "&#9666;"
627
646
 
628
647
 
629
- class nwHtmlUnicode():
648
+ class nwHtmlUnicode:
630
649
 
631
- U_TO_H = {
650
+ U_TO_H: Final[dict[str, str]] = {
632
651
  # Quotes
633
652
  nwUnicode.U_QUOT: nwUnicode.H_QUOT,
634
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__)