novelWriter 2.6.3__py3-none-any.whl → 2.7__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 (348) hide show
  1. novelwriter/__init__.py +98 -75
  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_de_DE.json +3 -1
  16. novelwriter/assets/i18n/project_en_GB.json +2 -0
  17. novelwriter/assets/i18n/project_en_US.json +2 -0
  18. novelwriter/assets/i18n/project_it_IT.json +2 -0
  19. novelwriter/assets/i18n/project_ja_JP.json +2 -0
  20. novelwriter/assets/i18n/project_nb_NO.json +2 -0
  21. novelwriter/assets/i18n/project_nn_NO.json +5 -0
  22. novelwriter/assets/i18n/project_pl_PL.json +2 -0
  23. novelwriter/assets/i18n/project_pt_BR.json +2 -0
  24. novelwriter/assets/i18n/project_ru_RU.json +2 -0
  25. novelwriter/assets/i18n/project_zh_CN.json +2 -0
  26. novelwriter/assets/icons/font_awesome.icons +109 -0
  27. novelwriter/assets/icons/material_filled_bold.icons +109 -0
  28. novelwriter/assets/icons/material_filled_normal.icons +109 -0
  29. novelwriter/assets/icons/material_filled_thin.icons +109 -0
  30. novelwriter/assets/icons/material_rounded_bold.icons +109 -0
  31. novelwriter/assets/icons/material_rounded_normal.icons +109 -0
  32. novelwriter/assets/icons/material_rounded_thin.icons +109 -0
  33. novelwriter/assets/icons/remix_filled.icons +109 -0
  34. novelwriter/assets/icons/remix_outline.icons +109 -0
  35. novelwriter/assets/images/splash.png +0 -0
  36. novelwriter/assets/manual.pdf +0 -0
  37. novelwriter/assets/{manual_fr_FR.pdf → manual_fr.pdf} +0 -0
  38. novelwriter/assets/sample.zip +0 -0
  39. novelwriter/assets/syntax/cyberpunk_night.conf +1 -1
  40. novelwriter/assets/syntax/snazzy.conf +3 -3
  41. novelwriter/assets/text/credits_en.htm +12 -6
  42. novelwriter/assets/themes/cyberpunk_night.conf +23 -7
  43. novelwriter/assets/themes/default_dark.conf +20 -4
  44. novelwriter/assets/themes/default_light.conf +21 -5
  45. novelwriter/assets/themes/dracula.conf +20 -4
  46. novelwriter/assets/themes/snazzy.conf +48 -0
  47. novelwriter/assets/themes/solarized_dark.conf +24 -8
  48. novelwriter/assets/themes/solarized_light.conf +22 -6
  49. novelwriter/common.py +43 -27
  50. novelwriter/config.py +201 -139
  51. novelwriter/constants.py +67 -36
  52. novelwriter/core/buildsettings.py +26 -17
  53. novelwriter/core/coretools.py +52 -41
  54. novelwriter/core/docbuild.py +20 -13
  55. novelwriter/core/document.py +2 -2
  56. novelwriter/core/index.py +166 -432
  57. novelwriter/core/indexdata.py +406 -0
  58. novelwriter/core/item.py +50 -32
  59. novelwriter/core/itemmodel.py +43 -38
  60. novelwriter/core/novelmodel.py +225 -0
  61. novelwriter/core/options.py +1 -1
  62. novelwriter/core/project.py +24 -25
  63. novelwriter/core/projectdata.py +47 -29
  64. novelwriter/core/projectxml.py +18 -8
  65. novelwriter/core/sessions.py +32 -15
  66. novelwriter/core/spellcheck.py +4 -3
  67. novelwriter/core/status.py +12 -15
  68. novelwriter/core/storage.py +1 -1
  69. novelwriter/core/tree.py +55 -13
  70. novelwriter/dialogs/about.py +19 -22
  71. novelwriter/dialogs/docmerge.py +23 -24
  72. novelwriter/dialogs/docsplit.py +26 -26
  73. novelwriter/dialogs/editlabel.py +19 -20
  74. novelwriter/dialogs/preferences.py +143 -69
  75. novelwriter/dialogs/projectsettings.py +51 -54
  76. novelwriter/dialogs/quotes.py +14 -19
  77. novelwriter/dialogs/wordlist.py +25 -30
  78. novelwriter/enum.py +8 -0
  79. novelwriter/error.py +16 -16
  80. novelwriter/extensions/configlayout.py +24 -20
  81. novelwriter/extensions/eventfilters.py +9 -5
  82. novelwriter/extensions/modified.py +34 -15
  83. novelwriter/extensions/novelselector.py +18 -5
  84. novelwriter/extensions/pagedsidebar.py +39 -49
  85. novelwriter/extensions/progressbars.py +10 -8
  86. novelwriter/extensions/statusled.py +6 -13
  87. novelwriter/extensions/switch.py +31 -41
  88. novelwriter/extensions/switchbox.py +8 -3
  89. novelwriter/extensions/versioninfo.py +4 -4
  90. novelwriter/formats/shared.py +1 -1
  91. novelwriter/formats/todocx.py +14 -10
  92. novelwriter/formats/tohtml.py +7 -5
  93. novelwriter/formats/tokenizer.py +37 -33
  94. novelwriter/formats/tomarkdown.py +6 -2
  95. novelwriter/formats/toodt.py +27 -22
  96. novelwriter/formats/toqdoc.py +19 -14
  97. novelwriter/formats/toraw.py +6 -2
  98. novelwriter/gui/doceditor.py +314 -305
  99. novelwriter/gui/dochighlight.py +46 -45
  100. novelwriter/gui/docviewer.py +102 -104
  101. novelwriter/gui/docviewerpanel.py +47 -51
  102. novelwriter/gui/editordocument.py +8 -5
  103. novelwriter/gui/itemdetails.py +11 -14
  104. novelwriter/gui/mainmenu.py +146 -145
  105. novelwriter/gui/noveltree.py +246 -406
  106. novelwriter/gui/outline.py +141 -72
  107. novelwriter/gui/projtree.py +139 -132
  108. novelwriter/gui/search.py +34 -31
  109. novelwriter/gui/sidebar.py +13 -18
  110. novelwriter/gui/statusbar.py +27 -21
  111. novelwriter/gui/theme.py +554 -436
  112. novelwriter/guimain.py +56 -38
  113. novelwriter/shared.py +32 -23
  114. novelwriter/splash.py +74 -0
  115. novelwriter/text/comments.py +70 -0
  116. novelwriter/text/patterns.py +4 -4
  117. novelwriter/tools/dictionaries.py +20 -29
  118. novelwriter/tools/lipsum.py +18 -18
  119. novelwriter/tools/manusbuild.py +39 -42
  120. novelwriter/tools/manuscript.py +102 -115
  121. novelwriter/tools/manussettings.py +129 -102
  122. novelwriter/tools/noveldetails.py +60 -72
  123. novelwriter/tools/welcome.py +57 -75
  124. novelwriter/tools/writingstats.py +112 -102
  125. novelwriter/types.py +5 -7
  126. {novelWriter-2.6.3.dist-info → novelwriter-2.7.dist-info}/METADATA +6 -6
  127. novelwriter-2.7.dist-info/RECORD +162 -0
  128. {novelWriter-2.6.3.dist-info → novelwriter-2.7.dist-info}/WHEEL +1 -1
  129. novelWriter-2.6.3.dist-info/RECORD +0 -363
  130. novelwriter/assets/icons/typicons_dark/README.md +0 -29
  131. novelwriter/assets/icons/typicons_dark/icons.conf +0 -134
  132. novelwriter/assets/icons/typicons_dark/mixed_copy.svg +0 -4
  133. novelwriter/assets/icons/typicons_dark/mixed_document-chapter.svg +0 -12
  134. novelwriter/assets/icons/typicons_dark/mixed_document-new.svg +0 -6
  135. novelwriter/assets/icons/typicons_dark/mixed_document-note.svg +0 -12
  136. novelwriter/assets/icons/typicons_dark/mixed_document-scene.svg +0 -12
  137. novelwriter/assets/icons/typicons_dark/mixed_document-section.svg +0 -12
  138. novelwriter/assets/icons/typicons_dark/mixed_document-title.svg +0 -12
  139. novelwriter/assets/icons/typicons_dark/mixed_edit.svg +0 -4
  140. novelwriter/assets/icons/typicons_dark/mixed_import.svg +0 -5
  141. novelwriter/assets/icons/typicons_dark/mixed_input-checked.svg +0 -5
  142. novelwriter/assets/icons/typicons_dark/mixed_input-none.svg +0 -5
  143. novelwriter/assets/icons/typicons_dark/mixed_input-unchecked.svg +0 -5
  144. novelwriter/assets/icons/typicons_dark/mixed_margin-bottom.svg +0 -6
  145. novelwriter/assets/icons/typicons_dark/mixed_margin-left.svg +0 -6
  146. novelwriter/assets/icons/typicons_dark/mixed_margin-right.svg +0 -6
  147. novelwriter/assets/icons/typicons_dark/mixed_margin-top.svg +0 -6
  148. novelwriter/assets/icons/typicons_dark/mixed_search-replace.svg +0 -6
  149. novelwriter/assets/icons/typicons_dark/mixed_size-height.svg +0 -6
  150. novelwriter/assets/icons/typicons_dark/mixed_size-width.svg +0 -6
  151. novelwriter/assets/icons/typicons_dark/nw_deco-h0.svg +0 -4
  152. novelwriter/assets/icons/typicons_dark/nw_deco-h1.svg +0 -4
  153. novelwriter/assets/icons/typicons_dark/nw_deco-h2-narrow.svg +0 -4
  154. novelwriter/assets/icons/typicons_dark/nw_deco-h2.svg +0 -4
  155. novelwriter/assets/icons/typicons_dark/nw_deco-h3-narrow.svg +0 -4
  156. novelwriter/assets/icons/typicons_dark/nw_deco-h3.svg +0 -4
  157. novelwriter/assets/icons/typicons_dark/nw_deco-h4-narrow.svg +0 -4
  158. novelwriter/assets/icons/typicons_dark/nw_deco-h4.svg +0 -4
  159. novelwriter/assets/icons/typicons_dark/nw_deco-note.svg +0 -4
  160. novelwriter/assets/icons/typicons_dark/nw_deco-noveltree-more.svg +0 -4
  161. novelwriter/assets/icons/typicons_dark/nw_font.svg +0 -4
  162. novelwriter/assets/icons/typicons_dark/nw_panel.svg +0 -4
  163. novelwriter/assets/icons/typicons_dark/nw_quote.svg +0 -4
  164. novelwriter/assets/icons/typicons_dark/nw_search-case.svg +0 -4
  165. novelwriter/assets/icons/typicons_dark/nw_search-preserve.svg +0 -4
  166. novelwriter/assets/icons/typicons_dark/nw_search-regex.svg +0 -4
  167. novelwriter/assets/icons/typicons_dark/nw_search-word.svg +0 -4
  168. novelwriter/assets/icons/typicons_dark/nw_tb-bold-md.svg +0 -4
  169. novelwriter/assets/icons/typicons_dark/nw_tb-bold.svg +0 -6
  170. novelwriter/assets/icons/typicons_dark/nw_tb-italic-md.svg +0 -4
  171. novelwriter/assets/icons/typicons_dark/nw_tb-italic.svg +0 -6
  172. novelwriter/assets/icons/typicons_dark/nw_tb-mark.svg +0 -7
  173. novelwriter/assets/icons/typicons_dark/nw_tb-strike-md.svg +0 -4
  174. novelwriter/assets/icons/typicons_dark/nw_tb-strike.svg +0 -6
  175. novelwriter/assets/icons/typicons_dark/nw_tb-subscript.svg +0 -7
  176. novelwriter/assets/icons/typicons_dark/nw_tb-superscript.svg +0 -7
  177. novelwriter/assets/icons/typicons_dark/nw_tb-underline.svg +0 -7
  178. novelwriter/assets/icons/typicons_dark/nw_toolbar.svg +0 -5
  179. novelwriter/assets/icons/typicons_dark/typ_arrow-down-thick-grey.svg +0 -4
  180. novelwriter/assets/icons/typicons_dark/typ_arrow-forward.svg +0 -4
  181. novelwriter/assets/icons/typicons_dark/typ_arrow-maximise.svg +0 -4
  182. novelwriter/assets/icons/typicons_dark/typ_arrow-minimise.svg +0 -4
  183. novelwriter/assets/icons/typicons_dark/typ_arrow-repeat-grey.svg +0 -4
  184. novelwriter/assets/icons/typicons_dark/typ_book-grey.svg +0 -4
  185. novelwriter/assets/icons/typicons_dark/typ_book.svg +0 -6
  186. novelwriter/assets/icons/typicons_dark/typ_bookmark.svg +0 -4
  187. novelwriter/assets/icons/typicons_dark/typ_calendar.svg +0 -4
  188. novelwriter/assets/icons/typicons_dark/typ_cancel-grey.svg +0 -4
  189. novelwriter/assets/icons/typicons_dark/typ_cancel.svg +0 -4
  190. novelwriter/assets/icons/typicons_dark/typ_chart-bar-grey.svg +0 -4
  191. novelwriter/assets/icons/typicons_dark/typ_chevron-down.svg +0 -4
  192. novelwriter/assets/icons/typicons_dark/typ_chevron-left.svg +0 -4
  193. novelwriter/assets/icons/typicons_dark/typ_chevron-right.svg +0 -4
  194. novelwriter/assets/icons/typicons_dark/typ_chevron-up.svg +0 -4
  195. novelwriter/assets/icons/typicons_dark/typ_cog.svg +0 -4
  196. novelwriter/assets/icons/typicons_dark/typ_delete-full.svg +0 -4
  197. novelwriter/assets/icons/typicons_dark/typ_delete.svg +0 -4
  198. novelwriter/assets/icons/typicons_dark/typ_directions-full.svg +0 -4
  199. novelwriter/assets/icons/typicons_dark/typ_document-add.svg +0 -4
  200. novelwriter/assets/icons/typicons_dark/typ_document-text.svg +0 -8
  201. novelwriter/assets/icons/typicons_dark/typ_document.svg +0 -4
  202. novelwriter/assets/icons/typicons_dark/typ_export-grey.svg +0 -4
  203. novelwriter/assets/icons/typicons_dark/typ_export.svg +0 -4
  204. novelwriter/assets/icons/typicons_dark/typ_eye.svg +0 -4
  205. novelwriter/assets/icons/typicons_dark/typ_flag.svg +0 -4
  206. novelwriter/assets/icons/typicons_dark/typ_folder-open.svg +0 -4
  207. novelwriter/assets/icons/typicons_dark/typ_folder.svg +0 -5
  208. novelwriter/assets/icons/typicons_dark/typ_globe-grey.svg +0 -4
  209. novelwriter/assets/icons/typicons_dark/typ_key.svg +0 -4
  210. novelwriter/assets/icons/typicons_dark/typ_lightbulb-full.svg +0 -4
  211. novelwriter/assets/icons/typicons_dark/typ_location.svg +0 -4
  212. novelwriter/assets/icons/typicons_dark/typ_media-pause-grey.svg +0 -4
  213. novelwriter/assets/icons/typicons_dark/typ_media-record-outline.svg +0 -4
  214. novelwriter/assets/icons/typicons_dark/typ_media-record.svg +0 -4
  215. novelwriter/assets/icons/typicons_dark/typ_minus.svg +0 -4
  216. novelwriter/assets/icons/typicons_dark/typ_pencil.svg +0 -5
  217. novelwriter/assets/icons/typicons_dark/typ_pin-outline.svg +0 -4
  218. novelwriter/assets/icons/typicons_dark/typ_pin.svg +0 -4
  219. novelwriter/assets/icons/typicons_dark/typ_plus.svg +0 -4
  220. novelwriter/assets/icons/typicons_dark/typ_puzzle-outline.svg +0 -4
  221. novelwriter/assets/icons/typicons_dark/typ_puzzle.svg +0 -4
  222. novelwriter/assets/icons/typicons_dark/typ_refresh-flipped.svg +0 -4
  223. novelwriter/assets/icons/typicons_dark/typ_refresh.svg +0 -4
  224. novelwriter/assets/icons/typicons_dark/typ_search-grey.svg +0 -4
  225. novelwriter/assets/icons/typicons_dark/typ_search.svg +0 -4
  226. novelwriter/assets/icons/typicons_dark/typ_star.svg +0 -4
  227. novelwriter/assets/icons/typicons_dark/typ_stopwatch-grey.svg +0 -4
  228. novelwriter/assets/icons/typicons_dark/typ_th-dot-menu.svg +0 -4
  229. novelwriter/assets/icons/typicons_dark/typ_th-dot-more.svg +0 -4
  230. novelwriter/assets/icons/typicons_dark/typ_th-list-grey.svg +0 -4
  231. novelwriter/assets/icons/typicons_dark/typ_th-list.svg +0 -9
  232. novelwriter/assets/icons/typicons_dark/typ_times.svg +0 -4
  233. novelwriter/assets/icons/typicons_dark/typ_trash.svg +0 -5
  234. novelwriter/assets/icons/typicons_dark/typ_unfold-hidden.svg +0 -4
  235. novelwriter/assets/icons/typicons_dark/typ_unfold-visible.svg +0 -4
  236. novelwriter/assets/icons/typicons_dark/typ_user.svg +0 -5
  237. novelwriter/assets/icons/typicons_dark/typ_warning-full.svg +0 -4
  238. novelwriter/assets/icons/typicons_light/README.md +0 -29
  239. novelwriter/assets/icons/typicons_light/icons.conf +0 -134
  240. novelwriter/assets/icons/typicons_light/mixed_copy.svg +0 -4
  241. novelwriter/assets/icons/typicons_light/mixed_document-chapter.svg +0 -12
  242. novelwriter/assets/icons/typicons_light/mixed_document-new.svg +0 -6
  243. novelwriter/assets/icons/typicons_light/mixed_document-note.svg +0 -12
  244. novelwriter/assets/icons/typicons_light/mixed_document-scene.svg +0 -12
  245. novelwriter/assets/icons/typicons_light/mixed_document-section.svg +0 -12
  246. novelwriter/assets/icons/typicons_light/mixed_document-title.svg +0 -12
  247. novelwriter/assets/icons/typicons_light/mixed_edit.svg +0 -4
  248. novelwriter/assets/icons/typicons_light/mixed_import.svg +0 -5
  249. novelwriter/assets/icons/typicons_light/mixed_input-checked.svg +0 -5
  250. novelwriter/assets/icons/typicons_light/mixed_input-none.svg +0 -5
  251. novelwriter/assets/icons/typicons_light/mixed_input-unchecked.svg +0 -5
  252. novelwriter/assets/icons/typicons_light/mixed_margin-bottom.svg +0 -6
  253. novelwriter/assets/icons/typicons_light/mixed_margin-left.svg +0 -6
  254. novelwriter/assets/icons/typicons_light/mixed_margin-right.svg +0 -6
  255. novelwriter/assets/icons/typicons_light/mixed_margin-top.svg +0 -6
  256. novelwriter/assets/icons/typicons_light/mixed_search-replace.svg +0 -6
  257. novelwriter/assets/icons/typicons_light/mixed_size-height.svg +0 -6
  258. novelwriter/assets/icons/typicons_light/mixed_size-width.svg +0 -6
  259. novelwriter/assets/icons/typicons_light/nw_deco-h0.svg +0 -4
  260. novelwriter/assets/icons/typicons_light/nw_deco-h1.svg +0 -4
  261. novelwriter/assets/icons/typicons_light/nw_deco-h2-narrow.svg +0 -4
  262. novelwriter/assets/icons/typicons_light/nw_deco-h2.svg +0 -4
  263. novelwriter/assets/icons/typicons_light/nw_deco-h3-narrow.svg +0 -4
  264. novelwriter/assets/icons/typicons_light/nw_deco-h3.svg +0 -4
  265. novelwriter/assets/icons/typicons_light/nw_deco-h4-narrow.svg +0 -4
  266. novelwriter/assets/icons/typicons_light/nw_deco-h4.svg +0 -4
  267. novelwriter/assets/icons/typicons_light/nw_deco-note.svg +0 -4
  268. novelwriter/assets/icons/typicons_light/nw_deco-noveltree-more.svg +0 -4
  269. novelwriter/assets/icons/typicons_light/nw_font.svg +0 -4
  270. novelwriter/assets/icons/typicons_light/nw_panel.svg +0 -4
  271. novelwriter/assets/icons/typicons_light/nw_quote.svg +0 -4
  272. novelwriter/assets/icons/typicons_light/nw_search-case.svg +0 -4
  273. novelwriter/assets/icons/typicons_light/nw_search-preserve.svg +0 -4
  274. novelwriter/assets/icons/typicons_light/nw_search-regex.svg +0 -4
  275. novelwriter/assets/icons/typicons_light/nw_search-word.svg +0 -4
  276. novelwriter/assets/icons/typicons_light/nw_tb-bold-md.svg +0 -4
  277. novelwriter/assets/icons/typicons_light/nw_tb-bold.svg +0 -6
  278. novelwriter/assets/icons/typicons_light/nw_tb-italic-md.svg +0 -4
  279. novelwriter/assets/icons/typicons_light/nw_tb-italic.svg +0 -6
  280. novelwriter/assets/icons/typicons_light/nw_tb-mark.svg +0 -7
  281. novelwriter/assets/icons/typicons_light/nw_tb-strike-md.svg +0 -4
  282. novelwriter/assets/icons/typicons_light/nw_tb-strike.svg +0 -6
  283. novelwriter/assets/icons/typicons_light/nw_tb-subscript.svg +0 -7
  284. novelwriter/assets/icons/typicons_light/nw_tb-superscript.svg +0 -7
  285. novelwriter/assets/icons/typicons_light/nw_tb-underline.svg +0 -7
  286. novelwriter/assets/icons/typicons_light/nw_toolbar.svg +0 -5
  287. novelwriter/assets/icons/typicons_light/typ_arrow-down-thick-grey.svg +0 -4
  288. novelwriter/assets/icons/typicons_light/typ_arrow-forward.svg +0 -4
  289. novelwriter/assets/icons/typicons_light/typ_arrow-maximise.svg +0 -4
  290. novelwriter/assets/icons/typicons_light/typ_arrow-minimise.svg +0 -4
  291. novelwriter/assets/icons/typicons_light/typ_arrow-repeat-grey.svg +0 -4
  292. novelwriter/assets/icons/typicons_light/typ_book-grey.svg +0 -4
  293. novelwriter/assets/icons/typicons_light/typ_book.svg +0 -6
  294. novelwriter/assets/icons/typicons_light/typ_bookmark.svg +0 -4
  295. novelwriter/assets/icons/typicons_light/typ_calendar.svg +0 -4
  296. novelwriter/assets/icons/typicons_light/typ_cancel-grey.svg +0 -4
  297. novelwriter/assets/icons/typicons_light/typ_cancel.svg +0 -4
  298. novelwriter/assets/icons/typicons_light/typ_chart-bar-grey.svg +0 -4
  299. novelwriter/assets/icons/typicons_light/typ_chevron-down.svg +0 -4
  300. novelwriter/assets/icons/typicons_light/typ_chevron-left.svg +0 -4
  301. novelwriter/assets/icons/typicons_light/typ_chevron-right.svg +0 -4
  302. novelwriter/assets/icons/typicons_light/typ_chevron-up.svg +0 -4
  303. novelwriter/assets/icons/typicons_light/typ_cog.svg +0 -4
  304. novelwriter/assets/icons/typicons_light/typ_delete-full.svg +0 -4
  305. novelwriter/assets/icons/typicons_light/typ_delete.svg +0 -4
  306. novelwriter/assets/icons/typicons_light/typ_directions-full.svg +0 -4
  307. novelwriter/assets/icons/typicons_light/typ_document-add.svg +0 -4
  308. novelwriter/assets/icons/typicons_light/typ_document-text.svg +0 -5
  309. novelwriter/assets/icons/typicons_light/typ_document.svg +0 -4
  310. novelwriter/assets/icons/typicons_light/typ_export-grey.svg +0 -4
  311. novelwriter/assets/icons/typicons_light/typ_export.svg +0 -4
  312. novelwriter/assets/icons/typicons_light/typ_eye.svg +0 -4
  313. novelwriter/assets/icons/typicons_light/typ_flag.svg +0 -4
  314. novelwriter/assets/icons/typicons_light/typ_folder-open.svg +0 -4
  315. novelwriter/assets/icons/typicons_light/typ_folder.svg +0 -5
  316. novelwriter/assets/icons/typicons_light/typ_globe-grey.svg +0 -4
  317. novelwriter/assets/icons/typicons_light/typ_key.svg +0 -4
  318. novelwriter/assets/icons/typicons_light/typ_lightbulb-full.svg +0 -4
  319. novelwriter/assets/icons/typicons_light/typ_location.svg +0 -4
  320. novelwriter/assets/icons/typicons_light/typ_media-pause-grey.svg +0 -4
  321. novelwriter/assets/icons/typicons_light/typ_media-record-outline.svg +0 -4
  322. novelwriter/assets/icons/typicons_light/typ_media-record.svg +0 -4
  323. novelwriter/assets/icons/typicons_light/typ_minus.svg +0 -4
  324. novelwriter/assets/icons/typicons_light/typ_pencil.svg +0 -5
  325. novelwriter/assets/icons/typicons_light/typ_pin-outline.svg +0 -4
  326. novelwriter/assets/icons/typicons_light/typ_pin.svg +0 -4
  327. novelwriter/assets/icons/typicons_light/typ_plus.svg +0 -4
  328. novelwriter/assets/icons/typicons_light/typ_puzzle-outline.svg +0 -4
  329. novelwriter/assets/icons/typicons_light/typ_puzzle.svg +0 -4
  330. novelwriter/assets/icons/typicons_light/typ_refresh-flipped.svg +0 -4
  331. novelwriter/assets/icons/typicons_light/typ_refresh.svg +0 -4
  332. novelwriter/assets/icons/typicons_light/typ_search-grey.svg +0 -4
  333. novelwriter/assets/icons/typicons_light/typ_search.svg +0 -4
  334. novelwriter/assets/icons/typicons_light/typ_star.svg +0 -4
  335. novelwriter/assets/icons/typicons_light/typ_stopwatch-grey.svg +0 -4
  336. novelwriter/assets/icons/typicons_light/typ_th-dot-menu.svg +0 -4
  337. novelwriter/assets/icons/typicons_light/typ_th-dot-more.svg +0 -4
  338. novelwriter/assets/icons/typicons_light/typ_th-list-grey.svg +0 -4
  339. novelwriter/assets/icons/typicons_light/typ_th-list.svg +0 -9
  340. novelwriter/assets/icons/typicons_light/typ_times.svg +0 -4
  341. novelwriter/assets/icons/typicons_light/typ_trash.svg +0 -5
  342. novelwriter/assets/icons/typicons_light/typ_unfold-hidden.svg +0 -4
  343. novelwriter/assets/icons/typicons_light/typ_unfold-visible.svg +0 -4
  344. novelwriter/assets/icons/typicons_light/typ_user.svg +0 -5
  345. novelwriter/assets/icons/typicons_light/typ_warning-full.svg +0 -4
  346. {novelWriter-2.6.3.dist-info → novelwriter-2.7.dist-info}/entry_points.txt +0 -0
  347. {novelWriter-2.6.3.dist-info → novelwriter-2.7.dist-info/licenses}/LICENSE.md +0 -0
  348. {novelWriter-2.6.3.dist-info → novelwriter-2.7.dist-info}/top_level.txt +0 -0
