novelWriter 2.5b1__py3-none-any.whl → 2.5rc1__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 (62) hide show
  1. {novelWriter-2.5b1.dist-info → novelWriter-2.5rc1.dist-info}/METADATA +1 -1
  2. {novelWriter-2.5b1.dist-info → novelWriter-2.5rc1.dist-info}/RECORD +61 -61
  3. {novelWriter-2.5b1.dist-info → novelWriter-2.5rc1.dist-info}/WHEEL +1 -1
  4. novelwriter/__init__.py +3 -3
  5. novelwriter/assets/i18n/nw_pt_BR.qm +0 -0
  6. novelwriter/assets/i18n/project_pt_BR.json +74 -74
  7. novelwriter/assets/manual.pdf +0 -0
  8. novelwriter/assets/sample.zip +0 -0
  9. novelwriter/assets/themes/cyberpunk_night.conf +1 -0
  10. novelwriter/assets/themes/default_dark.conf +1 -0
  11. novelwriter/assets/themes/default_light.conf +1 -0
  12. novelwriter/assets/themes/dracula.conf +1 -0
  13. novelwriter/assets/themes/solarized_dark.conf +1 -0
  14. novelwriter/assets/themes/solarized_light.conf +1 -0
  15. novelwriter/common.py +2 -3
  16. novelwriter/config.py +67 -15
  17. novelwriter/constants.py +8 -10
  18. novelwriter/core/buildsettings.py +5 -3
  19. novelwriter/core/coretools.py +3 -1
  20. novelwriter/core/docbuild.py +1 -0
  21. novelwriter/core/tohtml.py +69 -29
  22. novelwriter/core/tokenizer.py +83 -14
  23. novelwriter/core/toodt.py +48 -21
  24. novelwriter/core/toqdoc.py +25 -9
  25. novelwriter/dialogs/about.py +10 -15
  26. novelwriter/dialogs/docmerge.py +16 -16
  27. novelwriter/dialogs/docsplit.py +16 -16
  28. novelwriter/dialogs/editlabel.py +6 -8
  29. novelwriter/dialogs/preferences.py +94 -68
  30. novelwriter/dialogs/projectsettings.py +10 -10
  31. novelwriter/dialogs/quotes.py +9 -5
  32. novelwriter/dialogs/wordlist.py +6 -6
  33. novelwriter/enum.py +4 -5
  34. novelwriter/extensions/configlayout.py +23 -4
  35. novelwriter/extensions/modified.py +22 -3
  36. novelwriter/extensions/{circularprogress.py → progressbars.py} +26 -3
  37. novelwriter/extensions/statusled.py +28 -22
  38. novelwriter/gui/doceditor.py +20 -11
  39. novelwriter/gui/dochighlight.py +30 -39
  40. novelwriter/gui/docviewer.py +21 -14
  41. novelwriter/gui/mainmenu.py +11 -11
  42. novelwriter/gui/outline.py +3 -3
  43. novelwriter/gui/projtree.py +19 -28
  44. novelwriter/gui/search.py +10 -1
  45. novelwriter/gui/statusbar.py +25 -29
  46. novelwriter/gui/theme.py +3 -0
  47. novelwriter/guimain.py +91 -84
  48. novelwriter/shared.py +10 -8
  49. novelwriter/text/patterns.py +113 -0
  50. novelwriter/tools/dictionaries.py +2 -8
  51. novelwriter/tools/lipsum.py +8 -12
  52. novelwriter/tools/manusbuild.py +9 -9
  53. novelwriter/tools/manuscript.py +10 -5
  54. novelwriter/tools/manussettings.py +7 -3
  55. novelwriter/tools/noveldetails.py +10 -10
  56. novelwriter/tools/welcome.py +10 -10
  57. novelwriter/tools/writingstats.py +3 -3
  58. novelwriter/types.py +5 -2
  59. novelwriter/extensions/simpleprogress.py +0 -53
  60. {novelWriter-2.5b1.dist-info → novelWriter-2.5rc1.dist-info}/LICENSE.md +0 -0
  61. {novelWriter-2.5b1.dist-info → novelWriter-2.5rc1.dist-info}/entry_points.txt +0 -0
  62. {novelWriter-2.5b1.dist-info → novelWriter-2.5rc1.dist-info}/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: novelWriter
3
- Version: 2.5b1
3
+ Version: 2.5rc1
4
4
  Summary: A markdown-like text editor for planning and writing novels
5
5
  Author-email: Veronica Berglyd Olsen <code@vkbo.net>
6
6
  License: GNU General Public License v3
@@ -1,14 +1,14 @@
1
- novelwriter/__init__.py,sha256=H7RVewswhg3RViwaGImEb4xbTi-NURPn_nSqHXbJXxQ,7552
2
- novelwriter/common.py,sha256=NcMU6bF9rOecpPo14C8svqZb6gNSZobfq3vzpwObFc4,18257
3
- novelwriter/config.py,sha256=gyjoWD3NmMmPXm1XbRWVelKffBRVlpqy5E4Tergvj2M,37349
4
- novelwriter/constants.py,sha256=_E464sJcGwWvDyxqGPmCyILN9h4tlpJ7T8XsrG8IPj0,21372
5
- novelwriter/enum.py,sha256=ckfliz_klLNSyswJAgD4V5yGlRN_w0FbEYBd6XYayxw,3515
1
+ novelwriter/__init__.py,sha256=GYdc7rDpW0764jkkbmX8iziTEnMHeHhcqgH4pHPr5Ng,7553
2
+ novelwriter/common.py,sha256=sJK-MpM6bnZbhp0D8nRLRqL0HlnogGKDQozRhAZv6FU,18236
3
+ novelwriter/config.py,sha256=cUL4S-JOKhxEes--NxCiV84NpanvVbcbW_K5v74dS3w,39081
4
+ novelwriter/constants.py,sha256=y-UjNZxtU2lzn0Ji9lKiNU3233RmoJuK-3JWHT6GIvc,21368
5
+ novelwriter/enum.py,sha256=c1IS9rmpWMtqnMzftpWoQFtfRqcK9VMTO0vbMsf7pLM,3501
6
6
  novelwriter/error.py,sha256=iIx1OzyXTT7Ngk2mXW_5c0YqVdFBD0NIkUFgAXNNBlM,6813
