novelWriter 2.6.3__py3-none-any.whl → 2.7b1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (321) hide show
  1. novelwriter/__init__.py +84 -74
  2. novelwriter/assets/i18n/project_en_GB.json +1 -0
  3. novelwriter/assets/icons/font_awesome.icons +109 -0
  4. novelwriter/assets/icons/material_filled_bold.icons +109 -0
  5. novelwriter/assets/icons/material_filled_normal.icons +109 -0
  6. novelwriter/assets/icons/material_filled_thin.icons +109 -0
  7. novelwriter/assets/icons/material_rounded_bold.icons +109 -0
  8. novelwriter/assets/icons/material_rounded_normal.icons +109 -0
  9. novelwriter/assets/icons/material_rounded_thin.icons +109 -0
  10. novelwriter/assets/icons/remix_filled.icons +108 -0
  11. novelwriter/assets/icons/remix_outline.icons +108 -0
  12. novelwriter/assets/manual.pdf +0 -0
  13. novelwriter/assets/{manual_fr_FR.pdf → manual_fr.pdf} +0 -0
  14. novelwriter/assets/sample.zip +0 -0
  15. novelwriter/assets/syntax/cyberpunk_night.conf +1 -1
  16. novelwriter/assets/text/credits_en.htm +6 -6
  17. novelwriter/assets/themes/cyberpunk_night.conf +23 -7
  18. novelwriter/assets/themes/default_dark.conf +20 -4
  19. novelwriter/assets/themes/default_light.conf +21 -5
  20. novelwriter/assets/themes/dracula.conf +20 -4
  21. novelwriter/assets/themes/solarized_dark.conf +24 -8
  22. novelwriter/assets/themes/solarized_light.conf +22 -6
  23. novelwriter/common.py +33 -26
  24. novelwriter/config.py +118 -127
  25. novelwriter/constants.py +50 -36
  26. novelwriter/core/buildsettings.py +23 -16
  27. novelwriter/core/coretools.py +11 -7
  28. novelwriter/core/docbuild.py +19 -13
  29. novelwriter/core/document.py +2 -2
  30. novelwriter/core/index.py +142 -432
  31. novelwriter/core/indexdata.py +403 -0
  32. novelwriter/core/item.py +35 -28
  33. novelwriter/core/itemmodel.py +27 -26
  34. novelwriter/core/novelmodel.py +223 -0
  35. novelwriter/core/options.py +1 -1
  36. novelwriter/core/project.py +10 -11
  37. novelwriter/core/projectdata.py +5 -5
  38. novelwriter/core/projectxml.py +1 -1
  39. novelwriter/core/sessions.py +3 -2
  40. novelwriter/core/spellcheck.py +4 -3
  41. novelwriter/core/status.py +12 -15
  42. novelwriter/core/storage.py +1 -1
  43. novelwriter/core/tree.py +46 -8
  44. novelwriter/dialogs/about.py +19 -22
  45. novelwriter/dialogs/docmerge.py +21 -23
  46. novelwriter/dialogs/docsplit.py +20 -23
  47. novelwriter/dialogs/editlabel.py +9 -13
  48. novelwriter/dialogs/preferences.py +111 -48
  49. novelwriter/dialogs/projectsettings.py +48 -54
  50. novelwriter/dialogs/quotes.py +14 -19
  51. novelwriter/dialogs/wordlist.py +25 -30
  52. novelwriter/enum.py +8 -0
  53. novelwriter/error.py +16 -16
  54. novelwriter/extensions/configlayout.py +18 -18
  55. novelwriter/extensions/eventfilters.py +9 -5
  56. novelwriter/extensions/modified.py +34 -15
  57. novelwriter/extensions/novelselector.py +18 -5
  58. novelwriter/extensions/pagedsidebar.py +39 -49
  59. novelwriter/extensions/progressbars.py +10 -8
  60. novelwriter/extensions/statusled.py +6 -13
  61. novelwriter/extensions/switch.py +19 -30
  62. novelwriter/extensions/switchbox.py +7 -3
  63. novelwriter/extensions/versioninfo.py +4 -4
  64. novelwriter/formats/shared.py +1 -1
  65. novelwriter/formats/todocx.py +14 -10
  66. novelwriter/formats/tohtml.py +7 -5
  67. novelwriter/formats/tokenizer.py +36 -33
  68. novelwriter/formats/tomarkdown.py +6 -2
  69. novelwriter/formats/toodt.py +27 -22
  70. novelwriter/formats/toqdoc.py +19 -14
  71. novelwriter/formats/toraw.py +6 -2
  72. novelwriter/gui/doceditor.py +216 -265
  73. novelwriter/gui/dochighlight.py +46 -45
  74. novelwriter/gui/docviewer.py +102 -104
  75. novelwriter/gui/docviewerpanel.py +47 -51
  76. novelwriter/gui/editordocument.py +8 -5
  77. novelwriter/gui/itemdetails.py +11 -14
  78. novelwriter/gui/mainmenu.py +146 -145
  79. novelwriter/gui/noveltree.py +239 -405
  80. novelwriter/gui/outline.py +133 -72
  81. novelwriter/gui/projtree.py +138 -132
  82. novelwriter/gui/search.py +33 -31
  83. novelwriter/gui/sidebar.py +13 -18
  84. novelwriter/gui/statusbar.py +13 -15
  85. novelwriter/gui/theme.py +533 -430
  86. novelwriter/guimain.py +27 -29
  87. novelwriter/shared.py +32 -23
  88. novelwriter/text/comments.py +70 -0
  89. novelwriter/text/patterns.py +4 -4
  90. novelwriter/tools/dictionaries.py +20 -29
  91. novelwriter/tools/lipsum.py +16 -17
  92. novelwriter/tools/manusbuild.py +39 -42
  93. novelwriter/tools/manuscript.py +101 -114
  94. novelwriter/tools/manussettings.py +78 -83
  95. novelwriter/tools/noveldetails.py +51 -64
  96. novelwriter/tools/welcome.py +56 -75
  97. novelwriter/tools/writingstats.py +44 -57
  98. novelwriter/types.py +5 -7
  99. {novelWriter-2.6.3.dist-info → novelwriter-2.7b1.dist-info}/METADATA +6 -6
  100. novelwriter-2.7b1.dist-info/RECORD +159 -0
  101. {novelWriter-2.6.3.dist-info → novelwriter-2.7b1.dist-info}/WHEEL +1 -1
  102. novelWriter-2.6.3.dist-info/RECORD +0 -363
  103. novelwriter/assets/icons/typicons_dark/README.md +0 -29
  104. novelwriter/assets/icons/typicons_dark/icons.conf +0 -134
  105. novelwriter/assets/icons/typicons_dark/mixed_copy.svg +0 -4
  106. novelwriter/assets/icons/typicons_dark/mixed_document-chapter.svg +0 -12
  107. novelwriter/assets/icons/typicons_dark/mixed_document-new.svg +0 -6
  108. novelwriter/assets/icons/typicons_dark/mixed_document-note.svg +0 -12
  109. novelwriter/assets/icons/typicons_dark/mixed_document-scene.svg +0 -12
  110. novelwriter/assets/icons/typicons_dark/mixed_document-section.svg +0 -12
  111. novelwriter/assets/icons/typicons_dark/mixed_document-title.svg +0 -12
  112. novelwriter/assets/icons/typicons_dark/mixed_edit.svg +0 -4
  113. novelwriter/assets/icons/typicons_dark/mixed_import.svg +0 -5
  114. novelwriter/assets/icons/typicons_dark/mixed_input-checked.svg +0 -5
  115. novelwriter/assets/icons/typicons_dark/mixed_input-none.svg +0 -5
  116. novelwriter/assets/icons/typicons_dark/mixed_input-unchecked.svg +0 -5
  117. novelwriter/assets/icons/typicons_dark/mixed_margin-bottom.svg +0 -6
  118. novelwriter/assets/icons/typicons_dark/mixed_margin-left.svg +0 -6
  119. novelwriter/assets/icons/typicons_dark/mixed_margin-right.svg +0 -6
  120. novelwriter/assets/icons/typicons_dark/mixed_margin-top.svg +0 -6
  121. novelwriter/assets/icons/typicons_dark/mixed_search-replace.svg +0 -6
  122. novelwriter/assets/icons/typicons_dark/mixed_size-height.svg +0 -6
  123. novelwriter/assets/icons/typicons_dark/mixed_size-width.svg +0 -6
  124. novelwriter/assets/icons/typicons_dark/nw_deco-h0.svg +0 -4
  125. novelwriter/assets/icons/typicons_dark/nw_deco-h1.svg +0 -4
  126. novelwriter/assets/icons/typicons_dark/nw_deco-h2-narrow.svg +0 -4
  127. novelwriter/assets/icons/typicons_dark/nw_deco-h2.svg +0 -4
  128. novelwriter/assets/icons/typicons_dark/nw_deco-h3-narrow.svg +0 -4
  129. novelwriter/assets/icons/typicons_dark/nw_deco-h3.svg +0 -4
  130. novelwriter/assets/icons/typicons_dark/nw_deco-h4-narrow.svg +0 -4
  131. novelwriter/assets/icons/typicons_dark/nw_deco-h4.svg +0 -4
  132. novelwriter/assets/icons/typicons_dark/nw_deco-note.svg +0 -4
  133. novelwriter/assets/icons/typicons_dark/nw_deco-noveltree-more.svg +0 -4
  134. novelwriter/assets/icons/typicons_dark/nw_font.svg +0 -4
  135. novelwriter/assets/icons/typicons_dark/nw_panel.svg +0 -4
  136. novelwriter/assets/icons/typicons_dark/nw_quote.svg +0 -4
  137. novelwriter/assets/icons/typicons_dark/nw_search-case.svg +0 -4
  138. novelwriter/assets/icons/typicons_dark/nw_search-preserve.svg +0 -4
  139. novelwriter/assets/icons/typicons_dark/nw_search-regex.svg +0 -4
  140. novelwriter/assets/icons/typicons_dark/nw_search-word.svg +0 -4
  141. novelwriter/assets/icons/typicons_dark/nw_tb-bold-md.svg +0 -4
  142. novelwriter/assets/icons/typicons_dark/nw_tb-bold.svg +0 -6
  143. novelwriter/assets/icons/typicons_dark/nw_tb-italic-md.svg +0 -4
  144. novelwriter/assets/icons/typicons_dark/nw_tb-italic.svg +0 -6
  145. novelwriter/assets/icons/typicons_dark/nw_tb-mark.svg +0 -7
  146. novelwriter/assets/icons/typicons_dark/nw_tb-strike-md.svg +0 -4
  147. novelwriter/assets/icons/typicons_dark/nw_tb-strike.svg +0 -6
  148. novelwriter/assets/icons/typicons_dark/nw_tb-subscript.svg +0 -7
  149. novelwriter/assets/icons/typicons_dark/nw_tb-superscript.svg +0 -7
  150. novelwriter/assets/icons/typicons_dark/nw_tb-underline.svg +0 -7
  151. novelwriter/assets/icons/typicons_dark/nw_toolbar.svg +0 -5
  152. novelwriter/assets/icons/typicons_dark/typ_arrow-down-thick-grey.svg +0 -4
  153. novelwriter/assets/icons/typicons_dark/typ_arrow-forward.svg +0 -4
  154. novelwriter/assets/icons/typicons_dark/typ_arrow-maximise.svg +0 -4
  155. novelwriter/assets/icons/typicons_dark/typ_arrow-minimise.svg +0 -4
  156. novelwriter/assets/icons/typicons_dark/typ_arrow-repeat-grey.svg +0 -4
  157. novelwriter/assets/icons/typicons_dark/typ_book-grey.svg +0 -4
  158. novelwriter/assets/icons/typicons_dark/typ_book.svg +0 -6
  159. novelwriter/assets/icons/typicons_dark/typ_bookmark.svg +0 -4
  160. novelwriter/assets/icons/typicons_dark/typ_calendar.svg +0 -4
  161. novelwriter/assets/icons/typicons_dark/typ_cancel-grey.svg +0 -4
  162. novelwriter/assets/icons/typicons_dark/typ_cancel.svg +0 -4
  163. novelwriter/assets/icons/typicons_dark/typ_chart-bar-grey.svg +0 -4
  164. novelwriter/assets/icons/typicons_dark/typ_chevron-down.svg +0 -4
  165. novelwriter/assets/icons/typicons_dark/typ_chevron-left.svg +0 -4
  166. novelwriter/assets/icons/typicons_dark/typ_chevron-right.svg +0 -4
  167. novelwriter/assets/icons/typicons_dark/typ_chevron-up.svg +0 -4
  168. novelwriter/assets/icons/typicons_dark/typ_cog.svg +0 -4
  169. novelwriter/assets/icons/typicons_dark/typ_delete-full.svg +0 -4
  170. novelwriter/assets/icons/typicons_dark/typ_delete.svg +0 -4
  171. novelwriter/assets/icons/typicons_dark/typ_directions-full.svg +0 -4
  172. novelwriter/assets/icons/typicons_dark/typ_document-add.svg +0 -4
  173. novelwriter/assets/icons/typicons_dark/typ_document-text.svg +0 -8
  174. novelwriter/assets/icons/typicons_dark/typ_document.svg +0 -4
  175. novelwriter/assets/icons/typicons_dark/typ_export-grey.svg +0 -4
  176. novelwriter/assets/icons/typicons_dark/typ_export.svg +0 -4
  177. novelwriter/assets/icons/typicons_dark/typ_eye.svg +0 -4
  178. novelwriter/assets/icons/typicons_dark/typ_flag.svg +0 -4
  179. novelwriter/assets/icons/typicons_dark/typ_folder-open.svg +0 -4
  180. novelwriter/assets/icons/typicons_dark/typ_folder.svg +0 -5
  181. novelwriter/assets/icons/typicons_dark/typ_globe-grey.svg +0 -4
  182. novelwriter/assets/icons/typicons_dark/typ_key.svg +0 -4
  183. novelwriter/assets/icons/typicons_dark/typ_lightbulb-full.svg +0 -4
  184. novelwriter/assets/icons/typicons_dark/typ_location.svg +0 -4
  185. novelwriter/assets/icons/typicons_dark/typ_media-pause-grey.svg +0 -4
  186. novelwriter/assets/icons/typicons_dark/typ_media-record-outline.svg +0 -4
  187. novelwriter/assets/icons/typicons_dark/typ_media-record.svg +0 -4
  188. novelwriter/assets/icons/typicons_dark/typ_minus.svg +0 -4
  189. novelwriter/assets/icons/typicons_dark/typ_pencil.svg +0 -5
  190. novelwriter/assets/icons/typicons_dark/typ_pin-outline.svg +0 -4
  191. novelwriter/assets/icons/typicons_dark/typ_pin.svg +0 -4
  192. novelwriter/assets/icons/typicons_dark/typ_plus.svg +0 -4
  193. novelwriter/assets/icons/typicons_dark/typ_puzzle-outline.svg +0 -4
  194. novelwriter/assets/icons/typicons_dark/typ_puzzle.svg +0 -4
  195. novelwriter/assets/icons/typicons_dark/typ_refresh-flipped.svg +0 -4
  196. novelwriter/assets/icons/typicons_dark/typ_refresh.svg +0 -4
  197. novelwriter/assets/icons/typicons_dark/typ_search-grey.svg +0 -4
  198. novelwriter/assets/icons/typicons_dark/typ_search.svg +0 -4
  199. novelwriter/assets/icons/typicons_dark/typ_star.svg +0 -4
  200. novelwriter/assets/icons/typicons_dark/typ_stopwatch-grey.svg +0 -4
  201. novelwriter/assets/icons/typicons_dark/typ_th-dot-menu.svg +0 -4
  202. novelwriter/assets/icons/typicons_dark/typ_th-dot-more.svg +0 -4
  203. novelwriter/assets/icons/typicons_dark/typ_th-list-grey.svg +0 -4
  204. novelwriter/assets/icons/typicons_dark/typ_th-list.svg +0 -9
  205. novelwriter/assets/icons/typicons_dark/typ_times.svg +0 -4
  206. novelwriter/assets/icons/typicons_dark/typ_trash.svg +0 -5
  207. novelwriter/assets/icons/typicons_dark/typ_unfold-hidden.svg +0 -4
  208. novelwriter/assets/icons/typicons_dark/typ_unfold-visible.svg +0 -4
  209. novelwriter/assets/icons/typicons_dark/typ_user.svg +0 -5
  210. novelwriter/assets/icons/typicons_dark/typ_warning-full.svg +0 -4
  211. novelwriter/assets/icons/typicons_light/README.md +0 -29
  212. novelwriter/assets/icons/typicons_light/icons.conf +0 -134
  213. novelwriter/assets/icons/typicons_light/mixed_copy.svg +0 -4
  214. novelwriter/assets/icons/typicons_light/mixed_document-chapter.svg +0 -12
  215. novelwriter/assets/icons/typicons_light/mixed_document-new.svg +0 -6
  216. novelwriter/assets/icons/typicons_light/mixed_document-note.svg +0 -12
  217. novelwriter/assets/icons/typicons_light/mixed_document-scene.svg +0 -12
  218. novelwriter/assets/icons/typicons_light/mixed_document-section.svg +0 -12
  219. novelwriter/assets/icons/typicons_light/mixed_document-title.svg +0 -12
  220. novelwriter/assets/icons/typicons_light/mixed_edit.svg +0 -4
  221. novelwriter/assets/icons/typicons_light/mixed_import.svg +0 -5
  222. novelwriter/assets/icons/typicons_light/mixed_input-checked.svg +0 -5
  223. novelwriter/assets/icons/typicons_light/mixed_input-none.svg +0 -5
  224. novelwriter/assets/icons/typicons_light/mixed_input-unchecked.svg +0 -5
  225. novelwriter/assets/icons/typicons_light/mixed_margin-bottom.svg +0 -6
  226. novelwriter/assets/icons/typicons_light/mixed_margin-left.svg +0 -6
  227. novelwriter/assets/icons/typicons_light/mixed_margin-right.svg +0 -6
  228. novelwriter/assets/icons/typicons_light/mixed_margin-top.svg +0 -6
  229. novelwriter/assets/icons/typicons_light/mixed_search-replace.svg +0 -6
  230. novelwriter/assets/icons/typicons_light/mixed_size-height.svg +0 -6
  231. novelwriter/assets/icons/typicons_light/mixed_size-width.svg +0 -6
  232. novelwriter/assets/icons/typicons_light/nw_deco-h0.svg +0 -4
  233. novelwriter/assets/icons/typicons_light/nw_deco-h1.svg +0 -4
  234. novelwriter/assets/icons/typicons_light/nw_deco-h2-narrow.svg +0 -4
  235. novelwriter/assets/icons/typicons_light/nw_deco-h2.svg +0 -4
  236. novelwriter/assets/icons/typicons_light/nw_deco-h3-narrow.svg +0 -4
  237. novelwriter/assets/icons/typicons_light/nw_deco-h3.svg +0 -4
  238. novelwriter/assets/icons/typicons_light/nw_deco-h4-narrow.svg +0 -4
  239. novelwriter/assets/icons/typicons_light/nw_deco-h4.svg +0 -4
  240. novelwriter/assets/icons/typicons_light/nw_deco-note.svg +0 -4
  241. novelwriter/assets/icons/typicons_light/nw_deco-noveltree-more.svg +0 -4
  242. novelwriter/assets/icons/typicons_light/nw_font.svg +0 -4
  243. novelwriter/assets/icons/typicons_light/nw_panel.svg +0 -4
  244. novelwriter/assets/icons/typicons_light/nw_quote.svg +0 -4
  245. novelwriter/assets/icons/typicons_light/nw_search-case.svg +0 -4
  246. novelwriter/assets/icons/typicons_light/nw_search-preserve.svg +0 -4
  247. novelwriter/assets/icons/typicons_light/nw_search-regex.svg +0 -4
  248. novelwriter/assets/icons/typicons_light/nw_search-word.svg +0 -4
  249. novelwriter/assets/icons/typicons_light/nw_tb-bold-md.svg +0 -4
  250. novelwriter/assets/icons/typicons_light/nw_tb-bold.svg +0 -6
  251. novelwriter/assets/icons/typicons_light/nw_tb-italic-md.svg +0 -4
  252. novelwriter/assets/icons/typicons_light/nw_tb-italic.svg +0 -6
  253. novelwriter/assets/icons/typicons_light/nw_tb-mark.svg +0 -7
  254. novelwriter/assets/icons/typicons_light/nw_tb-strike-md.svg +0 -4
  255. novelwriter/assets/icons/typicons_light/nw_tb-strike.svg +0 -6
  256. novelwriter/assets/icons/typicons_light/nw_tb-subscript.svg +0 -7
  257. novelwriter/assets/icons/typicons_light/nw_tb-superscript.svg +0 -7
  258. novelwriter/assets/icons/typicons_light/nw_tb-underline.svg +0 -7
  259. novelwriter/assets/icons/typicons_light/nw_toolbar.svg +0 -5
  260. novelwriter/assets/icons/typicons_light/typ_arrow-down-thick-grey.svg +0 -4
  261. novelwriter/assets/icons/typicons_light/typ_arrow-forward.svg +0 -4
  262. novelwriter/assets/icons/typicons_light/typ_arrow-maximise.svg +0 -4
  263. novelwriter/assets/icons/typicons_light/typ_arrow-minimise.svg +0 -4
  264. novelwriter/assets/icons/typicons_light/typ_arrow-repeat-grey.svg +0 -4
  265. novelwriter/assets/icons/typicons_light/typ_book-grey.svg +0 -4
  266. novelwriter/assets/icons/typicons_light/typ_book.svg +0 -6
  267. novelwriter/assets/icons/typicons_light/typ_bookmark.svg +0 -4
  268. novelwriter/assets/icons/typicons_light/typ_calendar.svg +0 -4
  269. novelwriter/assets/icons/typicons_light/typ_cancel-grey.svg +0 -4
  270. novelwriter/assets/icons/typicons_light/typ_cancel.svg +0 -4
  271. novelwriter/assets/icons/typicons_light/typ_chart-bar-grey.svg +0 -4
  272. novelwriter/assets/icons/typicons_light/typ_chevron-down.svg +0 -4
  273. novelwriter/assets/icons/typicons_light/typ_chevron-left.svg +0 -4
  274. novelwriter/assets/icons/typicons_light/typ_chevron-right.svg +0 -4
  275. novelwriter/assets/icons/typicons_light/typ_chevron-up.svg +0 -4
  276. novelwriter/assets/icons/typicons_light/typ_cog.svg +0 -4
  277. novelwriter/assets/icons/typicons_light/typ_delete-full.svg +0 -4
  278. novelwriter/assets/icons/typicons_light/typ_delete.svg +0 -4
  279. novelwriter/assets/icons/typicons_light/typ_directions-full.svg +0 -4
  280. novelwriter/assets/icons/typicons_light/typ_document-add.svg +0 -4
  281. novelwriter/assets/icons/typicons_light/typ_document-text.svg +0 -5
  282. novelwriter/assets/icons/typicons_light/typ_document.svg +0 -4
  283. novelwriter/assets/icons/typicons_light/typ_export-grey.svg +0 -4
  284. novelwriter/assets/icons/typicons_light/typ_export.svg +0 -4
  285. novelwriter/assets/icons/typicons_light/typ_eye.svg +0 -4
  286. novelwriter/assets/icons/typicons_light/typ_flag.svg +0 -4
  287. novelwriter/assets/icons/typicons_light/typ_folder-open.svg +0 -4
  288. novelwriter/assets/icons/typicons_light/typ_folder.svg +0 -5
  289. novelwriter/assets/icons/typicons_light/typ_globe-grey.svg +0 -4
  290. novelwriter/assets/icons/typicons_light/typ_key.svg +0 -4
  291. novelwriter/assets/icons/typicons_light/typ_lightbulb-full.svg +0 -4
  292. novelwriter/assets/icons/typicons_light/typ_location.svg +0 -4
  293. novelwriter/assets/icons/typicons_light/typ_media-pause-grey.svg +0 -4
  294. novelwriter/assets/icons/typicons_light/typ_media-record-outline.svg +0 -4
  295. novelwriter/assets/icons/typicons_light/typ_media-record.svg +0 -4
  296. novelwriter/assets/icons/typicons_light/typ_minus.svg +0 -4
  297. novelwriter/assets/icons/typicons_light/typ_pencil.svg +0 -5
  298. novelwriter/assets/icons/typicons_light/typ_pin-outline.svg +0 -4
  299. novelwriter/assets/icons/typicons_light/typ_pin.svg +0 -4
  300. novelwriter/assets/icons/typicons_light/typ_plus.svg +0 -4
  301. novelwriter/assets/icons/typicons_light/typ_puzzle-outline.svg +0 -4
  302. novelwriter/assets/icons/typicons_light/typ_puzzle.svg +0 -4
  303. novelwriter/assets/icons/typicons_light/typ_refresh-flipped.svg +0 -4
  304. novelwriter/assets/icons/typicons_light/typ_refresh.svg +0 -4
  305. novelwriter/assets/icons/typicons_light/typ_search-grey.svg +0 -4
  306. novelwriter/assets/icons/typicons_light/typ_search.svg +0 -4
  307. novelwriter/assets/icons/typicons_light/typ_star.svg +0 -4
  308. novelwriter/assets/icons/typicons_light/typ_stopwatch-grey.svg +0 -4
  309. novelwriter/assets/icons/typicons_light/typ_th-dot-menu.svg +0 -4
  310. novelwriter/assets/icons/typicons_light/typ_th-dot-more.svg +0 -4
  311. novelwriter/assets/icons/typicons_light/typ_th-list-grey.svg +0 -4
  312. novelwriter/assets/icons/typicons_light/typ_th-list.svg +0 -9
  313. novelwriter/assets/icons/typicons_light/typ_times.svg +0 -4
  314. novelwriter/assets/icons/typicons_light/typ_trash.svg +0 -5
  315. novelwriter/assets/icons/typicons_light/typ_unfold-hidden.svg +0 -4
  316. novelwriter/assets/icons/typicons_light/typ_unfold-visible.svg +0 -4
  317. novelwriter/assets/icons/typicons_light/typ_user.svg +0 -5
  318. novelwriter/assets/icons/typicons_light/typ_warning-full.svg +0 -4
  319. {novelWriter-2.6.3.dist-info → novelwriter-2.7b1.dist-info}/entry_points.txt +0 -0
  320. {novelWriter-2.6.3.dist-info → novelwriter-2.7b1.dist-info/licenses}/LICENSE.md +0 -0
  321. {novelWriter-2.6.3.dist-info → novelwriter-2.7b1.dist-info}/top_level.txt +0 -0