novelwriter/common.py CHANGED
@@ -29,23 +29,23 @@ import unicodedata
29
29
  import uuid
30
30
  import xml.etree.ElementTree as ET
31
31
 
32
- from collections.abc import Callable
33
32
  from configparser import ConfigParser
34
33
  from datetime import datetime
35
34
  from pathlib import Path
36
- from typing import TYPE_CHECKING, Any, Literal, TypeVar
35
+ from typing import TYPE_CHECKING, Any, Literal, TypeGuard, TypeVar
37
36
  from urllib.parse import urljoin
38
37
  from urllib.request import pathname2url
39
38
 
40
- from PyQt5.QtCore import QCoreApplication, QMimeData, QUrl
41
- from PyQt5.QtGui import QColor, QDesktopServices, QFont, QFontDatabase, QFontInfo
39
+ from PyQt6.QtCore import QCoreApplication, QMimeData, QUrl
40
+ from PyQt6.QtGui import QAction, QDesktopServices, QFont, QFontDatabase, QFontInfo
41
+ from PyQt6.QtWidgets import QMenu, QMenuBar, QWidget
42
42
 
43
- from novelwriter.constants import nwConst, nwLabels, nwUnicode, trConst
43
+ from novelwriter.constants import nwConst, nwLabels, nwQuotes, nwUnicode, trConst
44
44
  from novelwriter.enum import nwItemClass, nwItemLayout, nwItemType
45
45
  from novelwriter.error import logException
46
46
 
47
- if TYPE_CHECKING: # pragma: no cover
48
- from typing import TypeGuard # Requires Python 3.10
47
+ if TYPE_CHECKING:
48
+ from collections.abc import Callable
49
49
 
50
50
  logger = logging.getLogger(__name__)
51
51
 
@@ -298,6 +298,15 @@ def uniqueCompact(text: str) -> str:
298
298
  return "".join(sorted(set(compact(text))))
299
299
 
300
300
 
301
+ def processDialogSymbols(symbols: str) -> str:
302
+ """Process dialogue line symbols."""
303
+ result = ""
304
+ for c in uniqueCompact(symbols):
305
+ if c in nwQuotes.ALLOWED:
306
+ result += c
307
+ return result
308
+
309
+
301
310
  def elide(text: str, length: int) -> str:
302
311
  """Elide a piece of text to a maximum length."""
303
312
  if len(text) > (cut := max(4, length)):
@@ -349,7 +358,7 @@ def fuzzyTime(seconds: int) -> str:
349
358
  elif seconds < 3300: # 55 minutes
350
359
  return QCoreApplication.translate(
351
360
  "Common", "{0} minutes ago"
352
- ).format(int(round(seconds/60)))
361
+ ).format(round(seconds/60))
353
362
  elif seconds < 5400: # 90 minutes