7
- novelwriter/guimain.py,sha256=ACxMx2sKQedaMoZiOELu7qenEimx0fV_NNS4qjjbNSI,52987
8
- novelwriter/shared.py,sha256=lSp2Tk3ABCNee5I1Mt7z4MmdBI5gGZAyqExqYl-EXms,15362
9
- novelwriter/types.py,sha256=s35ESln-3OuXdxBGpYvyyC47kxhzgD225-dGwe7d_0U,4600
10
- novelwriter/assets/manual.pdf,sha256=bG6KQ6qSXZQai9A8BsSUfImKR29lpDDEGBuHXA1-ZdE,2691769
11
- novelwriter/assets/sample.zip,sha256=GTQfl86FrrIM_eTxKWzJ4oMapW28RtphI0TMSGtlsSc,27808
7
+ novelwriter/guimain.py,sha256=b6RwIFtLCOFoETmNSnHP2QvaWJ6qRoiBPYLMLBoi8m4,53363
8
+ novelwriter/shared.py,sha256=PPbEe8S2TRzEvXii8s8U4R0371ACpeMFdKmAkO-On4g,15540
9
+ novelwriter/types.py,sha256=tV-XFc10wsk7zH__S2dEuEfidI6_adgOetpAVbnmJmI,4691
10
+ novelwriter/assets/manual.pdf,sha256=SfYdeBc57qUYB84p1HtAZ9gMl08DRdqePCvAzGRHl3M,2692539
11
+ novelwriter/assets/sample.zip,sha256=bio1FbkHrclw5cJkdgawV-urSO96Qf2eIARB-m60980,27808
12
12
  novelwriter/assets/i18n/nw_de_DE.qm,sha256=PPBpHJ3M0jL0t4xSY8zr3CKaO0umGW4K4Tb7bj0gtlA,97532
13
13
  novelwriter/assets/i18n/nw_en_US.qm,sha256=sZKjLkT2CcPhGAS3WUgKm9XO3ugbBrx2zbwVyhP7vSE,90470
14
14
  novelwriter/assets/i18n/nw_es_419.qm,sha256=8saaQ1As_hOgBI-oyEIqV5KCmLaMg_ldkOT9Q1uJmaY,99857
@@ -17,7 +17,7 @@ novelwriter/assets/i18n/nw_it_IT.qm,sha256=mRgsonFCjm6bgG2sldQtMrRDAfqNIpiq9ebp1
17
17
  novelwriter/assets/i18n/nw_ja_JP.qm,sha256=kbZKcnRDKralChIDOqsnK8Sn0NdcjlTDf03fOLVPxxY,74895
18
18
  novelwriter/assets/i18n/nw_nb_NO.qm,sha256=cuQLRkvGXIFYsK7a4j1wxKY3H7JQIfjObkVvFbVFt-Q,92928
19
19
  novelwriter/assets/i18n/nw_nl_NL.qm,sha256=4RcFVAWj3PGT4jeivxLEp85HfiSr3FvFCnlmjQRXSRc,96814
20
- novelwriter/assets/i18n/nw_pt_BR.qm,sha256=2pW_7MFG152nN3Yc721qvvcG01XSRTVe21BvvqdBQvk,79257
20
+ novelwriter/assets/i18n/nw_pt_BR.qm,sha256=JNs3XUrVyq2qNxlwSu4em8J8qUi_Wfp_Wom3JtwXWSE,98636
21
21
  novelwriter/assets/i18n/nw_zh_CN.qm,sha256=3q2cSsY3kT7dRggXq-fj8Sank88V_G2RKzjXQY5-3nA,67445
22
22
  novelwriter/assets/i18n/project_de_DE.json,sha256=85ud9rxRHyXm85QDmW_LKcUE8h0L1Bvukaf5Tjt-wpg,2818
23
23
  novelwriter/assets/i18n/project_en_GB.json,sha256=7c9W2YJAELCSwx4zN_2qYZ3xsGncinCrGNhaj_FVkxk,2511
@@ -29,7 +29,7 @@ novelwriter/assets/i18n/project_ja_JP.json,sha256=8P03f2D9o2TlSxFU5ugRa-DJDeDZr_
29
29
  novelwriter/assets/i18n/project_nb_NO.json,sha256=e8E9c188KRPJfgZa298hDiaLEuhjHMxbRMaIF8HaVew,2298
30
30
  novelwriter/assets/i18n/project_nl_NL.json,sha256=qUEEjLMRtvt9VuNmjb_qOVCXqUCENHskCEyp5YlPMc4,2683
31
31
  novelwriter/assets/i18n/project_nn_NO.json,sha256=7ZfmtFWHcDMiLVqdOEDHQWHbpoC_bv5ESmf_-CoYiks,2250
32
- novelwriter/assets/i18n/project_pt_BR.json,sha256=oZ7jdSF1h-kuGhKYZOWbuwVCRgakgs9HzeMSiLPnTns,2763
32
+ novelwriter/assets/i18n/project_pt_BR.json,sha256=FDxIeSlf3v8AcrWfgwk7UOMRDmb2hWdDoabsBq5rkL8,2763
33
33
  novelwriter/assets/i18n/project_ru_RU.json,sha256=F4QkD6VVDCtGdil7uoXCmuczvUpe9tv-1L-3Eyc8sKE,3699
34
34
  novelwriter/assets/i18n/project_zh_CN.json,sha256=cfl0TsnbISYUvygOw015y0x0REDG97xR0yjyJ85Jm34,2322
35
35
  novelwriter/assets/icons/none.svg,sha256=NRN9vMzohg7Ner71GwPthrCG0uA81TpY8UmKb8-L-pM,251
@@ -260,16 +260,16 @@ novelwriter/assets/syntax/tomorrow_night_bright.conf,sha256=h8_775Ed8hl2XhfCoxAY
260
260
  novelwriter/assets/syntax/tomorrow_night_eighties.conf,sha256=stO_xH5RzMN0jaZeYr53LVXbpqSmIXALBFGVLlJBDLA,1557
261
261
  novelwriter/assets/text/credits_en.htm,sha256=FLmgB5HLLWyKPBfJp-_P86cb6s9pOGu7OnIpEYpAJqo,4361
262
262
  novelwriter/assets/text/lipsum.txt,sha256=sGA6AC_p4jrUifxLxy3cSODeRwkpBNXDPGgX6YRTm2s,62937
263
- novelwriter/assets/themes/cyberpunk_night.conf,sha256=G0Mz7k7HoUvP8k6zIL9W-tWE2amWvLHY89O52K2_MuQ,891
263
+ novelwriter/assets/themes/cyberpunk_night.conf,sha256=FvG_YVfEnMwJV1XUDEdpi9qoHQ5sdyVEaR_Y3WfWNA8,923
264
264
  novelwriter/assets/themes/default.conf,sha256=K0LZ64lODpCtUg3pISTAP4UKvEYMvPkmIYN9RDEaWwk,72
265
- novelwriter/assets/themes/default_dark.conf,sha256=1jFL3rMHjN6d_s0SslId1n_Aw6c4nDOM3ybTvHOW1rs,957
266
- novelwriter/assets/themes/default_light.conf,sha256=h6c0Lnp1PTIJCfSKh3q-4giSqi4ln1L8AsKCZrBWBBM,960
267
- novelwriter/assets/themes/dracula.conf,sha256=IuGxKRUqVbRXRYaKxQ2RemQwGA9zKkeiGKsRi264wiQ,1393
268
- novelwriter/assets/themes/solarized_dark.conf,sha256=Prdp6-igYhOlUjW8eTDxYbibj2ezo3MD2z9TiWHy0hE,884
269
- novelwriter/assets/themes/solarized_light.conf,sha256=m_DmSdBQ6Ufvj1XXqc9yTxMiplyBKjv6u2EUaoS598s,886
270
- novelwriter/core/buildsettings.py,sha256=4kG4SjZ_tSoc9btHC919PKhteYU0nZJ2YVlJF2keh3k,22537
271
- novelwriter/core/coretools.py,sha256=CR4rMVchfBUSzO2QsUjEysxhDgmN4-CWc7kGfbL00oA,20950
272
- novelwriter/core/docbuild.py,sha256=6ORKq1kzS-Ri0Sr3eyqCQ3CowqjdGV4Xei70-ov_abk,14156
265
+ novelwriter/assets/themes/default_dark.conf,sha256=obPCLVOXL1Zp973DbbROldyQOoUPGWlPKLbetZqMZe8,989
266
+ novelwriter/assets/themes/default_light.conf,sha256=zNjrtkRs2hLEcefFt3uys2-tei3Lxdth-yThO9InNz4,992
267
+ novelwriter/assets/themes/dracula.conf,sha256=pUvu7FS1nRPj3PyU3NZMR0WSb5sIa0oLpSa2XTzsh98,1425
268
+ novelwriter/assets/themes/solarized_dark.conf,sha256=7dDjs8aiFuAjl--hqMJQEExrfCgAapiPY82CL6aAo-I,916
269
+ novelwriter/assets/themes/solarized_light.conf,sha256=psCPVWcjAKB5y8H_E_h5zYUifxh5YpdFdBzxFofIHa0,918
270
+ novelwriter/core/buildsettings.py,sha256=cx-yjeja6VeYUdVZwNhLr6Ka_EXT8xCTwzQtv1Cmrec,22689
271
+ novelwriter/core/coretools.py,sha256=mItCKIHMMu1zrW3q2-FhF_lVfzjOKhbPtTEaXLt6U-o,21048
272
+ novelwriter/core/docbuild.py,sha256=h1jCFgkzyuoDgusjvuctBQpyDdNWBCHL2CNwQN0aEeM,14236
273
273
  novelwriter/core/document.py,sha256=T8FlxyEMlR3t2HNE92InseWUMylWFTMnr2fP-Ge5LQc,12130
274
274
  novelwriter/core/index.py,sha256=soGv-bDdAHk77ubqr1OfftGtyB1aJAJNODyfOq2nZm8,48450
275
275
  novelwriter/core/item.py,sha256=0p_o3eCf8ZK30MiUR1rd1fDXb63lqNB4lHZeLMA6Wys,17635
@@ -281,57 +281,57 @@ novelwriter/core/sessions.py,sha256=V9eBXaUMcXTZjYXR5dgi6E14COIlcLIkNwS6pDrn75U,
281
281
  novelwriter/core/spellcheck.py,sha256=MwkRPp3MJa2X-6yRWX6Rc-sq2vLsbLnjNnyUpAbRFiE,7176
282
282
  novelwriter/core/status.py,sha256=pxW43PfS8rRjsNe3N406YSMOzSxOLCV5YrPH0Tw7YqQ,11498
283
283
  novelwriter/core/storage.py,sha256=cu3V1YzdUJECW_QEXj9F2991ZKfYJHbCVynmPmMmLn8,20775
284
- novelwriter/core/tohtml.py,sha256=aDxZD6wfY2JUHzBrWd3Oxy46zL1tNbAXiWBhXzzs--M,16886
285
- novelwriter/core/tokenizer.py,sha256=m7oHg1Iz1toEwygCuvHAJZeIXZqqmHvPBC4oT-gUCrs,44516
284
+ novelwriter/core/tohtml.py,sha256=NxM4c52q2ZFNW-XdHOI9L5lqTSiw9J5KZAELhdmN_9I,19211
285
+ novelwriter/core/tokenizer.py,sha256=6aUIdbF_u2nXEJn7YY5tpIVISXlvy-Y_w6T07on9t2I,47631
286
286
  novelwriter/core/tomarkdown.py,sha256=sZG64PLyTjDuIxnPQVMdcMSF-obsp4C06B1dUKhlbHU,7925
287
- novelwriter/core/toodt.py,sha256=jiP_fTlk8Oe2YHUQVBohEThzSKYAc5zeF7kfENFV_-M,61580
288
- novelwriter/core/toqdoc.py,sha256=-idcdDTz1zVJ1TuqacVs6mf3YYLvA9lrHwpYR7I70VM,14784
287
+ novelwriter/core/toodt.py,sha256=Hrb6FJkwf2wwcKE6f7lw5o0PZqKsf1TWqvJbrJWrijU,62529
288
+ novelwriter/core/toqdoc.py,sha256=tt34SuQ6phh-8huOJfbwt4Velkq9lo6z2LJUVeze1W4,15537
289
289
  novelwriter/core/tree.py,sha256=mmOB7kN0tjWda_AdT1WuZyFrewuc6uRAlqCfX6opwek,18681
290
- novelwriter/dialogs/about.py,sha256=NRK-1XI0U8bdogDjRAFDTicblEhTxtXq7iPGhdjo5nA,4927
291
- novelwriter/dialogs/docmerge.py,sha256=WyhU2xV2hIm9zMJZZlaloh6OnGpTvdxrrKtd2_EbrG4,6123
292
- novelwriter/dialogs/docsplit.py,sha256=KbE0120qd8EEu7nTgPzjaZtiHP5jsFMc7IdxcT7chv0,9115
293
- novelwriter/dialogs/editlabel.py,sha256=yo_lPnmogsasUMDKF418f4dsjvcwlzx8T_6bBy-MGHA,2938
294
- novelwriter/dialogs/preferences.py,sha256=fPDW7y0vfpBvzTneRvqqd_FarlqE1rUMDXRzt8-Lr2s,37663
295
- novelwriter/dialogs/projectsettings.py,sha256=nvEa47ppKwpFkCuq-pft2HSye4CqJVmkJcKo06df-cY,27638
296
- novelwriter/dialogs/quotes.py,sha256=fmlDEoaqf1qOMJUsA5_1PXGrpJtEcVy6jGo0IGz5XUI,4678
297
- novelwriter/dialogs/wordlist.py,sha256=Q_xqwF4OL50Dw4lcAT2uBPc-06mZeLSZuByYWfWkqJ8,8512
298
- novelwriter/extensions/circularprogress.py,sha256=y_T92IvVEziPHE3gFhACnQVn7I5dpkhs-vqhzh0OLpE,3805
299
- novelwriter/extensions/configlayout.py,sha256=_ihrLuwjqd0ZtuuKJjKpqzk7tuDX7o4y26cDPyAHkl8,9438
290
+ novelwriter/dialogs/about.py,sha256=0iBYkifACc5vZj4KwG0G2Dll_Wp4acAHUfNTto74MFU,4755
291
+ novelwriter/dialogs/docmerge.py,sha256=HtJvmu56CGb_G27XGRgF3kl0jPR_14SBVsOKv_UyVX8,6286
292
+ novelwriter/dialogs/docsplit.py,sha256=nPb7U68vtZ5yuJtUIr-2yTWCfADCtK4T1h7LgL0Hx8c,9281
293
+ novelwriter/dialogs/editlabel.py,sha256=cs8ztrK1Gi3lEZozvs978dNAR6rnlV8cWr9dZArD51I,2963
294
+ novelwriter/dialogs/preferences.py,sha256=yC2m-eLAo9p0a8b0ffxOolL9-AHF58EtlkSTYEMOUMg,38490
295
+ novelwriter/dialogs/projectsettings.py,sha256=hyRuOYk0FLPkZm8F8e-tx6-1dMRmp3PV8GZYojYpIlc,27635
296
+ novelwriter/dialogs/quotes.py,sha256=JCgoz9I8HepxYYVBXOzQac6aFpzNMF4CRdw4CnAnuNM,4727
297
+ novelwriter/dialogs/wordlist.py,sha256=yuQebLRuasVk2QUm2zWGn7ZzuWM4lFGyXz0egQPyILw,8511
298
+ novelwriter/extensions/configlayout.py,sha256=fHZb8xCCahzQRuP2Y0a36W8i9W1CfgmvBKyh_YKrtf4,9982
300
299
  novelwriter/extensions/eventfilters.py,sha256=mTU_sMQPOEocRfvLcwQyXUpkm314tH32WsID61ss1CI,2522
301
- novelwriter/extensions/modified.py,sha256=hXQeGh6qKdOXjH5mP7OW3nTpZCUksrATVdwyYdjjqRQ,5161
300
+ novelwriter/extensions/modified.py,sha256=kXntkvw1ZWeRxseZyA444bV3O9RbmbErtaDDafu0DwY,5756
302
301
  novelwriter/extensions/novelselector.py,sha256=etVtoDkHGJIP4ab__vStJQCREKYt5sWLfK1vyuO3hLI,3794
303
302
  novelwriter/extensions/pagedsidebar.py,sha256=Brgl_d8KXnWWJov-sTkj9tMQu7Xrz8v7rXcnvpAaRK8,7232
304
- novelwriter/extensions/simpleprogress.py,sha256=Zp50OlnCjO1lxDSWEBnZ6SkdRXOm4E4Qod15MFSr5N8,1807
305
- novelwriter/extensions/statusled.py,sha256=IWLm8ZbOkICczhnCDu5_zaHrlLYcSEFFsAB_fRb6OVk,2292
303
+ novelwriter/extensions/progressbars.py,sha256=BpJHycboSNGYWIfAEMqIy1Qxf32Cg8TeWM3hogzakTs,4628
304
+ novelwriter/extensions/statusled.py,sha256=omaAm_-wpQr7Hw65rlJYWX3mvI0TBx1rpQDWk_3e6rI,2690
306
305
  novelwriter/extensions/switch.py,sha256=4kXJ3EHEhaivj1D69iBi46hkkPBGAt-Rt5EjVK3V4Aw,4299
307
306
  novelwriter/extensions/switchbox.py,sha256=5tCiFWkT9WF9xh2c__BnNAJHFLw2nRso3fJZfwzDqRE,4198
308
307
  novelwriter/extensions/versioninfo.py,sha256=R2_U6B678be0WNxbnhUntpxR5PnZVGf6eeyENp-S-Xo,5035
309
- novelwriter/gui/doceditor.py,sha256=ru4Ub3-sr3awgjwp8EYlunFP6NSBfMgwFDfVoknOp-c,113245
310
- novelwriter/gui/dochighlight.py,sha256=RXzCCx_sMr7qOT3QIsELjdRHs5mr2kKqk2geiKfmaWk,19850
311
- novelwriter/gui/docviewer.py,sha256=9D7n-tcvEL3awQTWahui2g32RoA76M0jQLBt5q4BV3Y,31937
308
+ novelwriter/gui/doceditor.py,sha256=_V_hbCnNZJ9LbPsktPWl64uAoOPixBbsZF1xabPQdfs,113640
309
+ novelwriter/gui/dochighlight.py,sha256=4JNWQkfaEc0p-EvRRkbBWwQdrFqVotgremzu2WWw9hA,19463
310
+ novelwriter/gui/docviewer.py,sha256=iNjjj-1YXXbHySTo94NDvdyTfzV_OJtNOjF4J7qWXvU,32198
312
311
  novelwriter/gui/docviewerpanel.py,sha256=Bh-WT2iSBqhMSxBgWKqNjJ2Erx_Y4BzsXLY_2RkMbMw,19852
313
312
  novelwriter/gui/editordocument.py,sha256=5_v-gwZ9-CwJHGs7lFUGdY3paR7F1PW2FjD6_fbq5wY,4087
