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
@@ -29,8 +29,8 @@ import re
29
29
 
30
30
  from time import time
31
31
 
32
- from PyQt5.QtCore import Qt
33
- from PyQt5.QtGui import (
32
+ from PyQt6.QtCore import Qt
33
+ from PyQt6.QtGui import (
34
34
  QBrush, QColor, QFont, QSyntaxHighlighter, QTextBlockUserData,
35
35
  QTextCharFormat, QTextDocument
36
36
  )
@@ -38,8 +38,8 @@ from PyQt5.QtGui import (
38
38
  from novelwriter import CONFIG, SHARED
39
39
  from novelwriter.common import checkInt
40
40
  from novelwriter.constants import nwStyles, nwUnicode
41
- from novelwriter.core.index import processComment
42
41
  from novelwriter.enum import nwComment
42
+ from novelwriter.text.comments import processComment
43
43
  from novelwriter.text.patterns import REGEX_PATTERNS, DialogParser
44
44
 
45
45
  logger = logging.getLogger(__name__)
@@ -58,8 +58,8 @@ BLOCK_TITLE = 4
58
58
  class GuiDocHighlighter(QSyntaxHighlighter):
59
59
 
60
60
  __slots__ = (
61
- "_tHandle", "_isNovel", "_isInactive", "_spellCheck", "_spellErr",
62
- "_hStyles", "_minRules", "_txtRules", "_cmnRules", "_dialogParser",
61
+ "_cmnRules", "_dialogParser", "_hStyles", "_isInactive", "_isNovel",
62
+ "_minRules", "_spellCheck", "_spellErr", "_tHandle", "_txtRules",
63
63
  )
64
64
 
65
65
  def __init__(self, document: QTextDocument) -> None:
@@ -91,44 +91,45 @@ class GuiDocHighlighter(QSyntaxHighlighter):
91
91
  rules and building the RegExes.
92
92
  """
93
93
  logger.debug("Setting up highlighting rules")
94
+ syntax = SHARED.theme.syntaxTheme
94
95
 
95
- colEmph = SHARED.theme.colEmph if CONFIG.highlightEmph else None
96
- colBreak = QColor(SHARED.theme.colEmph)
96
+ colEmph = syntax.emph if CONFIG.highlightEmph else None
97
+ colBreak = QColor(syntax.emph)
97
98
  colBreak.setAlpha(64)
98
99
 
99
100
  # Create Character Formats
100
- self._addCharFormat("text", SHARED.theme.colText)
101
- self._addCharFormat("header1", SHARED.theme.colHead, "b", nwStyles.H_SIZES[1])
102
- self._addCharFormat("header2", SHARED.theme.colHead, "b", nwStyles.H_SIZES[2])
103
- self._addCharFormat("header3", SHARED.theme.colHead, "b", nwStyles.H_SIZES[3])
104
- self._addCharFormat("header4", SHARED.theme.colHead, "b", nwStyles.H_SIZES[4])
105
- self._addCharFormat("head1h", SHARED.theme.colHeadH, "b", nwStyles.H_SIZES[1])
106
- self._addCharFormat("head2h", SHARED.theme.colHeadH, "b", nwStyles.H_SIZES[2])
107
- self._addCharFormat("head3h", SHARED.theme.colHeadH, "b", nwStyles.H_SIZES[3])
108
- self._addCharFormat("head4h", SHARED.theme.colHeadH, "b", nwStyles.H_SIZES[4])
101
+ self._addCharFormat("text", syntax.text)
102
+ self._addCharFormat("header1", syntax.head, "b", nwStyles.H_SIZES[1])
103
+ self._addCharFormat("header2", syntax.head, "b", nwStyles.H_SIZES[2])
104
+ self._addCharFormat("header3", syntax.head, "b", nwStyles.H_SIZES[3])
105
+ self._addCharFormat("header4", syntax.head, "b", nwStyles.H_SIZES[4])
106
+ self._addCharFormat("head1h", syntax.headH, "b", nwStyles.H_SIZES[1])
107
+ self._addCharFormat("head2h", syntax.headH, "b", nwStyles.H_SIZES[2])
108
+ self._addCharFormat("head3h", syntax.headH, "b", nwStyles.H_SIZES[3])
109
+ self._addCharFormat("head4h", syntax.headH, "b", nwStyles.H_SIZES[4])
109
110
  self._addCharFormat("bold", colEmph, "b")
110
111
  self._addCharFormat("italic", colEmph, "i")
111
- self._addCharFormat("strike", SHARED.theme.colHidden, "s")
112
- self._addCharFormat("mspaces", SHARED.theme.colError, "err")
112
+ self._addCharFormat("strike", syntax.hidden, "s")
113
+ self._addCharFormat("mspaces", syntax.error, "err")
113
114
  self._addCharFormat("nobreak", colBreak, "bg")
114
- self._addCharFormat("altdialog", SHARED.theme.colDialA)
115
- self._addCharFormat("dialog", SHARED.theme.colDialN)
116
- self._addCharFormat("replace", SHARED.theme.colRepTag)
117
- self._addCharFormat("hidden", SHARED.theme.colHidden)
118
- self._addCharFormat("markup", SHARED.theme.colHidden)
119
- self._addCharFormat("link", SHARED.theme.colLink, "u")
120
- self._addCharFormat("note", SHARED.theme.colNote)
121
- self._addCharFormat("code", SHARED.theme.colCode)
122
- self._addCharFormat("keyword", SHARED.theme.colKey)
123
- self._addCharFormat("tag", SHARED.theme.colTag, "u")
124
- self._addCharFormat("modifier", SHARED.theme.colMod)
125
- self._addCharFormat("value", SHARED.theme.colVal)
126
- self._addCharFormat("optional", SHARED.theme.colOpt)
115
+ self._addCharFormat("altdialog", syntax.dialA)
116
+ self._addCharFormat("dialog", syntax.dialN)
117
+ self._addCharFormat("replace", syntax.repTag)
118
+ self._addCharFormat("hidden", syntax.hidden)
119
+ self._addCharFormat("markup", syntax.hidden)
120
+ self._addCharFormat("link", syntax.link, "u")
121
+ self._addCharFormat("note", syntax.note)
122
+ self._addCharFormat("code", syntax.code)
123
+ self._addCharFormat("keyword", syntax.key)
124
+ self._addCharFormat("tag", syntax.tag, "u")
125
+ self._addCharFormat("modifier", syntax.mod)
126
+ self._addCharFormat("value", syntax.val)
127
+ self._addCharFormat("optional", syntax.opt)
127
128
  self._addCharFormat("invalid", None, "err")
128
129
 
129
130
  # Cache Spell Error Format
130
131
  self._spellErr = QTextCharFormat()
131
- self._spellErr.setUnderlineColor(SHARED.theme.colSpell)
132
+ self._spellErr.setUnderlineColor(syntax.spell)
132
133
  self._spellErr.setUnderlineStyle(QTextCharFormat.UnderlineStyle.SpellCheckUnderline)
133
134
 
134
135
  self._txtRules.clear()
@@ -271,14 +272,14 @@ class GuiDocHighlighter(QSyntaxHighlighter):
271
272
  """Loop through all blocks and re-highlight those of a given
272
273
  content type.
273
274
  """
274
- qDoc = self.document()
275
- nBlocks = qDoc.blockCount()
276
- tStart = time()
277
- for i in range(nBlocks):
278
- block = qDoc.findBlockByNumber(i)
279
- if block.userState() & cType > 0:
280
- self.rehighlightBlock(block)
281
- logger.debug("Document highlighted in %.3f ms" % (1000*(time() - tStart)))
275
+ if document := self.document():
276
+ nBlocks = document.blockCount()
277
+ tStart = time()
278
+ for i in range(nBlocks):
279
+ block = document.findBlockByNumber(i)
280
+ if block.userState() & cType > 0:
281
+ self.rehighlightBlock(block)
282
+ logger.debug("Document highlighted in %.3f ms" % (1000*(time() - tStart)))
282
283
  return
283
284
 
284
285
  ##
@@ -392,7 +393,7 @@ class GuiDocHighlighter(QSyntaxHighlighter):
392
393
  else: # Text Paragraph
393
394
  self.setCurrentBlockState(BLOCK_TEXT)
394
395
  hRules = self._txtRules if self._isNovel else self._minRules
395
- if self._dialogParser.enabled:
396
+ if self._isNovel and self._dialogParser.enabled:
396
397
  for pos, end in self._dialogParser(text):
397
398
  length = end - pos
398
399
  self.setFormat(pos, length, self._hStyles["dialog"])
@@ -450,7 +451,7 @@ class GuiDocHighlighter(QSyntaxHighlighter):
450
451
  if "s" in styles:
451
452
  charFormat.setFontStrikeOut(True)
452
453
  if "err" in styles:
453
- charFormat.setUnderlineColor(SHARED.theme.colError)
454
+ charFormat.setUnderlineColor(SHARED.theme.syntaxTheme.error)
454
455
  charFormat.setUnderlineStyle(QTextCharFormat.UnderlineStyle.SpellCheckUnderline)
455
456
  if "bg" in styles and color is not None:
456
457
  charFormat.setBackground(QBrush(color, Qt.BrushStyle.SolidPattern))
@@ -465,14 +466,14 @@ class GuiDocHighlighter(QSyntaxHighlighter):
465
466
 
466
467
  class TextBlockData(QTextBlockUserData):
467
468
 
468
- __slots__ = ("_text", "_offset", "_metaData", "_spellErrors")
469
+ __slots__ = ("_metaData", "_offset", "_spellErrors", "_text")
469
470
 
470
471
  def __init__(self) -> None:
471
472
  super().__init__()
472
473
  self._text = ""
473
474
  self._offset = 0
474
475
  self._metaData: list[tuple[int, int, str, str]] = []
475
- self._spellErrors: list[tuple[int, int,]] = []
476
+ self._spellErrors: list[tuple[int, int]] = []
476
477
  return
477
478
 
478
479
  @property
@@ -504,7 +505,7 @@ class TextBlockData(QTextBlockUserData):
504
505
  text = f"{text[:s]}{pad}{text[e:]}"
505
506
  self._metaData.append((s, e, res.group(0), "url"))
506
507
 
507
- self._text = text
508
+ self._text = text.replace("\u02bc", "'")
508
509
  self._offset = offset
509
510
 
510
511
  return
@@ -30,22 +30,22 @@ import logging
30
30
 
31
31
  from enum import Enum
32
32
 
33
- from PyQt5.QtCore import QPoint, Qt, QUrl, pyqtSignal, pyqtSlot
34
- from PyQt5.QtGui import (
33
+ from PyQt6.QtCore import QPoint, Qt, QUrl, pyqtSignal, pyqtSlot
34
+ from PyQt6.QtGui import (
35
35
  QCursor, QDesktopServices, QDragEnterEvent, QDragMoveEvent, QDropEvent,
36
36
  QMouseEvent, QPalette, QResizeEvent, QTextCursor
37
37
  )
38
- from PyQt5.QtWidgets import (
39
- QAction, QApplication, QFrame, QHBoxLayout, QMenu, QTextBrowser,
40
- QToolButton, QWidget
38
+ from PyQt6.QtWidgets import (
39
+ QApplication, QFrame, QHBoxLayout, QMenu, QTextBrowser, QToolButton,
40
+ QWidget
41
41
  )
42
42
 
43
43
  from novelwriter import CONFIG, SHARED
44
- from novelwriter.common import decodeMimeHandles, qtLambda
44
+ from novelwriter.common import decodeMimeHandles, qtAddAction, qtLambda
45
45
  from novelwriter.constants import nwConst, nwStyles, nwUnicode
46
- from novelwriter.enum import nwChange, nwDocAction, nwDocMode, nwItemType
46
+ from novelwriter.enum import nwChange, nwComment, nwDocAction, nwDocMode, nwItemType
47
47
  from novelwriter.error import logException
48
- from novelwriter.extensions.configlayout import NColourLabel
48
+ from novelwriter.extensions.configlayout import NColorLabel
49
49
  from novelwriter.extensions.eventfilters import WheelEventFilter
50
50
  from novelwriter.extensions.modified import NIconToolButton
51
51
  from novelwriter.formats.shared import TextDocumentTheme
@@ -79,7 +79,7 @@ class GuiDocViewer(QTextBrowser):
79
79
  self._docTheme = TextDocumentTheme()
80
80
 
81
81
  # Settings
82
- self.setMinimumWidth(CONFIG.pxInt(300))
82
+ self.setMinimumWidth(300)
83
83
  self.setAutoFillBackground(True)
84
84
  self.setOpenLinks(False)
85
85
  self.setOpenExternalLinks(False)
@@ -124,8 +124,7 @@ class GuiDocViewer(QTextBrowser):
124
124
  @property
125
125
  def scrollPosition(self) -> int:
126
126
  """Return the scrollbar position."""
127
- vBar = self.verticalScrollBar()
128
- if vBar.isVisible():
127
+ if (vBar := self.verticalScrollBar()) and vBar.isVisible():
129
128
  return vBar.value()
130
129
  return 0
131
130
 
@@ -155,36 +154,40 @@ class GuiDocViewer(QTextBrowser):
155
154
  self.docFooter.updateFont()
156
155
 
157
156
  # Set the widget colours to match syntax theme
158
- mainPalette = self.palette()
159
- mainPalette.setColor(QPalette.ColorRole.Window, SHARED.theme.colBack)
160
- mainPalette.setColor(QPalette.ColorRole.Base, SHARED.theme.colBack)
161
- mainPalette.setColor(QPalette.ColorRole.Text, SHARED.theme.colText)
162
- self.setPalette(mainPalette)
163
-
164
- docPalette = self.viewport().palette()
165
- docPalette.setColor(QPalette.ColorRole.Base, SHARED.theme.colBack)
166
- docPalette.setColor(QPalette.ColorRole.Text, SHARED.theme.colText)
167
- self.viewport().setPalette(docPalette)
168
- self.docHeader.matchColours()
169
- self.docFooter.matchColours()
157
+ syntax = SHARED.theme.syntaxTheme
158
+
159
+ palette = self.palette()
160
+ palette.setColor(QPalette.ColorRole.Window, syntax.back)
161
+ palette.setColor(QPalette.ColorRole.Base, syntax.back)
162
+ palette.setColor(QPalette.ColorRole.Text, syntax.text)
163
+ self.setPalette(palette)
164
+
165
+ if viewport := self.viewport():
166
+ palette = viewport.palette()
167
+ palette.setColor(QPalette.ColorRole.Base, syntax.back)
168
+ palette.setColor(QPalette.ColorRole.Text, syntax.text)
169
+ viewport.setPalette(palette)
170
+ self.docHeader.matchColors()
171
+ self.docFooter.matchColors()
170
172
 
171
173
  # Update theme colours
172
- self._docTheme.text = SHARED.theme.colText
173
- self._docTheme.highlight = SHARED.theme.colMark
174
- self._docTheme.head = SHARED.theme.colHead
175
- self._docTheme.link = SHARED.theme.colLink
176
- self._docTheme.comment = SHARED.theme.colHidden
177
- self._docTheme.note = SHARED.theme.colNote
178
- self._docTheme.code = SHARED.theme.colCode
179
- self._docTheme.modifier = SHARED.theme.colMod
180
- self._docTheme.keyword = SHARED.theme.colKey
181
- self._docTheme.tag = SHARED.theme.colTag
182
- self._docTheme.optional = SHARED.theme.colOpt
183
- self._docTheme.dialog = SHARED.theme.colDialN
184
- self._docTheme.altdialog = SHARED.theme.colDialA
174
+ self._docTheme.text = syntax.text
175
+ self._docTheme.highlight = syntax.mark
176
+ self._docTheme.head = syntax.head
177
+ self._docTheme.link = syntax.link
178
+ self._docTheme.comment = syntax.hidden
179
+ self._docTheme.note = syntax.note
180
+ self._docTheme.code = syntax.code
181
+ self._docTheme.modifier = syntax.mod
182
+ self._docTheme.keyword = syntax.key
183
+ self._docTheme.tag = syntax.tag
184
+ self._docTheme.optional = syntax.opt
185
+ self._docTheme.dialog = syntax.dialN
186
+ self._docTheme.altdialog = syntax.dialA
185
187
 
186
188
  # Set default text margins
187
- self.document().setDocumentMargin(0)
189
+ if document := self.document():
190
+ document.setDocumentMargin(0)
188
191
 
189
192
  # Scroll bars
190
193
  if CONFIG.hideVScroll:
@@ -198,7 +201,7 @@ class GuiDocViewer(QTextBrowser):
198
201
  self.setHorizontalScrollBarPolicy(QtScrollAsNeeded)
199
202
 
200
203
  # Refresh the tab stops
201
- self.setTabStopDistance(CONFIG.getTabWidth())
204
+ self.setTabStopDistance(CONFIG.tabWidth)
202
205
 
203
206
  # If we have a document open, we should reload it in case the font changed
204
207
  self.reloadText()
@@ -215,7 +218,9 @@ class GuiDocViewer(QTextBrowser):
215
218
  logger.debug("Generating preview for item '%s'", tHandle)
216
219
  QApplication.setOverrideCursor(QCursor(Qt.CursorShape.WaitCursor))
217
220
 
218
- sPos = self.verticalScrollBar().value()
221
+ vBar = self.verticalScrollBar()
222
+ sPos = vBar.value() if vBar else 0
223
+
219
224
  qDoc = ToQTextDocument(SHARED.project)
220
225
  qDoc.setJustify(CONFIG.doJustify)
221
226
  qDoc.setDialogHighlight(True)
@@ -223,8 +228,9 @@ class GuiDocViewer(QTextBrowser):
223
228
  qDoc.setTheme(self._docTheme)
224
229
  qDoc.initDocument()
225
230
  qDoc.setKeywords(True)
226
- qDoc.setComments(CONFIG.viewComments)
227
- qDoc.setSynopsis(CONFIG.viewSynopsis)
231
+ qDoc.setCommentType(nwComment.PLAIN, CONFIG.viewComments)
232
+ qDoc.setCommentType(nwComment.SYNOPSIS, CONFIG.viewSynopsis)
233
+ qDoc.setCommentType(nwComment.SHORT, CONFIG.viewSynopsis)
228
234
 
229
235
  # Be extra careful here to prevent crashes when first opening a
230
236
  # project as a crash here leaves no way of recovering.
@@ -248,11 +254,11 @@ class GuiDocViewer(QTextBrowser):
248
254
 
249
255
  self.setDocumentTitle(tHandle)
250
256
  self.setDocument(qDoc.document)
251
- self.setTabStopDistance(CONFIG.getTabWidth())
257
+ self.setTabStopDistance(CONFIG.tabWidth)
252
258
 
253
- if self._docHandle == tHandle:
259
+ if self._docHandle == tHandle and vBar:
254
260
  # This is a refresh, so we set the scrollbar back to where it was
255
- self.verticalScrollBar().setValue(sPos)
261
+ vBar.setValue(sPos)
256
262
 
257
263
  self._docHandle = tHandle
258
264
  SHARED.project.data.setLastHandle(tHandle, "viewer")
@@ -306,13 +312,13 @@ class GuiDocViewer(QTextBrowser):
306
312
  """Automatically adjust the margins so the text is centred."""
307
313
  wW = self.width()
308
314
  wH = self.height()
309
- cM = CONFIG.getTextMargin()
315
+ cM = CONFIG.textMargin
310
316
 
311
317
  vBar = self.verticalScrollBar()
312
- sW = vBar.width() if vBar.isVisible() else 0
318
+ sW = vBar.width() if vBar and vBar.isVisible() else 0
313
319
 
314
320
  hBar = self.horizontalScrollBar()
315
- sH = hBar.height() if hBar.isVisible() else 0
321
+ sH = hBar.height() if hBar and hBar.isVisible() else 0
316
322
 
317
323
  tM = cM
318
324
  if CONFIG.textWidth > 0:
@@ -337,8 +343,7 @@ class GuiDocViewer(QTextBrowser):
337
343
 
338
344
  def setScrollPosition(self, pos: int) -> None:
339
345
  """Set the scrollbar position."""
340
- vBar = self.verticalScrollBar()
341
- if vBar.isVisible():
346
+ if (vBar := self.verticalScrollBar()) and vBar.isVisible():
342
347
  vBar.setValue(pos)
343
348
  return
344
349
 
@@ -400,30 +405,27 @@ class GuiDocViewer(QTextBrowser):
400
405
  ctxMenu = QMenu(self)
401
406
 
402
407
  if userSelection:
403
- mnuCopy = QAction(self.tr("Copy"), ctxMenu)
404
- mnuCopy.triggered.connect(qtLambda(self.docAction, nwDocAction.COPY))
405
- ctxMenu.addAction(mnuCopy)
406
-
408
+ action = qtAddAction(ctxMenu, self.tr("Copy"))
409
+ action.triggered.connect(qtLambda(self.docAction, nwDocAction.COPY))
407
410
  ctxMenu.addSeparator()
408
411
 
409
- mnuSelAll = QAction(self.tr("Select All"), ctxMenu)
410
- mnuSelAll.triggered.connect(qtLambda(self.docAction, nwDocAction.SEL_ALL))
411
- ctxMenu.addAction(mnuSelAll)
412
+ action = qtAddAction(ctxMenu, self.tr("Select All"))
413
+ action.triggered.connect(qtLambda(self.docAction, nwDocAction.SEL_ALL))
412
414
 
413
- mnuSelWord = QAction(self.tr("Select Word"), ctxMenu)
414
- mnuSelWord.triggered.connect(qtLambda(
415
+ action = qtAddAction(ctxMenu, self.tr("Select Word"))
416
+ action.triggered.connect(qtLambda(
415
417
  self._makePosSelection, QTextCursor.SelectionType.WordUnderCursor, point
416
418
  ))
417
- ctxMenu.addAction(mnuSelWord)
418
419
 
419
- mnuSelPara = QAction(self.tr("Select Paragraph"), ctxMenu)
420
- mnuSelPara.triggered.connect(qtLambda(
420
+ action = qtAddAction(ctxMenu, self.tr("Select Paragraph"))
421
+ action.triggered.connect(qtLambda(
421
422
  self._makePosSelection, QTextCursor.SelectionType.BlockUnderCursor, point
422
423
  ))
423
- ctxMenu.addAction(mnuSelPara)
424
424
 
425
425
  # Open the context menu
426
- ctxMenu.exec(self.viewport().mapToGlobal(point))
426
+ if viewport := self.viewport():
427
+ ctxMenu.exec(viewport.mapToGlobal(point))
428
+
427
429
  ctxMenu.setParent(None)
428
430
 
429
431
  return
@@ -450,7 +452,7 @@ class GuiDocViewer(QTextBrowser):
450
452
 
451
453
  def dragEnterEvent(self, event: QDragEnterEvent) -> None:
452
454
  """Overload drag enter event to handle dragged items."""
453
- if event.mimeData().hasFormat(nwConst.MIME_HANDLE):
455
+ if (data := event.mimeData()) and data.hasFormat(nwConst.MIME_HANDLE):
454
456
  event.acceptProposedAction()
455
457
  else:
456
458
  super().dragEnterEvent(event)
@@ -458,7 +460,7 @@ class GuiDocViewer(QTextBrowser):
458
460
 
459
461
  def dragMoveEvent(self, event: QDragMoveEvent) -> None:
460
462
  """Overload drag move event to handle dragged items."""
461
- if event.mimeData().hasFormat(nwConst.MIME_HANDLE):
463
+ if (data := event.mimeData()) and data.hasFormat(nwConst.MIME_HANDLE):
462
464
  event.acceptProposedAction()
463
465
  else:
464
466
  super().dragMoveEvent(event)
@@ -466,8 +468,8 @@ class GuiDocViewer(QTextBrowser):
466
468
 
467
469
  def dropEvent(self, event: QDropEvent) -> None:
468
470
  """Overload drop event to handle dragged items."""
469
- if event.mimeData().hasFormat(nwConst.MIME_HANDLE):
470
- if handles := decodeMimeHandles(event.mimeData()):
471
+ if (data := event.mimeData()) and data.hasFormat(nwConst.MIME_HANDLE):
472
+ if handles := decodeMimeHandles(data):
471
473
  if SHARED.project.tree.checkType(handles[0], nwItemType.FILE):
472
474
  self.openDocumentRequest.emit(handles[0], nwDocMode.VIEW, "", True)
473
475
  else:
@@ -609,12 +611,9 @@ class GuiDocViewHistory:
609
611
  for loop, it is skipped entirely if log level isn't DEBUG.
610
612
  """
611
613
  if CONFIG.isDebug: # pragma: no cover
612
- for i, (h, p) in enumerate(zip(self._navHistory, self._posHistory)):
613
- logger.debug(
614
- "History %02d: %s %13s [x:%d]" % (
615
- i + 1, ">" if i == self._currPos else " ", h, p
616
- )
617
- )
614
+ for i, (h, p) in enumerate(zip(self._navHistory, self._posHistory, strict=False)):
615
+ a = ">" if i == self._currPos else " "
616
+ logger.debug(f"History {i + 1:02d}: {a} {h:13s} [x:{p}]")
618
617
  return
619
618
 
620
619
 
@@ -638,13 +637,12 @@ class GuiDocViewHeader(QWidget):
638
637
 
639
638
  iPx = SHARED.theme.baseIconHeight
640
639
  iSz = SHARED.theme.baseIconSize
641
- mPx = CONFIG.pxInt(4)
642
640
 
643
641
  # Main Widget Settings
644
642
  self.setAutoFillBackground(True)
645
643
 
646
644
  # Title Label
647
- self.itemTitle = NColourLabel("", self, faded=SHARED.theme.fadedText)
645
+ self.itemTitle = NColorLabel("", self, faded=SHARED.theme.fadedText)
648
646
  self.itemTitle.setMargin(0)
649
647
  self.itemTitle.setContentsMargins(0, 0, 0, 0)
650
648
  self.itemTitle.setAutoFillBackground(True)
@@ -690,9 +688,9 @@ class GuiDocViewHeader(QWidget):
690
688
  self.outerBox.addWidget(self.outlineButton, 0)
691
689
  self.outerBox.addWidget(self.backButton, 0)
692
690
  self.outerBox.addWidget(self.forwardButton, 0)
693
- self.outerBox.addSpacing(mPx)
691
+ self.outerBox.addSpacing(4)
694
692
  self.outerBox.addWidget(self.itemTitle, 1)
695
- self.outerBox.addSpacing(mPx)
693
+ self.outerBox.addSpacing(4)
696
694
  self.outerBox.addWidget(self.editButton, 0)
697
695
  self.outerBox.addWidget(self.refreshButton, 0)
698
696
  self.outerBox.addWidget(self.closeButton, 0)
@@ -703,8 +701,8 @@ class GuiDocViewHeader(QWidget):
703
701
  # Fix Margins and Size
704
702
  # This is needed for high DPI systems. See issue #499.
705
703
  self.setContentsMargins(0, 0, 0, 0)
706
- self.outerBox.setContentsMargins(mPx, mPx, mPx, mPx)
707
- self.setMinimumHeight(iPx + 2*mPx)
704
+ self.outerBox.setContentsMargins(4, 4, 4, 4)
705
+ self.setMinimumHeight(iPx + 8)
708
706
 
709
707
  self.updateFont()
710
708
  self.updateTheme()
@@ -745,7 +743,7 @@ class GuiDocViewHeader(QWidget):
745
743
  minLevel = min(minLevel, level)
746
744
  for title, text, level in entries[:30]:
747
745
  indent = " "*(level - minLevel)
748
- action = self.outlineMenu.addAction(f"{indent}{text}")
746
+ action = qtAddAction(self.outlineMenu, f"{indent}{text}")
749
747
  action.triggered.connect(
750
748
  lambda _, title=title: self.docViewer.navigateTo(f"#{tHandle}:{title}")
751
749
  )
@@ -760,12 +758,12 @@ class GuiDocViewHeader(QWidget):
760
758
 
761
759
  def updateTheme(self) -> None:
762
760
  """Update theme elements."""
763
- self.outlineButton.setThemeIcon("list")
764
- self.backButton.setThemeIcon("backward")
765
- self.forwardButton.setThemeIcon("forward")
766
- self.editButton.setThemeIcon("edit")
767
- self.refreshButton.setThemeIcon("refresh")
768
- self.closeButton.setThemeIcon("close")
761
+ self.outlineButton.setThemeIcon("list", "blue")
762
+ self.backButton.setThemeIcon("chevron_left", "blue")
763
+ self.forwardButton.setThemeIcon("chevron_right", "blue")
764
+ self.editButton.setThemeIcon("edit", "green")
765
+ self.refreshButton.setThemeIcon("refresh", "green")
766
+ self.closeButton.setThemeIcon("close", "red")
769
767
 
770
768
  buttonStyle = SHARED.theme.getStyleSheet(STYLES_MIN_TOOLBUTTON)
771
769
  self.outlineButton.setStyleSheet(buttonStyle)
@@ -775,18 +773,19 @@ class GuiDocViewHeader(QWidget):
775
773
  self.refreshButton.setStyleSheet(buttonStyle)
776
774
  self.closeButton.setStyleSheet(buttonStyle)
777
775
 
778
- self.matchColours()
776
+ self.matchColors()
779
777
 
780
778
  return
781
779
 
782
- def matchColours(self) -> None:
780
+ def matchColors(self) -> None:
783
781
  """Update the colours of the widget to match those of the syntax
784
782
  theme rather than the main GUI.
785
783
  """
786
- palette = QPalette()
787
- palette.setColor(QPalette.ColorRole.Window, SHARED.theme.colBack)
788
- palette.setColor(QPalette.ColorRole.WindowText, SHARED.theme.colText)
789
- palette.setColor(QPalette.ColorRole.Text, SHARED.theme.colText)
784
+ syntax = SHARED.theme.syntaxTheme
785
+ palette = self.palette()
786
+ palette.setColor(QPalette.ColorRole.Window, syntax.back)
787
+ palette.setColor(QPalette.ColorRole.WindowText, syntax.text)
788
+ palette.setColor(QPalette.ColorRole.Text, syntax.text)
790
789
  self.setPalette(palette)
791
790
  self.itemTitle.setTextColors(
792
791
  color=palette.windowText().color(), faded=SHARED.theme.fadedText
@@ -882,8 +881,6 @@ class GuiDocViewFooter(QWidget):
882
881
 
883
882
  iPx = SHARED.theme.baseIconHeight
884
883
  iSz = SHARED.theme.baseIconSize
885
- hSp = CONFIG.pxInt(4)
886
- mPx = CONFIG.pxInt(4)
887
884
 
888
885
  # Main Widget Settings
889
886
  self.setContentsMargins(0, 0, 0, 0)
@@ -920,14 +917,14 @@ class GuiDocViewFooter(QWidget):
920
917
  self.outerBox.addStretch(1)
921
918
  self.outerBox.addWidget(self.showComments, 0)
922
919
  self.outerBox.addWidget(self.showSynopsis, 0)
923
- self.outerBox.setSpacing(hSp)
920
+ self.outerBox.setSpacing(4)
924
921
  self.setLayout(self.outerBox)
925
922
 
926
923
  # Fix Margins and Size
927
924
  # This is needed for high DPI systems. See issue #499.
928
925
  self.setContentsMargins(0, 0, 0, 0)
929
- self.outerBox.setContentsMargins(mPx, mPx, mPx, mPx)
930
- self.setMinimumHeight(iPx + 2*mPx)
926
+ self.outerBox.setContentsMargins(4, 4, 4, 4)
927
+ self.setMinimumHeight(iPx + 8)
931
928
 
932
929
  self.updateFont()
933
930
  self.updateTheme()
@@ -951,7 +948,7 @@ class GuiDocViewFooter(QWidget):
951
948
  """Update theme elements."""
952
949
  # Icons
953
950
  fPx = int(0.9*SHARED.theme.fontPixelSize)
954
- bulletIcon = SHARED.theme.getToggleIcon("bullet", (fPx, fPx))
951
+ bulletIcon = SHARED.theme.getToggleIcon("bullet", (fPx, fPx), "blue")
955
952
 
956
953
  self.showHide.setThemeIcon("panel")
957
954
  self.showComments.setIcon(bulletIcon)
@@ -962,18 +959,19 @@ class GuiDocViewFooter(QWidget):
962
959
  self.showComments.setStyleSheet(buttonStyle)
963
960
  self.showSynopsis.setStyleSheet(buttonStyle)
964
961
 
965
- self.matchColours()
962
+ self.matchColors()
966
963
 
967
964
  return
968
965
 
969
- def matchColours(self) -> None:
966
+ def matchColors(self) -> None:
970
967
  """Update the colours of the widget to match those of the syntax
971
968
  theme rather than the main GUI.
972
969
  """
973
- palette = QPalette()
974
- palette.setColor(QPalette.ColorRole.Window, SHARED.theme.colBack)
975
- palette.setColor(QPalette.ColorRole.WindowText, SHARED.theme.colText)
976
- palette.setColor(QPalette.ColorRole.Text, SHARED.theme.colText)
970
+ syntax = SHARED.theme.syntaxTheme
971
+ palette = self.palette()
972
+ palette.setColor(QPalette.ColorRole.Window, syntax.back)
973
+ palette.setColor(QPalette.ColorRole.WindowText, syntax.text)
974
+ palette.setColor(QPalette.ColorRole.Text, syntax.text)
977
975
  self.setPalette(palette)
978
976
  return
979
977