354
363
  return QCoreApplication.translate(
355
364
  "Common", "an hour ago"
@@ -357,7 +366,7 @@ def fuzzyTime(seconds: int) -> str:
357
366
  elif seconds < 84600: # 23.5 hours
358
367
  return QCoreApplication.translate(
359
368
  "Common", "{0} hours ago"
360
- ).format(int(round(seconds/3600)))
369
+ ).format(round(seconds/3600))
361
370
  elif seconds < 129600: # 1.5 days
362
371
  return QCoreApplication.translate(
363
372
  "Common", "a day ago"
@@ -365,7 +374,7 @@ def fuzzyTime(seconds: int) -> str:
365
374
  elif seconds < 561600: # 6.5 days
366
375
  return QCoreApplication.translate(
367
376
  "Common", "{0} days ago"
368
- ).format(int(round(seconds/86400)))
377
+ ).format(round(seconds/86400))
369
378
  elif seconds < 907200: # 10.5 days
370
379
  return QCoreApplication.translate(
371
380
  "Common", "a week ago"
@@ -373,7 +382,7 @@ def fuzzyTime(seconds: int) -> str:
373
382
  elif seconds < 2419200: # 28 days
374
383
  return QCoreApplication.translate(
375
384
  "Common", "{0} weeks ago"
376
- ).format(int(round(seconds/604800)))
385
+ ).format(round(seconds/604800))
377
386
  elif seconds < 3888000: # 45 days