@@ -32,10 +32,12 @@ import logging
32
32
 
33
33
  from enum import Enum
34
34
  from time import time
35
+ from typing import Final
35
36
 
36
- from PyQt5.QtCore import QT_TRANSLATE_NOOP, Qt, pyqtSignal, pyqtSlot
37
- from PyQt5.QtWidgets import (
38
- QAbstractItemView, QAction, QFileDialog, QFrame, QGridLayout, QGroupBox,
37
+ from PyQt6.QtCore import QT_TRANSLATE_NOOP, Qt, pyqtSignal, pyqtSlot
38
+ from PyQt6.QtGui import QAction, QIcon
39
+ from PyQt6.QtWidgets import (
40
+ QAbstractItemView, QFileDialog, QFrame, QGridLayout, QGroupBox,
39
41
  QHBoxLayout, QLabel, QMenu, QScrollArea, QSplitter, QToolBar, QToolButton,
40
42
  QTreeWidget, QTreeWidgetItem, QVBoxLayout, QWidget
41
43
  )
@@ -45,7 +47,7 @@ from novelwriter.common import checkInt, formatFileFilter
45
47
  from novelwriter.constants import nwKeyWords, nwLabels, nwStats, nwStyles, trConst, trStats
46
48
  from novelwriter.enum import nwChange, nwDocMode, nwItemClass, nwItemLayout, nwItemType, nwOutline
47
49
  from novelwriter.error import logException
48
- from novelwriter.extensions.configlayout import NColourLabel
50
+ from novelwriter.extensions.configlayout import NColorLabel
49
51
  from novelwriter.extensions.novelselector import NovelSelector
50
52
  from novelwriter.types import (
51
53
  QtAlignLeftTop, QtAlignRight, QtAlignRightTop, QtDecoration,
@@ -77,7 +79,7 @@ class GuiOutlineView(QWidget):
77
79
 
78
80
  # Assemble
79
81
  self.outerBox = QVBoxLayout()
80
- self.outerBox.setContentsMargins(0, 0, CONFIG.pxInt(4), 0)
82
+ self.outerBox.setContentsMargins(0, 0, 4, 0)
81
83
  self.outerBox.addWidget(self.outlineBar)
82
84
  self.outerBox.addWidget(self.splitOutline)
83
85
 
@@ -103,7 +105,10 @@ class GuiOutlineView(QWidget):
103
105
  def updateTheme(self) -> None:
104
106
  """Update theme elements."""
105
107
  self.outlineBar.updateTheme()
106
- self.refreshTree()
108
+ self.outlineTree.updateTheme()
109
+ self.outlineTree.refreshTree(
110
+ rootHandle=SHARED.project.data.getLastHandle("outline"), overRide=True
111
+ )
107
112
  return
108
113
 
109
114
  def initSettings(self) -> None:
@@ -218,14 +223,14 @@ class GuiOutlineToolBar(QToolBar):
218
223
  stretch.setSizePolicy(QtSizeExpanding, QtSizeExpanding)
219
224
 
220
225
  # Novel Selector
221
- self.novelLabel = NColourLabel(
222
- self.tr("Outline of"), self, scale=NColourLabel.HEADER_SCALE, bold=True
226
+ self.novelLabel = NColorLabel(
227
+ self.tr("Outline of"), self, scale=NColorLabel.HEADER_SCALE, bold=True
223
228
  )
224
- self.novelLabel.setContentsMargins(0, 0, CONFIG.pxInt(12), 0)
229
+ self.novelLabel.setContentsMargins(0, 0, 12, 0)
225
230
 
226
231
  self.novelValue = NovelSelector(self)
227
232
  self.novelValue.setIncludeAll(True)
228
- self.novelValue.setMinimumWidth(CONFIG.pxInt(200))
233
+ self.novelValue.setMinimumWidth(200)
229
234
  self.novelValue.novelSelectionChanged.connect(self._novelValueChanged)
230
235
 
231
236
  # Actions
@@ -268,9 +273,9 @@ class GuiOutlineToolBar(QToolBar):
268
273
  """Update theme elements."""
269
274
  self.setStyleSheet("QToolBar {border: 0px;}")
270
275
  self.novelValue.refreshNovelList()
271
- self.aRefresh.setIcon(SHARED.theme.getIcon("refresh"))
272
- self.aExport.setIcon(SHARED.theme.getIcon("export"))
273
- self.tbColumns.setIcon(SHARED.theme.getIcon("menu"))
276
+ self.aRefresh.setIcon(SHARED.theme.getIcon("refresh", "green"))
277
+ self.aExport.setIcon(SHARED.theme.getIcon("export", "blue"))
278
+ self.tbColumns.setIcon(SHARED.theme.getIcon("more_vertical"))
274
279
  self.tbColumns.setStyleSheet("QToolButton::menu-indicator {image: none;}")
275
280
  self.novelLabel.setTextColors(color=self.palette().windowText().color())
276
281
  return
@@ -315,7 +320,7 @@ class GuiOutlineToolBar(QToolBar):
315
320
 
316
321
  class GuiOutlineTree(QTreeWidget):
317
322
 
318
- DEF_WIDTH = {
323
+ DEF_WIDTH: Final[dict[nwOutline, int]] = {
319
324
  nwOutline.TITLE: 200,
320
325
  nwOutline.LEVEL: 40,
321
326
  nwOutline.LABEL: 150,
@@ -338,7 +343,7 @@ class GuiOutlineTree(QTreeWidget):
338
343
  nwOutline.SYNOP: 200,
339
344
  }
340
345
 
341
- DEF_HIDDEN = {
346
+ DEF_HIDDEN: Final[dict[nwOutline, bool]] = {
342
347
  nwOutline.TITLE: False,
343
348
  nwOutline.LEVEL: True,
344
349
  nwOutline.LABEL: False,
@@ -386,8 +391,8 @@ class GuiOutlineTree(QTreeWidget):
386
391
  self.setIconSize(SHARED.theme.baseIconSize)
387
392
  self.setIndentation(0)
388
393
 
389
- self.treeHead = self.header()
390
- self.treeHead.sectionMoved.connect(self._columnMoved)
394
+ if header := self.header():
395
+ header.sectionMoved.connect(self._columnMoved)
391
396
 
392
397
  # Pre-Generate Tree Formatting
393
398
  fH1 = self.font()
@@ -397,18 +402,8 @@ class GuiOutlineTree(QTreeWidget):
397
402
  fH2 = self.font()
398
403
  fH2.setBold(True)
399
404
 
400
- iType = nwItemType.FILE
401
- iClass = nwItemClass.NO_CLASS
402
- iLayout = nwItemLayout.DOCUMENT
403
-
404
405
  self._hFonts = [self.font(), fH1, fH2, self.font(), self.font()]
405
- self._dIcon = {
406
- "H0": SHARED.theme.getItemIcon(iType, iClass, iLayout, "H0"),
407
- "H1": SHARED.theme.getItemIcon(iType, iClass, iLayout, "H1"),
408
- "H2": SHARED.theme.getItemIcon(iType, iClass, iLayout, "H2"),
409
- "H3": SHARED.theme.getItemIcon(iType, iClass, iLayout, "H3"),
410
- "H4": SHARED.theme.getItemIcon(iType, iClass, iLayout, "H4"),
411
- }
406
+ self._dIcon: dict[str, QIcon] = {}
412
407
 
413
408
  # Internals
414
409
  self._treeOrder = []
@@ -419,6 +414,7 @@ class GuiOutlineTree(QTreeWidget):
419
414
  self._firstView = True
420
415
  self._lastBuild = 0
421
416
 
417
+ self.updateTheme()
422
418
  self.initSettings()
423
419
  self.clearContent()
424
420
 
@@ -480,6 +476,20 @@ class GuiOutlineTree(QTreeWidget):
480
476
 
481
477
  return
482
478
 
479
+ def updateTheme(self) -> None:
480
+ """Update theme elements."""
481
+ iType = nwItemType.FILE
482
+ iClass = nwItemClass.NO_CLASS
483
+ iLayout = nwItemLayout.DOCUMENT
484
+ self._dIcon = {
485
+ "H0": SHARED.theme.getItemIcon(iType, iClass, iLayout, "H0"),
486
+ "H1": SHARED.theme.getItemIcon(iType, iClass, iLayout, "H1"),
487
+ "H2": SHARED.theme.getItemIcon(iType, iClass, iLayout, "H2"),
488
+ "H3": SHARED.theme.getItemIcon(iType, iClass, iLayout, "H3"),
489
+ "H4": SHARED.theme.getItemIcon(iType, iClass, iLayout, "H4"),
490
+ }
491
+ return
492
+
483
493
  def refreshTree(
484
494
  self, rootHandle: str | None = None,
485
495
  overRide: bool = False, novelChanged: bool = False
@@ -489,7 +499,7 @@ class GuiOutlineTree(QTreeWidget):
489
499
  tree.
490
500
  """
491
501
  # If it's the first time, we always build
492
- if self._firstView or self._firstView and overRide:
502
+ if self._firstView or (self._firstView and overRide):
493
503
  self._loadHeaderState()
494
504
  self._populateTree(rootHandle)
495
505
  self._firstView = False
@@ -547,14 +557,11 @@ class GuiOutlineTree(QTreeWidget):
547
557
  )[0]:
548
558
  CONFIG.setLastPath("outline", path)
549
559
  logger.info("Writing CSV file: %s", path)
550
- cols = [col for col in self._treeOrder if not self._colHidden[col]]
551
- order = [self._colIdx[col] for col in cols]
552
- with open(path, mode="w", newline="") as csvFile:
560
+ with open(path, mode="w", newline="", encoding="utf-8") as csvFile:
553
561
  writer = csv.writer(csvFile, dialect="excel", quoting=csv.QUOTE_ALL)
554
- writer.writerow([trConst(nwLabels.OUTLINE_COLS[col]) for col in cols])
555
- for i in range(self.topLevelItemCount()):
556
- if item := self.topLevelItem(i):
557
- writer.writerow(item.text(i) for i in order)
562
+ writer.writerows(
563
+ self._dumpNovelData(self.outlineView.outlineBar.novelValue.handle)
564
+ )
558
565
  return
559
566
 
560
567
  ##
@@ -614,7 +621,7 @@ class GuiOutlineTree(QTreeWidget):
614
621
  continue
615
622
  tmpOrder.append(nwOutline[name])
616
623
  tmpHidden[nwOutline[name]] = hidden
617
- tmpWidth[nwOutline[name]] = CONFIG.pxInt(width)
624
+ tmpWidth[nwOutline[name]] = width
618
625
  except Exception:
619
626
  logger.error("Invalid column state")
620
627
  logException()
@@ -638,26 +645,22 @@ class GuiOutlineTree(QTreeWidget):
638
645
  save the current width of hidden columns though. This preserves
639
646
  the last known width in case they're unhidden again.
640
647
  """
641
- # If we haven't built the tree, there is nothing to save.
642
- if self._lastBuild == 0:
643
- return
644
-
645
- colState = {}
646
- for iCol in range(self.columnCount()):
647
- hItem = self._treeOrder[iCol]
648
- iLog = self.treeHead.logicalIndex(iCol)
649
- logHidden = self.isColumnHidden(iLog)
650
- orgWidth = CONFIG.rpxInt(self._colWidth[hItem])
651
- logWidth = CONFIG.rpxInt(self.columnWidth(iLog))
652
- colState[hItem.name] = [
653
- logHidden, orgWidth if logHidden and logWidth == 0 else logWidth
654
- ]
655
-
656
- logger.debug("Saving State: GuiOutline")
657
- pOptions = SHARED.project.options
658
- pOptions.setValue("GuiOutline", "columnState", colState)
659
- pOptions.saveSettings()
660
-
648
+ if self._lastBuild > 0 and (header := self.header()):
649
+ colState = {}
650
+ for iCol in range(self.columnCount()):
651
+ hItem = self._treeOrder[iCol]
652
+ iLog = header.logicalIndex(iCol)
653
+ logHidden = self.isColumnHidden(iLog)
654
+ orgWidth = self._colWidth[hItem]
655
+ logWidth = self.columnWidth(iLog)
656
+ colState[hItem.name] = [
657
+ logHidden, orgWidth if logHidden and logWidth == 0 else logWidth
658
+ ]
659
+
660
+ logger.debug("Saving State: GuiOutline")
661
+ pOptions = SHARED.project.options
662
+ pOptions.setValue("GuiOutline", "columnState", colState)
663
+ pOptions.saveSettings()
661
664
  return
662
665
 
663
666
  def _populateTree(self, rootHandle: str | None) -> None:
@@ -745,6 +748,69 @@ class GuiOutlineTree(QTreeWidget):
745
748
 
746
749
  return
747
750
 
751
+ def _dumpNovelData(self, rootHandle: str | None) -> list[list[str | int]]:
752
+ """Dump all novel data into a table."""
753
+ sLabel = SHARED.project.localLookup("Story Structure")
754
+ sKeys = sorted(SHARED.project.index.getStoryKeys())
755
+ sMatch = [f"story.{k}" for k in sKeys]
756
+ sHeaders = [f"{sLabel} ({k})" for k in sKeys]
757
+
758
+ data: list[list[str | int]] = [[
759
+ "H",
760
+ trConst(nwLabels.OUTLINE_COLS[nwOutline.TITLE]),
761
+ trConst(nwLabels.OUTLINE_COLS[nwOutline.LABEL]),
762
+ trConst(nwLabels.OUTLINE_COLS[nwOutline.LINE]),
763
+ trConst(nwLabels.OUTLINE_COLS[nwOutline.STATUS]),
764
+ trConst(nwLabels.OUTLINE_COLS[nwOutline.CCOUNT]),
765
+ trConst(nwLabels.OUTLINE_COLS[nwOutline.WCOUNT]),
766
+ trConst(nwLabels.OUTLINE_COLS[nwOutline.PCOUNT]),
767
+ trConst(nwLabels.OUTLINE_COLS[nwOutline.POV]),
768
+ trConst(nwLabels.OUTLINE_COLS[nwOutline.FOCUS]),
769
+ trConst(nwLabels.OUTLINE_COLS[nwOutline.CHAR]),
770
+ trConst(nwLabels.OUTLINE_COLS[nwOutline.PLOT]),
771
+ trConst(nwLabels.OUTLINE_COLS[nwOutline.TIME]),
772
+ trConst(nwLabels.OUTLINE_COLS[nwOutline.WORLD]),
773
+ trConst(nwLabels.OUTLINE_COLS[nwOutline.OBJECT]),
774
+ trConst(nwLabels.OUTLINE_COLS[nwOutline.ENTITY]),
775
+ trConst(nwLabels.OUTLINE_COLS[nwOutline.CUSTOM]),
776
+ trConst(nwLabels.OUTLINE_COLS[nwOutline.STORY]),
777
+ trConst(nwLabels.OUTLINE_COLS[nwOutline.MENTION]),
778
+ trConst(nwLabels.OUTLINE_COLS[nwOutline.SYNOP]),
779
+ *sHeaders,
780
+ ]]
781
+
782
+ for _, tHandle, sTitle, novIdx in SHARED.project.index.novelStructure(
783
+ rootHandle=rootHandle, activeOnly=True
784
+ ):
785
+ if novIdx.level != "H0" and (nwItem := SHARED.project.tree[tHandle]):
786
+ refs = SHARED.project.index.getReferences(tHandle, sTitle)
787
+ story = {k: v for k, v in novIdx.comments.items() if k in sMatch}.values()
788
+ data.append([
789
+ novIdx.level,
790
+ novIdx.title,
791
+ nwItem.itemName,
792
+ novIdx.line,
793
+ nwItem.getImportStatus()[0],
794
+ novIdx.charCount,
795
+ novIdx.wordCount,
796
+ novIdx.paraCount,
797
+ ", ".join(refs[nwKeyWords.POV_KEY]),
798
+ ", ".join(refs[nwKeyWords.FOCUS_KEY]),
799
+ ", ".join(refs[nwKeyWords.CHAR_KEY]),
800
+ ", ".join(refs[nwKeyWords.PLOT_KEY]),
801
+ ", ".join(refs[nwKeyWords.TIME_KEY]),
802
+ ", ".join(refs[nwKeyWords.WORLD_KEY]),
803
+ ", ".join(refs[nwKeyWords.OBJECT_KEY]),
804
+ ", ".join(refs[nwKeyWords.ENTITY_KEY]),
805
+ ", ".join(refs[nwKeyWords.CUSTOM_KEY]),
806
+ ", ".join(refs[nwKeyWords.STORY_KEY]),
807
+ ", ".join(refs[nwKeyWords.MENTION_KEY]),
808
+ novIdx.synopsis,
809
+ *story,
810
+ ])
811
+
812
+ return data
813
+
748
814
 
749
815
  class GuiOutlineHeaderMenu(QMenu):
750
816
 
@@ -790,7 +856,7 @@ class GuiOutlineHeaderMenu(QMenu):
790
856
 
791
857
  class GuiOutlineDetails(QScrollArea):
792
858
 
793
- LVL_MAP = {
859
+ LVL_MAP: Final[dict[str, str]] = {
794
860
  "H1": QT_TRANSLATE_NOOP("GuiOutlineDetails", "Title"),
795
861
  "H2": QT_TRANSLATE_NOOP("GuiOutlineDetails", "Chapter"),
796
862
  "H3": QT_TRANSLATE_NOOP("GuiOutlineDetails", "Scene"),
@@ -810,8 +876,6 @@ class GuiOutlineDetails(QScrollArea):
810
876
  minTitle = 30*SHARED.theme.textNWidth
811
877
  maxTitle = 40*SHARED.theme.textNWidth
812
878
  wCount = SHARED.theme.getTextWidth("999,999")
813
- hSpace = int(CONFIG.pxInt(10))
814
- vSpace = int(CONFIG.pxInt(4))
815
879
 
816
880
  bFont = SHARED.theme.guiFontB
817
881
 
@@ -890,8 +954,8 @@ class GuiOutlineDetails(QScrollArea):
890
954
 
891
955
  self.mainForm.setColumnStretch(1, 1)
892
956
  self.mainForm.setRowStretch(4, 1)
893
- self.mainForm.setHorizontalSpacing(hSpace)
894
- self.mainForm.setVerticalSpacing(vSpace)
957
+ self.mainForm.setHorizontalSpacing(10)
958
+ self.mainForm.setVerticalSpacing(4)
895
959
 
896
960
  # Selected Item Tags
897
961
  self.tagsForm = QGridLayout()
@@ -914,8 +978,8 @@ class GuiOutlineDetails(QScrollArea):
914
978
 
915
979
  self.tagsForm.setColumnStretch(1, 1)
916
980
  self.tagsForm.setRowStretch(len(self.tagValues), 1)
917
- self.tagsForm.setHorizontalSpacing(hSpace)
918
- self.tagsForm.setVerticalSpacing(vSpace)
981
+ self.tagsForm.setHorizontalSpacing(10)
982
+ self.tagsForm.setVerticalSpacing(4)
919
983
 
920
984
  # Assemble
921
985
  self.mainSplit = QSplitter(Qt.Orientation.Horizontal)
@@ -956,21 +1020,18 @@ class GuiOutlineDetails(QScrollArea):
956
1020
  width = parent.width() if isinstance(parent, QWidget) else 1000
957
1021
  pOptions = SHARED.project.options
958
1022
  self.mainSplit.setSizes([
959
- CONFIG.pxInt(pOptions.getInt("GuiOutlineDetails", "detailsWidth", width//3)),
960
- CONFIG.pxInt(pOptions.getInt("GuiOutlineDetails", "tagsWidth", 2*width//3))
1023
+ pOptions.getInt("GuiOutlineDetails", "detailsWidth", width//3),
1024
+ pOptions.getInt("GuiOutlineDetails", "tagsWidth", 2*width//3),
961
1025
  ])
962
1026
  return
963
1027
 
964
1028
  def saveGuiSettings(self) -> None:
965
1029
  """Run close project tasks."""
966
- mainSplit = self.mainSplit.sizes()
967
- detailsWidth = CONFIG.rpxInt(mainSplit[0])
968
- tagsWidth = CONFIG.rpxInt(mainSplit[1])
969
-
970
1030
  logger.debug("Saving State: GuiOutlineDetails")
1031
+ mainSplit = self.mainSplit.sizes()
971
1032
  pOptions = SHARED.project.options
972
- pOptions.setValue("GuiOutlineDetails", "detailsWidth", detailsWidth)
973
- pOptions.setValue("GuiOutlineDetails", "tagsWidth", tagsWidth)
1033
+ pOptions.setValue("GuiOutlineDetails", "detailsWidth", mainSplit[0])
1034
+ pOptions.setValue("GuiOutlineDetails", "tagsWidth", mainSplit[1])
974
1035
  return
975
1036
 
976
1037
  def clearDetails(self) -> None: