novelWriter 2.4.2__py3-none-any.whl → 2.4.4__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.
- {novelWriter-2.4.2.dist-info → novelWriter-2.4.4.dist-info}/METADATA +1 -1
- {novelWriter-2.4.2.dist-info → novelWriter-2.4.4.dist-info}/RECORD +20 -20
- novelwriter/__init__.py +3 -3
- novelwriter/assets/i18n/nw_pt_BR.qm +0 -0
- novelwriter/assets/i18n/project_pt_BR.json +74 -74
- novelwriter/assets/manual.pdf +0 -0
- novelwriter/assets/sample.zip +0 -0
- novelwriter/extensions/modified.py +13 -1
- novelwriter/gui/doceditor.py +52 -25
- novelwriter/gui/docviewer.py +33 -21
- novelwriter/gui/projtree.py +5 -6
- novelwriter/gui/theme.py +3 -3
- novelwriter/shared.py +13 -0
- novelwriter/tools/dictionaries.py +5 -4
- novelwriter/tools/manuscript.py +20 -14
- novelwriter/tools/manussettings.py +7 -5
- {novelWriter-2.4.2.dist-info → novelWriter-2.4.4.dist-info}/LICENSE.md +0 -0
- {novelWriter-2.4.2.dist-info → novelWriter-2.4.4.dist-info}/WHEEL +0 -0
- {novelWriter-2.4.2.dist-info → novelWriter-2.4.4.dist-info}/entry_points.txt +0 -0
- {novelWriter-2.4.2.dist-info → novelWriter-2.4.4.dist-info}/top_level.txt +0 -0
@@ -1,14 +1,14 @@
|
|
1
|
-
novelwriter/__init__.py,sha256=
|
1
|
+
novelwriter/__init__.py,sha256=_CJImzuDGASfUJUwJ6dCQnZT0pHK8G0tH-0Fa5iouHg,7744
|
2
2
|
novelwriter/common.py,sha256=oarn4-2Ezm595b-dHD4MVrytxMFFB_QhITbTMIKD40M,17440
|
3
3
|
novelwriter/config.py,sha256=Y0c3-0xfmDE-IDcFYW0U_x_WGPMoU2T0sqtNZ8CT4zQ,35841
|
4
4
|
novelwriter/constants.py,sha256=UIxiF-23cB_gmRfxbQPYmObn8Ib-ygm46uOIG329RLY,19818
|
5
5
|
novelwriter/enum.py,sha256=MP-nz3vDRp4bWxXitqjdLWO2_RvrDAlRxngiMON9mb8,3305
|
6
6
|
novelwriter/error.py,sha256=rY3kHVkt7W0MM9iKOBkMY-9qhStlESGlyeOOXwT4BGM,7278
|
7
7
|
novelwriter/guimain.py,sha256=Be32lkJv1ZF-aOSOQTPBfcH7TFrk3KvpLBmwIl20eRc,53477
|
8
|
-
novelwriter/shared.py,sha256=
|
8
|
+
novelwriter/shared.py,sha256=CIzGQcCEAPnFRLRbzPH2m0gcPYDtCZt8PSIdEKKBw7w,15158
|
9
9
|
novelwriter/types.py,sha256=6aP2hZraPEolYqBgj5R_5bah3NgelASBfKol6yYOi4g,3316
|
10
|
-
novelwriter/assets/manual.pdf,sha256=
|
11
|
-
novelwriter/assets/sample.zip,sha256=
|
10
|
+
novelwriter/assets/manual.pdf,sha256=TzPxpJnrik0Na6XaHjrCKctCXCQT-gmga9tysESLrRY,2691197
|
11
|
+
novelwriter/assets/sample.zip,sha256=zCNbDDyjElPMp4O37qDJuW_rYkR9-Q_VuEk98q3ZP44,27358
|
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=
|
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=EcQAVEiQgRL3qobuzkPTfOWIxAc3Om-tA7nXUFFXEdI,2483
|
@@ -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=
|
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
|
@@ -290,7 +290,7 @@ novelwriter/dialogs/wordlist.py,sha256=EfjKQn_SZ8qUCXXw5WHgqe6hWLAn02cD23mWUTTax
|
|
290
290
|
novelwriter/extensions/circularprogress.py,sha256=H0btKccdnvVfijU8ZudYvv4AgrvPYvx7IgznIxASBY0,3856
|
291
291
|
novelwriter/extensions/configlayout.py,sha256=xHUE_HckNwJsfPKZ3hJjAKAYhxzQFRmNCmBrIh6QtTs,9253
|
292
292
|
novelwriter/extensions/eventfilters.py,sha256=XehDoXwsnCvI1D3uieuYu5J3kxZggdV6Teo7Z0xZw7E,2581
|
293
|
-
novelwriter/extensions/modified.py,sha256=
|
293
|
+
novelwriter/extensions/modified.py,sha256=KT2Qo3YsZO5dKzjYhA46Kg-T7fCcm6FyhQrmvrNwgSk,4464
|
294
294
|
novelwriter/extensions/novelselector.py,sha256=5ccEDvqrbvrG7khZBrOiJwxsjjRnkFX-A4ZT-lj_z_g,3821
|
295
295
|
novelwriter/extensions/pagedsidebar.py,sha256=X0AYo6oKM7gKr57662v-ZZWUTCVf5AbvIUCoLQai8fk,7369
|
296
296
|
novelwriter/extensions/simpleprogress.py,sha256=13SrFQ9TZTDICyXCdTHeCX0MOtpw4UbBEgxiAmSOjyQ,1836
|
@@ -298,32 +298,32 @@ novelwriter/extensions/statusled.py,sha256=640phDm3ZcLvM9EC_uwVPjG9LD5W3pAjtoqU4
|
|
298
298
|
novelwriter/extensions/switch.py,sha256=sZBNX5Wj1qkVA6cHh04GjuWOTbejaatHgLZ5yGzXGv4,4346
|
299
299
|
novelwriter/extensions/switchbox.py,sha256=y6yuoCAZYYL7miaFlC8h5ymtuB0Xyk2AMmxAFYOYPDA,4210
|
300
300
|
novelwriter/extensions/versioninfo.py,sha256=eUJzO6eV6SFXgp71uxr9696rjUQctGm84CA7XqxFhGc,5120
|
301
|
-
novelwriter/gui/doceditor.py,sha256=
|
301
|
+
novelwriter/gui/doceditor.py,sha256=d96MDOqdLb4y8cR25ah5KGZGvfFADPT33bDBd7O7kzA,114599
|
302
302
|
novelwriter/gui/dochighlight.py,sha256=9-OP0YrMmljOCsdY-rqZe0G27gkBP7Fzk_R_f3iGGVE,17394
|
303
|
-
novelwriter/gui/docviewer.py,sha256=
|
303
|
+
novelwriter/gui/docviewer.py,sha256=RcvChY8OA5gxHzNi6l3xj60ua_6nPxSQ75_apIgeyDg,33559
|
304
304
|
novelwriter/gui/docviewerpanel.py,sha256=IcQGLN49MmVGfIPg-8IzLGKYn9DbJqfdXWG6jd_JaAI,20009
|
305
305
|
novelwriter/gui/editordocument.py,sha256=jxODONgq80Kf63lRezzbYtyEelaC-GpvgPEMKQ3m_sg,4116
|
306
306
|
novelwriter/gui/itemdetails.py,sha256=VIfWDtn9g0IRBYSDFT_AhZgluQ0d7sK5C14lENyvzHg,9774
|
307
307
|
novelwriter/gui/mainmenu.py,sha256=iTXNqmhEZqVDA6XkIAhpIq-cc1fF5-rZVe2g9z7v8_c,38707
|
308
308
|
novelwriter/gui/noveltree.py,sha256=F-r6vdgCoIzxFwOI9kvsLEnz7nX2uOs30LOHHijN7NY,27988
|
309
309
|
novelwriter/gui/outline.py,sha256=q0d21UI2r4K4D9jPARKc3ibWsdpiEnartAHfwxE2AgY,42410
|
310
|
-
novelwriter/gui/projtree.py,sha256=
|
310
|
+
novelwriter/gui/projtree.py,sha256=lfGkIBAwi71KrnzpdsfpaSGw4rv8JsD5F7TTjDvkcGA,77927
|
311
311
|
novelwriter/gui/search.py,sha256=PYsSIhe77PCuXj1fRXb2_7GF1gxLDv_vyq8JsgW5UfY,12996
|
312
312
|
novelwriter/gui/sidebar.py,sha256=kidGGzXQ5RNQvKuH0kFh-lwoUSlkXffBucEoL15RMd4,6258
|
313
313
|
novelwriter/gui/statusbar.py,sha256=ru-4pyg8owWkwkXGgj5GEupfq9fbIykYwGpomwzaINk,9353
|
314
|
-
novelwriter/gui/theme.py,sha256=
|
314
|
+
novelwriter/gui/theme.py,sha256=ANv1e5KghrB8z-uaHZbc3GZdmcl_or6KOpFhyBbgeX4,32781
|
315
315
|
novelwriter/text/counting.py,sha256=tkWKWS_scPYmBG8xLpIL1KLIjyF2HOlkrloQa5PZmDc,4304
|
316
|
-
novelwriter/tools/dictionaries.py,sha256=
|
316
|
+
novelwriter/tools/dictionaries.py,sha256=cEdkqXowPZJV9hD01EmYB6PDGsMFYwVQ7QLEt_jthOk,9308
|
317
317
|
novelwriter/tools/lipsum.py,sha256=d-qdRSrXLfTkTdzi7vhjeBlWawwGwWQ9Qd_zRSwzgpQ,4901
|
318
318
|
novelwriter/tools/manusbuild.py,sha256=80kRr4OfvW2lqjhLpnAWO8HiTX7Y3HSivcjT48v_KUE,14101
|
319
|
-
novelwriter/tools/manuscript.py,sha256=
|
320
|
-
novelwriter/tools/manussettings.py,sha256=
|
319
|
+
novelwriter/tools/manuscript.py,sha256=lI7xV8KxnuPQt26sN2m-kKORqK3hInepm5Bc8FYhgjk,40510
|
320
|
+
novelwriter/tools/manussettings.py,sha256=xMbamo3AKASz2NkJCIQYlvGPXE_rVeJQjxIXz2c57Bg,55754
|
321
321
|
novelwriter/tools/noveldetails.py,sha256=KoENyz0hH3TlXfRCEJvRTZ0h7ruOgTIv85AgCl1Ur5o,18503
|
322
322
|
novelwriter/tools/welcome.py,sha256=BxORHBPjqumEVNZC7SytE3kUasx01GMOKS5QQSagP-M,27954
|
323
323
|
novelwriter/tools/writingstats.py,sha256=IubrbbLB_Qlnwp9B3muKkeD84xtckPvmTax7E4LnI5g,22797
|
324
|
-
novelWriter-2.4.
|
325
|
-
novelWriter-2.4.
|
326
|
-
novelWriter-2.4.
|
327
|
-
novelWriter-2.4.
|
328
|
-
novelWriter-2.4.
|
329
|
-
novelWriter-2.4.
|
324
|
+
novelWriter-2.4.4.dist-info/LICENSE.md,sha256=2GirkkLrPfQqx7fACKRJjtKJUegKc8067erGvcDVQHM,32197
|
325
|
+
novelWriter-2.4.4.dist-info/METADATA,sha256=y8mt-5n0Fuv5tb5iMrqkhYyZW_t_w8qFWknSFE3h1AE,2582
|
326
|
+
novelWriter-2.4.4.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
|
327
|
+
novelWriter-2.4.4.dist-info/entry_points.txt,sha256=YDUG1w361LtLsjD3YhxoTDTwM17JA5-nigjC6j5C74A,45
|
328
|
+
novelWriter-2.4.4.dist-info/top_level.txt,sha256=wFFEucjEeNC_Ap5ULBuEutg5a1Uc0-YO9uFT5L2naNI,12
|
329
|
+
novelWriter-2.4.4.dist-info/RECORD,,
|
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.4.
|
51
|
-
__hexversion__ = "
|
52
|
-
__date__ = "2024-
|
50
|
+
__version__ = "2.4.4"
|
51
|
+
__hexversion__ = "0x020404f0"
|
52
|
+
__date__ = "2024-06-12"
|
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": "
|
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": "
|
33
|
+
"17": "Dezessete",
|
34
34
|
"18": "Dezoito",
|
35
35
|
"19": "Dezenove",
|
36
36
|
"20": "Vinte",
|
37
|
-
"21": "Vinte e
|
38
|
-
"22": "Vinte e
|
39
|
-
"23": "Vinte e
|
40
|
-
"24": "Vinte e
|
41
|
-
"25": "Vinte e
|
42
|
-
"26": "Vinte e
|
43
|
-
"27": "Vinte e
|
44
|
-
"28": "Vinte e
|
45
|
-
"29": "Vinte e
|
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
|
48
|
-
"32": "Trinta e
|
49
|
-
"33": "Trinta e
|
50
|
-
"34": "Trinta e
|
51
|
-
"35": "Trinta e
|
52
|
-
"36": "Trinta e
|
53
|
-
"37": "Trinta e
|
54
|
-
"38": "Trinta e
|
55
|
-
"39": "Trinta e
|
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
|
58
|
-
"42": "Quarenta e
|
59
|
-
"43": "Quarenta e
|
60
|
-
"44": "Quarenta e
|
61
|
-
"45": "Quarenta e
|
62
|
-
"46": "Quarenta e
|
63
|
-
"47": "Quarenta e
|
64
|
-
"48": "Quarenta e
|
65
|
-
"49": "Quarenta e
|
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
|
68
|
-
"52": "Cinquenta e
|
69
|
-
"53": "Cinquenta e
|
70
|
-
"54": "Cinquenta e
|
71
|
-
"55": "Cinquenta e
|
72
|
-
"56": "Cinquenta e
|
73
|
-
"57": "Cinquenta e
|
74
|
-
"58": "Cinquenta e
|
75
|
-
"59": "Cinquenta e
|
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
|
78
|
-
"62": "Sessenta e
|
79
|
-
"63": "Sessenta e
|
80
|
-
"64": "Sessenta e
|
81
|
-
"65": "Sessenta e
|
82
|
-
"66": "Sessenta e
|
83
|
-
"67": "Sessenta e
|
84
|
-
"68": "Sessenta e
|
85
|
-
"69": "Sessenta e
|
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
|
88
|
-
"72": "Setenta e
|
89
|
-
"73": "Setenta e
|
90
|
-
"74": "Setenta e
|
91
|
-
"75": "Setenta e
|
92
|
-
"76": "Setenta e
|
93
|
-
"77": "Setenta e
|
94
|
-
"78": "Setenta e
|
95
|
-
"79": "Setenta e
|
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
|
98
|
-
"82": "Oitenta e
|
99
|
-
"83": "Oitenta e
|
100
|
-
"84": "Oitenta e
|
101
|
-
"85": "Oitenta e
|
102
|
-
"86": "Oitenta e
|
103
|
-
"87": "Oitenta e
|
104
|
-
"88": "Oitenta e
|
105
|
-
"89": "Oitenta e
|
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
|
108
|
-
"92": "Noventa e
|
109
|
-
"93": "Noventa e
|
110
|
-
"94": "Noventa e
|
111
|
-
"95": "Noventa e
|
112
|
-
"96": "Noventa e
|
113
|
-
"97": "Noventa e
|
114
|
-
"98": "Noventa e
|
115
|
-
"99": "Noventa e
|
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
|
}
|
novelwriter/assets/manual.pdf
CHANGED
Binary file
|
novelwriter/assets/sample.zip
CHANGED
Binary file
|
@@ -27,11 +27,23 @@ from __future__ import annotations
|
|
27
27
|
|
28
28
|
from PyQt5.QtCore import QSize, Qt
|
29
29
|
from PyQt5.QtGui import QWheelEvent
|
30
|
-
from PyQt5.QtWidgets import QComboBox, QDoubleSpinBox, QSpinBox, QToolButton, QWidget
|
30
|
+
from PyQt5.QtWidgets import QComboBox, QDialog, QDoubleSpinBox, QSpinBox, QToolButton, QWidget
|
31
31
|
|
32
32
|
from novelwriter import SHARED
|
33
33
|
|
34
34
|
|
35
|
+
class NDialog(QDialog):
|
36
|
+
|
37
|
+
def softDelete(self) -> None:
|
38
|
+
"""Since calling deleteLater is sometimes not safe from Python,
|
39
|
+
as the C++ object can be deleted before the Python process is
|
40
|
+
done with the object, we instead set the dialog's parent to None
|
41
|
+
so that it gets garbage collected when it runs out of scope.
|
42
|
+
"""
|
43
|
+
self.setParent(None) # type: ignore
|
44
|
+
return
|
45
|
+
|
46
|
+
|
35
47
|
class NComboBox(QComboBox):
|
36
48
|
|
37
49
|
def __init__(self, parent: QWidget | None = None) -> None:
|
novelwriter/gui/doceditor.py
CHANGED
@@ -43,8 +43,8 @@ from PyQt5.QtCore import (
|
|
43
43
|
pyqtSignal, pyqtSlot
|
44
44
|
)
|
45
45
|
from PyQt5.QtGui import (
|
46
|
-
QColor, QCursor,
|
47
|
-
|
46
|
+
QColor, QCursor, QKeyEvent, QKeySequence, QMouseEvent, QPalette, QPixmap,
|
47
|
+
QResizeEvent, QTextBlock, QTextCursor, QTextDocument, QTextOption
|
48
48
|
)
|
49
49
|
from PyQt5.QtWidgets import (
|
50
50
|
QAction, QApplication, QFrame, QGridLayout, QHBoxLayout, QLabel, QLineEdit,
|
@@ -329,10 +329,7 @@ class GuiDocEditor(QPlainTextEdit):
|
|
329
329
|
SHARED.updateSpellCheckLanguage()
|
330
330
|
|
331
331
|
# Set font
|
332
|
-
|
333
|
-
font.setFamily(CONFIG.textFont)
|
334
|
-
font.setPointSize(CONFIG.textSize)
|
335
|
-
self._qDocument.setDefaultFont(font)
|
332
|
+
self.initFont()
|
336
333
|
|
337
334
|
# Update highlighter settings
|
338
335
|
self._qDocument.syntaxHighlighter.initHighlighter()
|
@@ -382,6 +379,23 @@ class GuiDocEditor(QPlainTextEdit):
|
|
382
379
|
|
383
380
|
return
|
384
381
|
|
382
|
+
def initFont(self) -> None:
|
383
|
+
"""Set the font of the main widget and sub-widgets. This needs
|
384
|
+
special attention since there appears to be a bug in Qt 5.15.3.
|
385
|
+
See issues #1862 and #1875.
|
386
|
+
"""
|
387
|
+
font = self.font()
|
388
|
+
font.setFamily(CONFIG.textFont)
|
389
|
+
font.setPointSize(CONFIG.textSize)
|
390
|
+
self.setFont(font)
|
391
|
+
|
392
|
+
# Reset sub-widget font to GUI font
|
393
|
+
self.docHeader.updateFont()
|
394
|
+
self.docFooter.updateFont()
|
395
|
+
self.docSearch.updateFont()
|
396
|
+
|
397
|
+
return
|
398
|
+
|
385
399
|
def loadText(self, tHandle: str, tLine: int | None = None) -> bool:
|
386
400
|
"""Load text from a document into the editor. If we have an I/O
|
387
401
|
error, we must handle this and clear the editor so that we don't
|
@@ -2396,9 +2410,6 @@ class GuiDocEditSearch(QFrame):
|
|
2396
2410
|
iSz = SHARED.theme.baseIconSize
|
2397
2411
|
mPx = CONFIG.pxInt(6)
|
2398
2412
|
|
2399
|
-
self.boxFont = SHARED.theme.guiFont
|
2400
|
-
self.boxFont.setPointSizeF(0.9*SHARED.theme.fontPointSize)
|
2401
|
-
|
2402
2413
|
self.setContentsMargins(0, 0, 0, 0)
|
2403
2414
|
self.setAutoFillBackground(True)
|
2404
2415
|
self.setFrameStyle(QFrame.Shape.StyledPanel | QFrame.Shadow.Plain)
|
@@ -2410,12 +2421,10 @@ class GuiDocEditSearch(QFrame):
|
|
2410
2421
|
# ==========
|
2411
2422
|
|
2412
2423
|
self.searchBox = QLineEdit(self)
|
2413
|
-
self.searchBox.setFont(self.boxFont)
|
2414
2424
|
self.searchBox.setPlaceholderText(self.tr("Search for"))
|
2415
2425
|
self.searchBox.returnPressed.connect(self._doSearch)
|
2416
2426
|
|
2417
2427
|
self.replaceBox = QLineEdit(self)
|
2418
|
-
self.replaceBox.setFont(self.boxFont)
|
2419
2428
|
self.replaceBox.setPlaceholderText(self.tr("Replace with"))
|
2420
2429
|
self.replaceBox.returnPressed.connect(self._doReplace)
|
2421
2430
|
|
@@ -2425,12 +2434,9 @@ class GuiDocEditSearch(QFrame):
|
|
2425
2434
|
self.searchOpt.setContentsMargins(0, 0, 0, 0)
|
2426
2435
|
|
2427
2436
|
self.searchLabel = QLabel(self.tr("Search"), self)
|
2428
|
-
self.searchLabel.setFont(self.boxFont)
|
2429
2437
|
self.searchLabel.setIndent(CONFIG.pxInt(6))
|
2430
2438
|
|
2431
2439
|
self.resultLabel = QLabel("?/?", self)
|
2432
|
-
self.resultLabel.setFont(self.boxFont)
|
2433
|
-
self.resultLabel.setMinimumWidth(SHARED.theme.getTextWidth("?/?", self.boxFont))
|
2434
2440
|
|
2435
2441
|
self.toggleCase = QAction(self.tr("Case Sensitive"), self)
|
2436
2442
|
self.toggleCase.setCheckable(True)
|
@@ -2515,6 +2521,7 @@ class GuiDocEditSearch(QFrame):
|
|
2515
2521
|
self.replaceButton.setVisible(False)
|
2516
2522
|
self.adjustSize()
|
2517
2523
|
|
2524
|
+
self.updateFont()
|
2518
2525
|
self.updateTheme()
|
2519
2526
|
|
2520
2527
|
logger.debug("Ready: GuiDocEditSearch")
|
@@ -2598,7 +2605,9 @@ class GuiDocEditSearch(QFrame):
|
|
2598
2605
|
numCount = f"{lim:n}+" if (resCount or 0) > lim else f"{resCount:n}"
|
2599
2606
|
sCurrRes = "?" if currRes is None else str(currRes)
|
2600
2607
|
sResCount = "?" if resCount is None else numCount
|
2601
|
-
minWidth = SHARED.theme.getTextWidth(
|
2608
|
+
minWidth = SHARED.theme.getTextWidth(
|
2609
|
+
f"{sResCount}//{sResCount}", SHARED.theme.guiFontSmall
|
2610
|
+
)
|
2602
2611
|
self.resultLabel.setText(f"{sCurrRes}/{sResCount}")
|
2603
2612
|
self.resultLabel.setMinimumWidth(minWidth)
|
2604
2613
|
self.adjustSize()
|
@@ -2609,6 +2618,18 @@ class GuiDocEditSearch(QFrame):
|
|
2609
2618
|
# Methods
|
2610
2619
|
##
|
2611
2620
|
|
2621
|
+
def updateFont(self) -> None:
|
2622
|
+
"""Update the font settings."""
|
2623
|
+
self.setFont(SHARED.theme.guiFont)
|
2624
|
+
self.searchBox.setFont(SHARED.theme.guiFontSmall)
|
2625
|
+
self.replaceBox.setFont(SHARED.theme.guiFontSmall)
|
2626
|
+
self.searchLabel.setFont(SHARED.theme.guiFontSmall)
|
2627
|
+
self.resultLabel.setFont(SHARED.theme.guiFontSmall)
|
2628
|
+
self.resultLabel.setMinimumWidth(
|
2629
|
+
SHARED.theme.getTextWidth("?/?", SHARED.theme.guiFontSmall)
|
2630
|
+
)
|
2631
|
+
return
|
2632
|
+
|
2612
2633
|
def updateTheme(self) -> None:
|
2613
2634
|
"""Update theme elements."""
|
2614
2635
|
qPalette = QApplication.palette()
|
@@ -2793,10 +2814,6 @@ class GuiDocEditHeader(QWidget):
|
|
2793
2814
|
self.itemTitle.setAlignment(QtAlignCenterTop)
|
2794
2815
|
self.itemTitle.setFixedHeight(iPx)
|
2795
2816
|
|
2796
|
-
lblFont = self.itemTitle.font()
|
2797
|
-
lblFont.setPointSizeF(0.9*SHARED.theme.fontPointSize)
|
2798
|
-
self.itemTitle.setFont(lblFont)
|
2799
|
-
|
2800
2817
|
# Other Widgets
|
2801
2818
|
self.outlineMenu = QMenu(self)
|
2802
2819
|
|
@@ -2850,6 +2867,7 @@ class GuiDocEditHeader(QWidget):
|
|
2850
2867
|
self.setContentsMargins(0, 0, 0, 0)
|
2851
2868
|
self.setMinimumHeight(iPx + 2*mPx)
|
2852
2869
|
|
2870
|
+
self.updateFont()
|
2853
2871
|
self.updateTheme()
|
2854
2872
|
|
2855
2873
|
logger.debug("Ready: GuiDocEditHeader")
|
@@ -2888,6 +2906,12 @@ class GuiDocEditHeader(QWidget):
|
|
2888
2906
|
logger.debug("Document outline updated in %.3f ms", 1000*(time() - tStart))
|
2889
2907
|
return
|
2890
2908
|
|
2909
|
+
def updateFont(self) -> None:
|
2910
|
+
"""Update the font settings."""
|
2911
|
+
self.setFont(SHARED.theme.guiFont)
|
2912
|
+
self.itemTitle.setFont(SHARED.theme.guiFontSmall)
|
2913
|
+
return
|
2914
|
+
|
2891
2915
|
def updateTheme(self) -> None:
|
2892
2916
|
"""Update theme elements."""
|
2893
2917
|
self.tbButton.setThemeIcon("menu")
|
@@ -3001,9 +3025,6 @@ class GuiDocEditFooter(QWidget):
|
|
3001
3025
|
bSp = CONFIG.pxInt(4)
|
3002
3026
|
hSp = CONFIG.pxInt(6)
|
3003
3027
|
|
3004
|
-
lblFont = self.font()
|
3005
|
-
lblFont.setPointSizeF(0.9*SHARED.theme.fontPointSize)
|
3006
|
-
|
3007
3028
|
# Cached Translations
|
3008
3029
|
self._trLineCount = self.tr("Line: {0} ({1})")
|
3009
3030
|
self._trWordCount = self.tr("Words: {0} ({1})")
|
@@ -3026,7 +3047,6 @@ class GuiDocEditFooter(QWidget):
|
|
3026
3047
|
self.statusText.setAutoFillBackground(True)
|
3027
3048
|
self.statusText.setFixedHeight(fPx)
|
3028
3049
|
self.statusText.setAlignment(QtAlignLeftTop)
|
3029
|
-
self.statusText.setFont(lblFont)
|
3030
3050
|
|
3031
3051
|
# Lines
|
3032
3052
|
self.linesIcon = QLabel("", self)
|
@@ -3041,7 +3061,6 @@ class GuiDocEditFooter(QWidget):
|
|
3041
3061
|
self.linesText.setAutoFillBackground(True)
|
3042
3062
|
self.linesText.setFixedHeight(fPx)
|
3043
3063
|
self.linesText.setAlignment(QtAlignLeftTop)
|
3044
|
-
self.linesText.setFont(lblFont)
|
3045
3064
|
|
3046
3065
|
# Words
|
3047
3066
|
self.wordsIcon = QLabel("", self)
|
@@ -3056,7 +3075,6 @@ class GuiDocEditFooter(QWidget):
|
|
3056
3075
|
self.wordsText.setAutoFillBackground(True)
|
3057
3076
|
self.wordsText.setFixedHeight(fPx)
|
3058
3077
|
self.wordsText.setAlignment(QtAlignLeftTop)
|
3059
|
-
self.wordsText.setFont(lblFont)
|
3060
3078
|
|
3061
3079
|
# Assemble Layout
|
3062
3080
|
self.outerBox = QHBoxLayout()
|
@@ -3079,6 +3097,7 @@ class GuiDocEditFooter(QWidget):
|
|
3079
3097
|
self.setMinimumHeight(fPx + 2*mPx)
|
3080
3098
|
|
3081
3099
|
# Fix the Colours
|
3100
|
+
self.updateFont()
|
3082
3101
|
self.updateTheme()
|
3083
3102
|
|
3084
3103
|
# Initialise Info
|
@@ -3092,6 +3111,14 @@ class GuiDocEditFooter(QWidget):
|
|
3092
3111
|
# Methods
|
3093
3112
|
##
|
3094
3113
|
|
3114
|
+
def updateFont(self) -> None:
|
3115
|
+
"""Update the font settings."""
|
3116
|
+
self.setFont(SHARED.theme.guiFont)
|
3117
|
+
self.statusText.setFont(SHARED.theme.guiFontSmall)
|
3118
|
+
self.linesText.setFont(SHARED.theme.guiFontSmall)
|
3119
|
+
self.wordsText.setFont(SHARED.theme.guiFontSmall)
|
3120
|
+
return
|
3121
|
+
|
3095
3122
|
def updateTheme(self) -> None:
|
3096
3123
|
"""Update theme elements."""
|
3097
3124
|
iPx = round(0.9*SHARED.theme.baseIconHeight)
|
novelwriter/gui/docviewer.py
CHANGED
@@ -31,10 +31,7 @@ import logging
|
|
31
31
|
from enum import Enum
|
32
32
|
|
33
33
|
from PyQt5.QtCore import QPoint, Qt, QUrl, pyqtSignal, pyqtSlot
|
34
|
-
from PyQt5.QtGui import
|
35
|
-
QCursor, QFont, QMouseEvent, QPalette, QResizeEvent, QTextCursor,
|
36
|
-
QTextOption
|
37
|
-
)
|
34
|
+
from PyQt5.QtGui import QCursor, QMouseEvent, QPalette, QResizeEvent, QTextCursor, QTextOption
|
38
35
|
from PyQt5.QtWidgets import (
|
39
36
|
QAction, QApplication, QFrame, QHBoxLayout, QLabel, QMenu, QTextBrowser,
|
40
37
|
QToolButton, QWidget
|
@@ -141,12 +138,7 @@ class GuiDocViewer(QTextBrowser):
|
|
141
138
|
def initViewer(self) -> None:
|
142
139
|
"""Set editor settings from main config."""
|
143
140
|
self._makeStyleSheet()
|
144
|
-
|
145
|
-
# Set Font
|
146
|
-
font = QFont()
|
147
|
-
font.setFamily(CONFIG.textFont)
|
148
|
-
font.setPointSize(CONFIG.textSize)
|
149
|
-
self.document().setDefaultFont(font)
|
141
|
+
self.initFont()
|
150
142
|
|
151
143
|
# Set the widget colours to match syntax theme
|
152
144
|
mainPalette = self.palette()
|
@@ -189,6 +181,22 @@ class GuiDocViewer(QTextBrowser):
|
|
189
181
|
|
190
182
|
return
|
191
183
|
|
184
|
+
def initFont(self) -> None:
|
185
|
+
"""Set the font of the main widget and sub-widgets. This needs
|
186
|
+
special attention since there appears to be a bug in Qt 5.15.3.
|
187
|
+
See issues #1862 and #1875.
|
188
|
+
"""
|
189
|
+
font = self.font()
|
190
|
+
font.setFamily(CONFIG.textFont)
|
191
|
+
font.setPointSize(CONFIG.textSize)
|
192
|
+
self.setFont(font)
|
193
|
+
|
194
|
+
# Reset sub-widget font to GUI font
|
195
|
+
self.docHeader.updateFont()
|
196
|
+
self.docFooter.updateFont()
|
197
|
+
|
198
|
+
return
|
199
|
+
|
192
200
|
def loadText(self, tHandle: str, updateHistory: bool = True) -> bool:
|
193
201
|
"""Load text into the viewer from an item handle."""
|
194
202
|
if not SHARED.project.tree.checkType(tHandle, nwItemType.FILE):
|
@@ -646,10 +654,6 @@ class GuiDocViewHeader(QWidget):
|
|
646
654
|
self.itemTitle.setAlignment(QtAlignCenterTop)
|
647
655
|
self.itemTitle.setFixedHeight(iPx)
|
648
656
|
|
649
|
-
lblFont = self.itemTitle.font()
|
650
|
-
lblFont.setPointSizeF(0.9*SHARED.theme.fontPointSize)
|
651
|
-
self.itemTitle.setFont(lblFont)
|
652
|
-
|
653
657
|
# Other Widgets
|
654
658
|
self.outlineMenu = QMenu(self)
|
655
659
|
|
@@ -700,7 +704,7 @@ class GuiDocViewHeader(QWidget):
|
|
700
704
|
self.outerBox.setContentsMargins(mPx, mPx, mPx, mPx)
|
701
705
|
self.setMinimumHeight(iPx + 2*mPx)
|
702
706
|
|
703
|
-
|
707
|
+
self.updateFont()
|
704
708
|
self.updateTheme()
|
705
709
|
|
706
710
|
logger.debug("Ready: GuiDocViewHeader")
|
@@ -745,6 +749,12 @@ class GuiDocViewHeader(QWidget):
|
|
745
749
|
self._docOutline = data
|
746
750
|
return
|
747
751
|
|
752
|
+
def updateFont(self) -> None:
|
753
|
+
"""Update the font settings."""
|
754
|
+
self.setFont(SHARED.theme.guiFont)
|
755
|
+
self.itemTitle.setFont(SHARED.theme.guiFontSmall)
|
756
|
+
return
|
757
|
+
|
748
758
|
def updateTheme(self) -> None:
|
749
759
|
"""Update theme elements."""
|
750
760
|
self.outlineButton.setThemeIcon("list")
|
@@ -886,11 +896,6 @@ class GuiDocViewFooter(QWidget):
|
|
886
896
|
self.showSynopsis.toggled.connect(self._doToggleSynopsis)
|
887
897
|
self.showSynopsis.setToolTip(self.tr("Show Synopsis Comments"))
|
888
898
|
|
889
|
-
lblFont = self.font()
|
890
|
-
lblFont.setPointSizeF(0.9*SHARED.theme.fontPointSize)
|
891
|
-
self.showComments.setFont(lblFont)
|
892
|
-
self.showSynopsis.setFont(lblFont)
|
893
|
-
|
894
899
|
# Assemble Layout
|
895
900
|
self.outerBox = QHBoxLayout()
|
896
901
|
self.outerBox.addWidget(self.showHide, 0)
|
@@ -906,7 +911,7 @@ class GuiDocViewFooter(QWidget):
|
|
906
911
|
self.outerBox.setContentsMargins(mPx, mPx, mPx, mPx)
|
907
912
|
self.setMinimumHeight(iPx + 2*mPx)
|
908
913
|
|
909
|
-
|
914
|
+
self.updateFont()
|
910
915
|
self.updateTheme()
|
911
916
|
|
912
917
|
logger.debug("Ready: GuiDocViewFooter")
|
@@ -917,6 +922,13 @@ class GuiDocViewFooter(QWidget):
|
|
917
922
|
# Methods
|
918
923
|
##
|
919
924
|
|
925
|
+
def updateFont(self) -> None:
|
926
|
+
"""Update the font settings."""
|
927
|
+
self.setFont(SHARED.theme.guiFont)
|
928
|
+
self.showComments.setFont(SHARED.theme.guiFontSmall)
|
929
|
+
self.showSynopsis.setFont(SHARED.theme.guiFontSmall)
|
930
|
+
return
|
931
|
+
|
920
932
|
def updateTheme(self) -> None:
|
921
933
|
"""Update theme elements."""
|
922
934
|
# Icons
|
novelwriter/gui/projtree.py
CHANGED
@@ -32,10 +32,8 @@ from enum import Enum
|
|
32
32
|
from time import time
|
33
33
|
from typing import TYPE_CHECKING
|
34
34
|
|
35
|
-
from PyQt5.QtCore import QPoint,
|
36
|
-
from PyQt5.QtGui import
|
37
|
-
QDragEnterEvent, QDragMoveEvent, QDropEvent, QIcon, QMouseEvent, QPalette
|
38
|
-
)
|
35
|
+
from PyQt5.QtCore import QPoint, Qt, QTimer, pyqtSignal, pyqtSlot
|
36
|
+
from PyQt5.QtGui import QDragEnterEvent, QDragMoveEvent, QDropEvent, QIcon, QMouseEvent, QPalette
|
39
37
|
from PyQt5.QtWidgets import (
|
40
38
|
QAbstractItemView, QAction, QDialog, QFrame, QHBoxLayout, QHeaderView,
|
41
39
|
QLabel, QMenu, QShortcut, QSizePolicy, QTreeWidget, QTreeWidgetItem,
|
@@ -44,14 +42,14 @@ from PyQt5.QtWidgets import (
|
|
44
42
|
|
45
43
|
from novelwriter import CONFIG, SHARED
|
46
44
|
from novelwriter.common import minmax
|
47
|
-
from novelwriter.constants import nwHeaders, nwUnicode, trConst
|
45
|
+
from novelwriter.constants import nwHeaders, nwLabels, nwUnicode, trConst
|
48
46
|
from novelwriter.core.coretools import DocDuplicator, DocMerger, DocSplitter
|
49
47
|
from novelwriter.core.item import NWItem
|
50
48
|
from novelwriter.dialogs.docmerge import GuiDocMerge
|
51
49
|
from novelwriter.dialogs.docsplit import GuiDocSplit
|
52
50
|
from novelwriter.dialogs.editlabel import GuiEditLabel
|
53
51
|
from novelwriter.dialogs.projectsettings import GuiProjectSettings
|
54
|
-
from novelwriter.enum import nwDocMode,
|
52
|
+
from novelwriter.enum import nwDocMode, nwItemClass, nwItemLayout, nwItemType
|
55
53
|
from novelwriter.extensions.modified import NIconToolButton
|
56
54
|
from novelwriter.gui.theme import STYLES_MIN_TOOLBUTTON
|
57
55
|
from novelwriter.types import QtAlignLeft, QtAlignRight, QtMouseLeft, QtMouseMiddle, QtUserRole
|
@@ -1830,6 +1828,7 @@ class _TreeContextMenu(QMenu):
|
|
1830
1828
|
|
1831
1829
|
def _itemHeader(self) -> None:
|
1832
1830
|
"""Check if there is a header that can be used for rename."""
|
1831
|
+
SHARED.ensureEditorSaved(self._handle)
|
1833
1832
|
if hItem := SHARED.project.index.getItemHeading(self._handle, "T0001"):
|
1834
1833
|
action = self.addAction(self.tr("Rename to Heading"))
|
1835
1834
|
action.triggered.connect(
|
novelwriter/gui/theme.py
CHANGED
@@ -30,9 +30,7 @@ from math import ceil
|
|
30
30
|
from pathlib import Path
|
31
31
|
|
32
32
|
from PyQt5.QtCore import QSize, Qt
|
33
|
-
from PyQt5.QtGui import
|
34
|
-
QPalette, QColor, QIcon, QFont, QFontMetrics, QFontDatabase, QPixmap
|
35
|
-
)
|
33
|
+
from PyQt5.QtGui import QColor, QFont, QFontDatabase, QFontMetrics, QIcon, QPalette, QPixmap
|
36
34
|
from PyQt5.QtWidgets import QApplication
|
37
35
|
|
38
36
|
from novelwriter import CONFIG
|
@@ -154,6 +152,8 @@ class GuiTheme:
|
|
154
152
|
self.guiFont = QApplication.font()
|
155
153
|
self.guiFontB = QApplication.font()
|
156
154
|
self.guiFontB.setBold(True)
|
155
|
+
self.guiFontSmall = QApplication.font()
|
156
|
+
self.guiFontSmall.setPointSizeF(0.9*self.guiFont.pointSizeF())
|
157
157
|
|
158
158
|
qMetric = QFontMetrics(self.guiFont)
|
159
159
|
fHeight = qMetric.height()
|
novelwriter/shared.py
CHANGED
@@ -204,6 +204,19 @@ class SharedData(QObject):
|
|
204
204
|
self._resetIdleTimer()
|
205
205
|
return
|
206
206
|
|
207
|
+
def ensureEditorSaved(self, tHandle: str | None) -> None:
|
208
|
+
"""Ensure that the editor content is saved. Optionally, only if
|
209
|
+
it is a specific handle.
|
210
|
+
"""
|
211
|
+
docEditor = self.mainGui.docEditor
|
212
|
+
if (
|
213
|
+
self.hasProject and docEditor.docHandle
|
214
|
+
and (tHandle is None or tHandle == docEditor.docHandle)
|
215
|
+
):
|
216
|
+
logger.debug("Saving editor document before action")
|
217
|
+
docEditor.saveText()
|
218
|
+
return
|
219
|
+
|
207
220
|
def updateSpellCheckLanguage(self, reload: bool = False) -> None:
|
208
221
|
"""Update the active spell check language from settings."""
|
209
222
|
from novelwriter import CONFIG
|
@@ -36,7 +36,7 @@ from PyQt5.QtWidgets import (
|
|
36
36
|
)
|
37
37
|
|
38
38
|
from novelwriter import CONFIG, SHARED
|
39
|
-
from novelwriter.common import formatFileFilter,
|
39
|
+
from novelwriter.common import formatFileFilter, formatInt, getFileSize, openExternalPath
|
40
40
|
from novelwriter.error import formatException
|
41
41
|
from novelwriter.extensions.modified import NIconToolButton
|
42
42
|
from novelwriter.types import QtDialogClose
|
@@ -143,11 +143,12 @@ class GuiDictionaries(QDialog):
|
|
143
143
|
try:
|
144
144
|
import enchant
|
145
145
|
path = Path(enchant.get_user_config_dir())
|
146
|
+
self._installPath = Path(path).resolve()
|
147
|
+
self._installPath.mkdir(exist_ok=True, parents=True)
|
146
148
|
except Exception:
|
147
149
|
logger.error("Could not get enchant path")
|
148
150
|
return False
|
149
151
|
|
150
|
-
self._installPath = Path(path).resolve()
|
151
152
|
if path.is_dir():
|
152
153
|
self.inPath.setText(str(path))
|
153
154
|
hunspell = path / "hunspell"
|
@@ -199,9 +200,9 @@ class GuiDictionaries(QDialog):
|
|
199
200
|
if self._installPath:
|
200
201
|
temp = self.huInput.text()
|
201
202
|
if temp and (path := Path(temp)).is_file():
|
202
|
-
hunspell = self._installPath / "hunspell"
|
203
|
-
hunspell.mkdir(exist_ok=True)
|
204
203
|
try:
|
204
|
+
hunspell = self._installPath / "hunspell"
|
205
|
+
hunspell.mkdir(exist_ok=True)
|
205
206
|
nAff, nDic = self._extractDicts(path, hunspell)
|
206
207
|
if nAff == 0 or nDic == 0:
|
207
208
|
self._appendLog(procErr, err=True)
|
novelwriter/tools/manuscript.py
CHANGED
@@ -31,13 +31,13 @@ from time import time
|
|
31
31
|
from typing import TYPE_CHECKING
|
32
32
|
|
33
33
|
from PyQt5.QtCore import Qt, QTimer, QUrl, pyqtSignal, pyqtSlot
|
34
|
-
from PyQt5.QtGui import QCloseEvent, QColor, QCursor,
|
34
|
+
from PyQt5.QtGui import QCloseEvent, QColor, QCursor, QPalette, QResizeEvent
|
35
35
|
from PyQt5.QtPrintSupport import QPrinter, QPrintPreviewDialog
|
36
36
|
from PyQt5.QtWidgets import (
|
37
|
-
QAbstractItemView, QApplication,
|
38
|
-
|
39
|
-
|
40
|
-
|
37
|
+
QAbstractItemView, QApplication, QFormLayout, QGridLayout, QHBoxLayout,
|
38
|
+
QLabel, QListWidget, QListWidgetItem, QPushButton, QSizePolicy, QSplitter,
|
39
|
+
QStackedWidget, QTabWidget, QTextBrowser, QTreeWidget, QTreeWidgetItem,
|
40
|
+
QVBoxLayout, QWidget
|
41
41
|
)
|
42
42
|
|
43
43
|
from novelwriter import CONFIG, SHARED
|
@@ -48,7 +48,7 @@ from novelwriter.core.tohtml import ToHtml
|
|
48
48
|
from novelwriter.core.tokenizer import HeadingFormatter
|
49
49
|
from novelwriter.error import logException
|
50
50
|
from novelwriter.extensions.circularprogress import NProgressCircle
|
51
|
-
from novelwriter.extensions.modified import NIconToggleButton, NIconToolButton
|
51
|
+
from novelwriter.extensions.modified import NDialog, NIconToggleButton, NIconToolButton
|
52
52
|
from novelwriter.gui.theme import STYLES_FLAT_TABS, STYLES_MIN_TOOLBUTTON
|
53
53
|
from novelwriter.tools.manusbuild import GuiManuscriptBuild
|
54
54
|
from novelwriter.tools.manussettings import GuiBuildSettings
|
@@ -63,7 +63,7 @@ if TYPE_CHECKING: # pragma: no cover
|
|
63
63
|
logger = logging.getLogger(__name__)
|
64
64
|
|
65
65
|
|
66
|
-
class GuiManuscript(
|
66
|
+
class GuiManuscript(NDialog):
|
67
67
|
"""GUI Tools: Manuscript Tool
|
68
68
|
|
69
69
|
The dialog displays all the users build definitions, a preview panel
|
@@ -285,7 +285,7 @@ class GuiManuscript(QDialog):
|
|
285
285
|
if isinstance(obj, GuiBuildSettings) and obj.isVisible():
|
286
286
|
obj.close()
|
287
287
|
event.accept()
|
288
|
-
self.
|
288
|
+
self.softDelete()
|
289
289
|
return
|
290
290
|
|
291
291
|
##
|
@@ -343,7 +343,7 @@ class GuiManuscript(QDialog):
|
|
343
343
|
return
|
344
344
|
|
345
345
|
# Make sure editor content is saved before we start
|
346
|
-
SHARED.
|
346
|
+
SHARED.ensureEditorSaved(None)
|
347
347
|
|
348
348
|
docBuild = NWBuildDocument(SHARED.project, build)
|
349
349
|
docBuild.setPreviewMode(True)
|
@@ -761,7 +761,6 @@ class _PreviewWidget(QTextBrowser):
|
|
761
761
|
self.setPalette(dPalette)
|
762
762
|
|
763
763
|
self.setMinimumWidth(40*SHARED.theme.textNWidth)
|
764
|
-
self.setTextFont(CONFIG.textFont, CONFIG.textSize)
|
765
764
|
self.setTabStopDistance(CONFIG.getTabWidth())
|
766
765
|
self.setOpenExternalLinks(False)
|
767
766
|
|
@@ -802,6 +801,8 @@ class _PreviewWidget(QTextBrowser):
|
|
802
801
|
self._updateDocMargins()
|
803
802
|
self._updateBuildAge()
|
804
803
|
|
804
|
+
self.setTextFont(CONFIG.textFont, CONFIG.textSize)
|
805
|
+
|
805
806
|
# Age Timer
|
806
807
|
self.ageTimer = QTimer(self)
|
807
808
|
self.ageTimer.setInterval(10000)
|
@@ -831,12 +832,17 @@ class _PreviewWidget(QTextBrowser):
|
|
831
832
|
return
|
832
833
|
|
833
834
|
def setTextFont(self, family: str, size: int) -> None:
|
834
|
-
"""Set the text font properties.
|
835
|
-
|
836
|
-
|
835
|
+
"""Set the text font properties and then reset for sub-widgets.
|
836
|
+
This needs special attention since there appears to be a bug in
|
837
|
+
Qt 5.15.3. See issues #1862 and #1875.
|
838
|
+
"""
|
839
|
+
if family and size > 4:
|
840
|
+
font = self.font()
|
837
841
|
font.setFamily(family)
|
838
842
|
font.setPointSize(size)
|
839
|
-
self.
|
843
|
+
self.setFont(font)
|
844
|
+
self.buildProgress.setFont(SHARED.theme.guiFont)
|
845
|
+
self.ageLabel.setFont(SHARED.theme.guiFontSmall)
|
840
846
|
return
|
841
847
|
|
842
848
|
##
|
@@ -30,8 +30,8 @@ from typing import TYPE_CHECKING
|
|
30
30
|
from PyQt5.QtCore import QEvent, Qt, pyqtSignal, pyqtSlot
|
31
31
|
from PyQt5.QtGui import QFont, QIcon, QSyntaxHighlighter, QTextCharFormat, QTextDocument
|
32
32
|
from PyQt5.QtWidgets import (
|
33
|
-
QAbstractButton, QAbstractItemView,
|
34
|
-
|
33
|
+
QAbstractButton, QAbstractItemView, QDialogButtonBox, QFontDialog, QFrame,
|
34
|
+
QGridLayout, QHBoxLayout, QHeaderView, QLabel, QLineEdit, QMenu,
|
35
35
|
QPlainTextEdit, QPushButton, QSplitter, QStackedWidget, QTreeWidget,
|
36
36
|
QTreeWidgetItem, QVBoxLayout, QWidget
|
37
37
|
)
|
@@ -42,7 +42,9 @@ from novelwriter.core.buildsettings import BuildSettings, FilterMode
|
|
42
42
|
from novelwriter.extensions.configlayout import (
|
43
43
|
NColourLabel, NFixedPage, NScrollableForm, NScrollablePage
|
44
44
|
)
|
45
|
-
from novelwriter.extensions.modified import
|
45
|
+
from novelwriter.extensions.modified import (
|
46
|
+
NComboBox, NDialog, NDoubleSpinBox, NIconToolButton, NSpinBox
|
47
|
+
)
|
46
48
|
from novelwriter.extensions.pagedsidebar import NPagedSideBar
|
47
49
|
from novelwriter.extensions.switch import NSwitch
|
48
50
|
from novelwriter.extensions.switchbox import NSwitchBox
|
@@ -57,7 +59,7 @@ if TYPE_CHECKING: # pragma: no cover
|
|
57
59
|
logger = logging.getLogger(__name__)
|
58
60
|
|
59
61
|
|
60
|
-
class GuiBuildSettings(
|
62
|
+
class GuiBuildSettings(NDialog):
|
61
63
|
"""GUI Tools: Manuscript Build Settings Dialog
|
62
64
|
|
63
65
|
The main tool for configuring manuscript builds. It's a GUI tool for
|
@@ -199,7 +201,7 @@ class GuiBuildSettings(QDialog):
|
|
199
201
|
self._askToSaveBuild()
|
200
202
|
self._saveSettings()
|
201
203
|
event.accept()
|
202
|
-
self.
|
204
|
+
self.softDelete()
|
203
205
|
return
|
204
206
|
|
205
207
|
##
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|