378
387
  return QCoreApplication.translate(
379
388
  "Common", "a month ago"
@@ -381,7 +390,7 @@ def fuzzyTime(seconds: int) -> str:
381
390
  elif seconds < 29808000: # 345 days
382
391
  return QCoreApplication.translate(
383
392
  "Common", "{0} months ago"
384
- ).format(int(round(seconds/2592000)))
393
+ ).format(round(seconds/2592000))
385
394
  elif seconds < 47336400: # 1.5 years
386
395
  return QCoreApplication.translate(
387
396
  "Common", "a year ago"
@@ -389,7 +398,7 @@ def fuzzyTime(seconds: int) -> str:
389
398
  else:
390
399
  return QCoreApplication.translate(
391
400
  "Common", "{0} years ago"
392
- ).format(int(round(seconds/31557600)))
401
+ ).format(round(seconds/31557600))
393
402
 
394
403
 
395
404
  def numberToRoman(value: int, toLower: bool = False) -> str:
@@ -419,35 +428,29 @@ def numberToRoman(value: int, toLower: bool = False) -> str:
419
428
  # Qt Helpers
420
429
  ##
421
430
 
422
- def cssCol(col: QColor, alpha: int | None = None) -> str:
423
- """Convert a QColor object to an rgba entry to use in CSS."""
424
- return f"rgba({col.red()}, {col.green()}, {col.blue()}, {alpha or col.alpha()})"
425
-
426
-
427
431
  def describeFont(font: QFont) -> str:
428
432
  """Describe a font in a way that can be displayed on the GUI."""
429
433
  if isinstance(font, QFont):
430
434
  info = QFontInfo(font)
431
435
  family = info.family()
432
436
  styles = [v for v in info.styleName().split() if v not in family]
433
- return " ".join([f"{info.pointSize()} pt", family] + styles)
437
+ return " ".join([f"{info.pointSize()} pt", family, *styles])
434
438
  return "Error"
435
439
 
436
440
 
437
441
  def fontMatcher(font: QFont) -> QFont:
438
442
  """Make sure the font is the correct family, if possible. This
439
443
  ensures that Qt doesn't re-use another font under the hood. The
440
- default Qt5 font matching algorithm doesn't handle well changing
444
+ default Qt font matching algorithm doesn't handle well changing
441
445
  application fonts at runtime.
442
446
  """
443
447
  info = QFontInfo(font)
444
448
  if (famRequest := font.family()) != (famActual := info.family()):
445
449
  logger.warning("Font mismatch: Requested '%s', but got '%s'", famRequest, famActual)
446
- db = QFontDatabase()
447
- if famRequest in db.families():
450
+ if famRequest in QFontDatabase.families():
448
451
  styleRequest, sizeRequest = font.styleName(), font.pointSize()
449
452
  logger.info("Lookup: %s, %s, %d pt", famRequest, styleRequest, sizeRequest)