314
313
  novelwriter/gui/itemdetails.py,sha256=0U3hghK4Vue3AwtLBRY6YJMN3vOCjatvvzXhJDn4UXo,9688
315
- novelwriter/gui/mainmenu.py,sha256=7pLytuDutOSLbqX10PluAEW6soX4-6NuynGEv7OuSfs,38906
314
+ novelwriter/gui/mainmenu.py,sha256=PaJjO38DQ72UL9hMyvSbh2I1daxOZBSbJhNsov771fw,38908
316
315
  novelwriter/gui/noveltree.py,sha256=rAU_f6efrt5uAsew6jGqo3X3E3ggrZaoQh2prm13wD8,27635
317
- novelwriter/gui/outline.py,sha256=qH4qdf5_gqKC4J_Uj_AQvDrE3-qaHY8cgMU7v8MuSAA,42218
318
- novelwriter/gui/projtree.py,sha256=PQdiSbmQccWBve76plCf4Vs22LsDYdQNzh7pENL21fs,77501
319
- novelwriter/gui/search.py,sha256=mUw9dWTDLz1Jvr9EHelqLMlFygOLpIIn1l-Jr6_0jF8,12958
316
+ novelwriter/gui/outline.py,sha256=hAS6DCPhQtAUrIP4a2qBFa-Rm1fYDS-ijqnEZ2UIbic,42231
317
+ novelwriter/gui/projtree.py,sha256=PUw0NcRqGHpYm1WTqUHflSSekigNJrqEs-Un0oCbGH0,77270
318
+ novelwriter/gui/search.py,sha256=HnS0_vOg15f3woXeZ8MS_ZAblx9aFIuN7BSa195tY1M,13262
320
319
  novelwriter/gui/sidebar.py,sha256=jBkOinx69lwt4m1GovQ7nF44lF-g_SOk3yTT96KlbFY,6212
321
- novelwriter/gui/statusbar.py,sha256=fmw9JZ6CyCsSQg6HyW90_Y-FQ4ahC1HIaCTTb0EHAOk,9236
322
- novelwriter/gui/theme.py,sha256=p9TElPyPn5R_hubKZOOHi7OIbuYU6h0MYLtG0732Ag8,31807
320
+ novelwriter/gui/statusbar.py,sha256=-rF6bIJXGKFRswVKWE1c5In5x3sX4iXMfp0AGxZxt0c,9053
321
+ novelwriter/gui/theme.py,sha256=M1ZbEKAZcU-INROiYyanUsDFNHcAZurArpEDvmg8870,31974
323
322
  novelwriter/text/counting.py,sha256=tkWKWS_scPYmBG8xLpIL1KLIjyF2HOlkrloQa5PZmDc,4304
324
- novelwriter/tools/dictionaries.py,sha256=6w_RwVo0OBYEe7YJfDCCsUfaZ4j1IwVdSB5_e7rz9GA,9363
325
- novelwriter/tools/lipsum.py,sha256=9A9Z5lFjTSIeWKH0t9TdoMyYWFVmeAjakqyOH71FmWI,4878
326
- novelwriter/tools/manusbuild.py,sha256=BZGRvORhpliL-G8zLeuGC-ufzUMWdIUhI3FXJ1aFyIU,14061
327
- novelwriter/tools/manuscript.py,sha256=7Aie12WhbXXvz5GxEhtj14uWMWL778pTdxzFdNIiXvo,37816
328
- novelwriter/tools/manussettings.py,sha256=yfbeuNcJ17LlaJPFZKx5gac341f1eJWYiBcUcKD1mGk,55845
329
- novelwriter/tools/noveldetails.py,sha256=i2Gd3pC9wFmO-wJA9T3OGcH62sGoUALolsjNkBS3rKw,18485
330
- novelwriter/tools/welcome.py,sha256=ZrWQSfY1t3CJGKYx1C8_O2CPfDGsc3ZsHVxHtF7_eyU,27746
331
- novelwriter/tools/writingstats.py,sha256=gorOg4PDgy5k0b4Y2J2CMhiA3aNiEDR3VHOUex1bcQc,22738
332
- novelWriter-2.5b1.dist-info/LICENSE.md,sha256=2GirkkLrPfQqx7fACKRJjtKJUegKc8067erGvcDVQHM,32197
333
- novelWriter-2.5b1.dist-info/METADATA,sha256=XpCwBrY8IT8upLR6jsbFp5LC_pFyYEksFXKKVpaN7Ww,2532
334
- novelWriter-2.5b1.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
335
- novelWriter-2.5b1.dist-info/entry_points.txt,sha256=YDUG1w361LtLsjD3YhxoTDTwM17JA5-nigjC6j5C74A,45
336
- novelWriter-2.5b1.dist-info/top_level.txt,sha256=wFFEucjEeNC_Ap5ULBuEutg5a1Uc0-YO9uFT5L2naNI,12
337
- novelWriter-2.5b1.dist-info/RECORD,,
323
+ novelwriter/text/patterns.py,sha256=sEBPf9buLtJvYeoYquZzDcSC6gfKBHIUPGbD31y5H-g,3843
324
+ novelwriter/tools/dictionaries.py,sha256=92GNCSEOK1EI7t2DiayT8p7nzKW7LwxJJz98F6kn3Vg,9243
325
+ novelwriter/tools/lipsum.py,sha256=NcmoxWzrbEybh_w1FzxuxHmeTr8N03OrxjxsPWEbae4,4794
326
+ novelwriter/tools/manusbuild.py,sha256=c3NdpkAqUPTKN2BpGX_xleFtZPi1G8uv80XBZEp27Bw,14071
327
+ novelwriter/tools/manuscript.py,sha256=77BaTqfytdrqgUxnCLUUVPxx1wScu289xfyBhcHGX-M,37955
328
+ novelwriter/tools/manussettings.py,sha256=Uz7QpCb2l_SftpQ5N7x0qHdq41-6fvTRHv7bxWvDLWg,56145
329
+ novelwriter/tools/noveldetails.py,sha256=xNpTf5-hFu-K_flPhMLug6tNboKvDWV7OEetpHx6Lsc,18481
330
+ novelwriter/tools/welcome.py,sha256=XTTqVqeojZW8hoA6b4nusq4cJ4d1ISoHVPYrEjO4lR0,27759
331
+ novelwriter/tools/writingstats.py,sha256=f5nbmE5V9VsQ8qi_DlvfF5yVIupEbVDavtuMbTzU7IA,22753
332
+ novelWriter-2.5rc1.dist-info/LICENSE.md,sha256=2GirkkLrPfQqx7fACKRJjtKJUegKc8067erGvcDVQHM,32197
333
+ novelWriter-2.5rc1.dist-info/METADATA,sha256=mkaYvtyWGejmUtcwGSmtZlfMcUqrIK4jvejIQ84T4zw,2533
334
+ novelWriter-2.5rc1.dist-info/WHEEL,sha256=cpQTJ5IWu9CdaPViMhC9YzF8gZuS5-vlfoFihTBC86A,91
335
+ novelWriter-2.5rc1.dist-info/entry_points.txt,sha256=YDUG1w361LtLsjD3YhxoTDTwM17JA5-nigjC6j5C74A,45
336
+ novelWriter-2.5rc1.dist-info/top_level.txt,sha256=wFFEucjEeNC_Ap5ULBuEutg5a1Uc0-YO9uFT5L2naNI,12
337
+ novelWriter-2.5rc1.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: bdist_wheel (0.43.0)
2
+ Generator: setuptools (70.1.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
novelwriter/__init__.py CHANGED
@@ -47,9 +47,9 @@ __license__ = "GPLv3"
47
47
  __author__ = "Veronica Berglyd Olsen"
48
48
  __maintainer__ = "Veronica Berglyd Olsen"
49
49
  __email__ = "code@vkbo.net"
50
- __version__ = "2.5b1"
51
- __hexversion__ = "0x020500b1"
52
- __date__ = "2024-05-26"
50
+ __version__ = "2.5rc1"
51
+ __hexversion__ = "0x020500c1"
52
+ __date__ = "2024-06-22"
53
53
  __status__ = "Stable"
54
54
  __domain__ = "novelwriter.io"
55
55
 
Binary file
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "Synopsis": "Sinopse",
3
3
  "Short Description": "Descrição breve",
4
- "Comment": "Comentários",
4
+ "Comment": "Comentário",
5
5
  "Notes": "Notas",
6
6
  "Tag": "Etiqueta",
7
7
  "Point of View": "Ponto de vista",
@@ -30,87 +30,87 @@
30
30
  "14": "Quatorze",
31
31
  "15": "Quinze",
32
32
  "16": "Dezesseis",
33
- "17": "Dezesete",
33
+ "17": "Dezessete",
34
34
  "18": "Dezoito",
35
35
  "19": "Dezenove",
36
36
  "20": "Vinte",
37
- "21": "Vinte e Um",
38
- "22": "Vinte e Dois",
39
- "23": "Vinte e Três",
40
- "24": "Vinte e Quatro",
41
- "25": "Vinte e Cinco",
42
- "26": "Vinte e Seis",
43
- "27": "Vinte e Sete",
44
- "28": "Vinte e Oito",
45
- "29": "Vinte e Nove",
37
+ "21": "Vinte e um",
38
+ "22": "Vinte e dois",
39
+ "23": "Vinte e três",
40
+ "24": "Vinte e quatro",
41
+ "25": "Vinte e cinco",
42
+ "26": "Vinte e seis",
43
+ "27": "Vinte e sete",
44
+ "28": "Vinte e oito",
45
+ "29": "Vinte e nove",
46
46
  "30": "Trinta",
47
- "31": "Trinta e Um",
48
- "32": "Trinta e Dois",
49
- "33": "Trinta e Três",
50
- "34": "Trinta e Quatro",
51
- "35": "Trinta e Cinco",
52
- "36": "Trinta e Seis",
53
- "37": "Trinta e Sete",
54
- "38": "Trinta e Oito",
55
- "39": "Trinta e Nove",
47
+ "31": "Trinta e um",
48
+ "32": "Trinta e dois",
49
+ "33": "Trinta e três",
50
+ "34": "Trinta e quatro",
51
+ "35": "Trinta e cinco",
52
+ "36": "Trinta e seis",
53
+ "37": "Trinta e sete",
54
+ "38": "Trinta e oito",
55
+ "39": "Trinta e nove",
56
56
  "40": "Quarenta",
57
- "41": "Quarenta e Um",
58
- "42": "Quarenta e Dois",
59
- "43": "Quarenta e Três",
60
- "44": "Quarenta e Quatro",
61
- "45": "Quarenta e Cinco",
62
- "46": "Quarenta e Seis",
63
- "47": "Quarenta e Sete",
64
- "48": "Quarenta e Oito",
65
- "49": "Quarenta e Nove",
57
+ "41": "Quarenta e um",
58
+ "42": "Quarenta e dois",
59
+ "43": "Quarenta e três",
60
+ "44": "Quarenta e quatro",
61
+ "45": "Quarenta e cinco",
62
+ "46": "Quarenta e seis",
63
+ "47": "Quarenta e sete",
64
+ "48": "Quarenta e oito",
65
+ "49": "Quarenta e nove",
66
66
  "50": "Cinquenta",
67
- "51": "Cinquenta e Um",
68
- "52": "Cinquenta e Dois",
69
- "53": "Cinquenta e Três",
70
- "54": "Cinquenta e Quatro",
71
- "55": "Cinquenta e Cinco",
72
- "56": "Cinquenta e Seis",
73
- "57": "Cinquenta e Sete",
74
- "58": "Cinquenta e Oito",
75
- "59": "Cinquenta e Nove",
67
+ "51": "Cinquenta e um",
68
+ "52": "Cinquenta e dois",
69
+ "53": "Cinquenta e três",
70
+ "54": "Cinquenta e quatro",
71
+ "55": "Cinquenta e cinco",
72
+ "56": "Cinquenta e seis",
73
+ "57": "Cinquenta e sete",
74
+ "58": "Cinquenta e oito",
75
+ "59": "Cinquenta e nove",
76
76
  "60": "Sessenta",
77
- "61": "Sessenta e Um",
78
- "62": "Sessenta e Dois",
79
- "63": "Sessenta e Três",
80
- "64": "Sessenta e Quatro",
81
- "65": "Sessenta e Cinco",
82
- "66": "Sessenta e Seis",
83
- "67": "Sessenta e Sete",
84
- "68": "Sessenta e Oito",
85
- "69": "Sessenta e Nove",
77
+ "61": "Sessenta e um",
78
+ "62": "Sessenta e dois",
79
+ "63": "Sessenta e três",
80
+ "64": "Sessenta e quatro",
81
+ "65": "Sessenta e cinco",
82
+ "66": "Sessenta e seis",
83
+ "67": "Sessenta e sete",
84
+ "68": "Sessenta e oito",
85
+ "69": "Sessenta e nove",
86
86
  "70": "Setenta",
87
- "71": "Setenta e Um",
88
- "72": "Setenta e Dois",
89
- "73": "Setenta e Três",
90
- "74": "Setenta e Quatro",
91
- "75": "Setenta e Cinco",
92
- "76": "Setenta e Seis",
93
- "77": "Setenta e Sete",
94
- "78": "Setenta e Oito",
95
- "79": "Setenta e Nove",
87
+ "71": "Setenta e um",
88
+ "72": "Setenta e dois",
89
+ "73": "Setenta e três",
90
+ "74": "Setenta e quatro",
91
+ "75": "Setenta e cinco",
92
+ "76": "Setenta e seis",
93
+ "77": "Setenta e sete",
94
+ "78": "Setenta e oito",
95
+ "79": "Setenta e nove",
96
96
  "80": "Oitenta",
97
- "81": "Oitenta e Um",
98
- "82": "Oitenta e Dois",
99
- "83": "Oitenta e Três",
100
- "84": "Oitenta e Quatro",
101
- "85": "Oitenta e Cinco",
102
- "86": "Oitenta e Seis",
103
- "87": "Oitenta e Sete",
104
- "88": "Oitenta e Oito",
105
- "89": "Oitenta e Nove",
97
+ "81": "Oitenta e um",
98
+ "82": "Oitenta e dois",
99
+ "83": "Oitenta e três",
100
+ "84": "Oitenta e quatro",
101
+ "85": "Oitenta e cinco",
102
+ "86": "Oitenta e seis",
103
+ "87": "Oitenta e sete",
104
+ "88": "Oitenta e oito",
105
+ "89": "Oitenta e nove",
106
106
  "90": "Noventa",
107
- "91": "Noventa e Um",
108
- "92": "Noventa e Dois",
109
- "93": "Noventa e Três",
110
- "94": "Noventa e Quatro",
111
- "95": "Noventa e Cinco",
112
- "96": "Noventa e Seis",
113
- "97": "Noventa e Sete",
114
- "98": "Noventa e Oito",
115
- "99": "Noventa e Nove"
107
+ "91": "Noventa e um",
108
+ "92": "Noventa e dois",
109
+ "93": "Noventa e três",
110
+ "94": "Noventa e quatro",
111
+ "95": "Noventa e cinco",
112
+ "96": "Noventa e seis",
113
+ "97": "Noventa e sete",
114
+ "98": "Noventa e oito",
115
+ "99": "Noventa e nove"
116
116
  }