450
- temp = db.font(famRequest, styleRequest, sizeRequest)
453
+ temp = QFontDatabase.font(famRequest, styleRequest, sizeRequest)
451
454
  temp.setPointSize(sizeRequest) # Make sure it isn't changed
452
455
  famFound, styleFound, sizeFound = temp.family(), temp.styleName(), temp.pointSize()
453
456
  if famFound == famRequest:
@@ -465,6 +468,20 @@ def qtLambda(func: Callable, *args: Any, **kwargs: Any) -> Callable:
465
468
  return wrapper
466
469
 
467
470
 
471
+ def qtAddAction(parent: QWidget, label: str) -> QAction:
472
+ """Helper to add action to widget and always return the action."""
473
+ action = QAction(label, parent)
474
+ parent.addAction(action)
475
+ return action
476
+
477
+
478
+ def qtAddMenu(parent: QMenuBar | QMenu, label: str) -> QMenu:
479
+ """Helper to add menu to menu and always return the menu."""
480
+ menu = QMenu(label, parent)
481
+ parent.addMenu(menu)
482
+ return menu
483
+
484
+
468
485
  def encodeMimeHandles(mimeData: QMimeData, handles: list[str]) -> None:
469
486
  """Encode handles into a mime data object."""
470
487
  mimeData.setData(nwConst.MIME_HANDLE, b"|".join(h.encode() for h in handles))
@@ -484,7 +501,7 @@ def jsonEncode(data: dict | list | tuple, n: int = 0, nmax: int = 0) -> str:
484
501
  """Encode a dictionary, list or tuple as a json object or array, and
485
502
  indent from level n up to a max level nmax if nmax is larger than 0.
486
503
  """
487
- if not isinstance(data, (dict, list, tuple)):
504
+ if not isinstance(data, dict | list | tuple):
488
505
  return "[]"
489
506
 
490
507
  buffer = []
@@ -531,12 +548,11 @@ def jsonEncode(data: dict | list | tuple, n: int = 0, nmax: int = 0) -> str:
531
548
  # XML Helpers
532
549
  ##
533
550
 
534
- def xmlIndent(tree: ET.Element | ET.ElementTree) -> None:
551
+ def xmlIndent(xml: ET.Element | ET.ElementTree) -> None:
535
552
  """A modified version of the XML indent function in the standard
536
553
  library. It behaves more closely to how the one from lxml does.
537
554
  """
538
- if isinstance(tree, ET.ElementTree):
539
- tree = tree.getroot()
555
+ tree = xml.getroot() if isinstance(xml, ET.ElementTree) else xml
540
556
  if not isinstance(tree, ET.Element):
541
557
  return
542
558