Binary file
Binary file
@@ -25,6 +25,7 @@ linkvisited = 50, 0, 80
25
25
 
26
26
  [GUI]
27
27
  helptext = 97, 97, 97
28
+ fadedtext = 97, 97, 97
28
29
  errortext = 255, 77, 77
29
30
  statusnone = 50, 50, 50
30
31
  statussaved = 77, 255, 77
@@ -26,6 +26,7 @@ linkvisited = 102, 153, 204
26
26
 
27
27
  [GUI]
28
28
  helptext = 164, 164, 164
29
+ fadedtext = 148, 148, 148
29
30
  errortext = 255, 164, 164
30
31
  statusnone = 150, 152, 150
31
32
  statussaved = 39, 135, 78
@@ -26,6 +26,7 @@ linkvisited = 66, 113, 174
26
26
 
27
27
  [GUI]
28
28
  helptext = 92, 92, 92
29
+ fadedtext = 108, 108, 108
29
30
  errortext = 255, 92, 92
30
31
  statusnone = 120, 120, 120
31
32
  statussaved = 200, 15, 39
@@ -41,6 +41,7 @@ linkvisited = 139, 233, 253
41
41
 
42
42
  [GUI]
43
43
  helptext = 204, 172, 249
44
+ fadedtext = 98, 114, 164
44
45
  errortext = 255, 85, 85
45
46
  statusnone = 98, 114, 164
46
47
  statussaved = 80, 250, 123
@@ -25,6 +25,7 @@ linkvisited = 38, 139, 210
25
25
 
26
26
  [GUI]
27
27
  helptext = 166, 161, 149
28
+ fadedtext = 166, 161, 149
28
29
  errortext = 255, 161, 149
29
30
  statusnone = 88, 110, 117
30
31
  statussaved = 42, 161, 152
@@ -25,6 +25,7 @@ linkvisited = 38, 139, 210
25
25
 
26
26
  [GUI]
27
27
  helptext = 78, 91, 95
28
+ fadedtext = 78, 91, 95
28
29
  errortext = 255, 91, 95
29
30
  statusnone = 88, 110, 117
30
31
  statussaved = 42, 161, 152
novelwriter/common.py CHANGED
@@ -523,12 +523,11 @@ def readTextFile(path: str | Path) -> str:
523
523
 
524
524
 
525
525
  def makeFileNameSafe(text: str) -> str:
526
- """Return a filename safe string.
526
+ """Return a filename-safe string.
527
527
  See: https://unicode.org/reports/tr15/#Norm_Forms
528
528
  """
529
529
  text = unicodedata.normalize("NFKC", text).strip()
530
- allowed = (" ", ".", "-", "_")
531
- return "".join(c for c in text if c.isalnum() or c in allowed)
530
+ return "".join(c for c in text if c.isprintable() and c not in r'\/:*?"<>|')
532
531
 
533
532
 
534
533
  def getFileSize(path: Path) -> int:
novelwriter/config.py CHANGED
@@ -5,6 +5,7 @@ novelWriter – Config Class
5
5
  File History:
6
6
  Created: 2018-09-22 [0.0.1] Config
7
7
  Created: 2022-11-09 [2.0rc2] RecentProjects
8
+ Created: 2024-06-16 [2.5rc1] RecentPaths
8
9
 
9
10
  This file is a part of novelWriter
10
11
  Copyright 2018–2024, Veronica Berglyd Olsen
@@ -103,7 +104,8 @@ class Config:
103
104
  # User Settings
104
105
  # =============
105
106
 
106
- self._recentObj = RecentProjects(self)
107
+ self._recentProjects = RecentProjects(self)
108
+ self._recentPaths = RecentPaths(self)
107
109
 
108
110
  # General GUI Settings
109
111
  self.guiLocale = self._qLocale.name()
@@ -180,7 +182,6 @@ class Config:
180
182
  self.fmtPadThin = False
181
183
 
182
184
  # User Paths
183
- self._lastPath = self._homePath # The user's last used path
184
185
  self._backupPath = self._backPath # Backup path to use, can be none
185
186
 
186
187
  # Spell Checking Settings
@@ -253,7 +254,7 @@ class Config:
253
254
 
254
255
  @property
255
256
  def recentProjects(self) -> RecentProjects:
256
- return self._recentObj
257
+ return self._recentProjects
257
258
 
258
259
  @property
259
260
  def mainWinSize(self) -> list[int]:
@@ -343,7 +344,7 @@ class Config:
343
344
  self._outlnPanePos = [int(x/self.guiScale) for x in pos]
344
345
  return
345
346
 
346
- def setLastPath(self, path: str | Path) -> None:
347
+ def setLastPath(self, key: str, path: str | Path) -> None:
347
348
  """Set the last used path. Only the folder is saved, so if the
348
349
  path is not a folder, the parent of the path is used instead.
349
350
  """
@@ -352,8 +353,7 @@ class Config:
352
353
  if not path.is_dir():
353
354
  path = path.parent
354
355
  if path.is_dir():
355
- self._lastPath = path
356
- logger.debug("Last path updated: %s" % self._lastPath)
356
+ self._recentPaths.setPath(key, path)
357
357
  return
358
358
 
359
359
  def setBackupPath(self, path: Path | str) -> None:
@@ -438,11 +438,12 @@ class Config:
438
438
  return self._appPath / "assets" / target
439
439
  return self._appPath / "assets"
440
440
 
441
- def lastPath(self) -> Path:
441
+ def lastPath(self, key: str) -> Path:
442
442
  """Return the last path used by the user, if it exists."""
443
- if isinstance(self._lastPath, Path):
444
- if self._lastPath.is_dir():
445
- return self._lastPath
443
+ if path := self._recentPaths.getPath(key):
444
+ asPath = Path(path)
445
+ if asPath.is_dir():
446
+ return asPath
446
447
  return self._homePath
447
448
 
448
449
  def backupPath(self) -> Path:
@@ -516,7 +517,6 @@ class Config:
516
517
  logger.debug("Data Path: %s", self._dataPath)
517
518
  logger.debug("App Root: %s", self._appRoot)
518
519
  logger.debug("App Path: %s", self._appPath)
519
- logger.debug("Last Path: %s", self._lastPath)
520
520
  logger.debug("PDF Manual: %s", self.pdfDocs)
521
521
 
522
522
  # If the config and data folders don't exist, create them
@@ -531,7 +531,8 @@ class Config:
531
531
  (self._dataPath / "syntax").mkdir(exist_ok=True)
532
532
  (self._dataPath / "themes").mkdir(exist_ok=True)
533
533
 
534
- self._recentObj.loadCache()
534
+ self._recentPaths.loadCache()
535
+ self._recentProjects.loadCache()
535
536
  self._checkOptionalPackages()
536
537
 
537
538
  logger.debug("Config instance initialised")
@@ -600,7 +601,6 @@ class Config:
600
601
  self.hideHScroll = conf.rdBool(sec, "hidehscroll", self.hideHScroll)
601
602
  self.lastNotes = conf.rdStr(sec, "lastnotes", self.lastNotes)
602
603
  self.nativeFont = conf.rdBool(sec, "nativefont", self.nativeFont)
603
- self._lastPath = conf.rdPath(sec, "lastpath", self._lastPath)
604
604
 
605
605
  # Sizes
606
606
  sec = "Sizes"
@@ -710,7 +710,6 @@ class Config:
710
710
  "hidehscroll": str(self.hideHScroll),
711
711
  "lastnotes": str(self.lastNotes),
712
712
  "nativefont": str(self.nativeFont),
713
- "lastpath": str(self._lastPath),
714
713
  }
715
714
 
716
715
  conf["Sizes"] = {
@@ -811,7 +810,7 @@ class Config:
811
810
  """Pack a list of items into a comma-separated string for saving
812
811
  to the config file.
813
812
  """
814
- return ", ".join([str(inVal) for inVal in data])
813
+ return ", ".join(str(inVal) for inVal in data)
815
814
 
816
815
  def _checkOptionalPackages(self) -> None:
817
816
  """Check optional packages used by some features."""
@@ -893,3 +892,56 @@ class RecentProjects:
893
892
  logger.debug("Removed recent: %s", path)
894
893
  self.saveCache()
895
894
  return
895
+
896
+
897
+ class RecentPaths:
898
+
899
+ KEYS = ["default", "project", "import", "outline", "stats"]
900
+
901
+ def __init__(self, config: Config) -> None:
902
+ self._conf = config
903
+ self._data = {}
904
+ return
905
+
906
+ def setPath(self, key: str, path: Path | str) -> None:
907
+ """Set a path for a given key, and save the cache."""
908
+ if key in self.KEYS:
909
+ self._data[key] = str(path)
910
+ self.saveCache()
911
+ return
912
+
913
+ def getPath(self, key: str) -> str | None:
914
+ """Get a path for a given key, or return None."""
915
+ return self._data.get(key)
916
+
917
+ def loadCache(self) -> bool:
918
+ """Load the cache file for recent paths."""
919
+ self._data = {}
920
+ cacheFile = self._conf.dataPath(nwFiles.RECENT_PATH)
921
+ if cacheFile.is_file():
922
+ try:
923
+ with open(cacheFile, mode="r", encoding="utf-8") as inFile:
924
+ data = json.load(inFile)
925
+ if isinstance(data, dict):
926
+ for key, path in data.items():
927
+ if key in self.KEYS and isinstance(path, str):
928
+ self._data[key] = path
929
+ except Exception:
930
+ logger.error("Could not load recent paths cache")
931
+ logException()
932
+ return False
933
+ return True
934
+
935
+ def saveCache(self) -> bool:
936
+ """Save the cache dictionary of recent paths."""
937
+ cacheFile = self._conf.dataPath(nwFiles.RECENT_PATH)
938
+ cacheTemp = cacheFile.with_suffix(".tmp")
939
+ try:
940
+ with open(cacheTemp, mode="w+", encoding="utf-8") as outFile:
941
+ json.dump(self._data, outFile, indent=2)
942
+ cacheTemp.replace(cacheFile)
943
+ except Exception:
944
+ logger.error("Could not save recent paths cache")
945
+ logException()
946
+ return False
947
+ return True