Merge branch 'master' into release_0.7

This commit is contained in:
Veronica K. B. Olsen
2020-05-31 17:04:07 +02:00
35 changed files with 1088 additions and 159 deletions
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+93
View File
@@ -0,0 +1,93 @@
Copyright (c) 2009-2010, Understanding Limited (dave@understandinglimited.com)
This Font Software is licensed under the SIL Open Font License, Version 1.1.
This license is copied below, and is also available with a FAQ at:
http://scripts.sil.org/OFL
-----------------------------------------------------------
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
-----------------------------------------------------------
PREAMBLE
The goals of the Open Font License (OFL) are to stimulate worldwide
development of collaborative font projects, to support the font creation
efforts of academic and linguistic communities, and to provide a free and
open framework in which fonts may be shared and improved in partnership
with others.
The OFL allows the licensed fonts to be used, studied, modified and
redistributed freely as long as they are not sold by themselves. The
fonts, including any derivative works, can be bundled, embedded,
redistributed and/or sold with any software provided that any reserved
names are not used by derivative works. The fonts and derivatives,
however, cannot be released under any other type of license. The
requirement for fonts to remain under this license does not apply
to any document created using the fonts or their derivatives.
DEFINITIONS
"Font Software" refers to the set of files released by the Copyright
Holder(s) under this license and clearly marked as such. This may
include source files, build scripts and documentation.
"Reserved Font Name" refers to any names specified as such after the
copyright statement(s).
"Original Version" refers to the collection of Font Software components as
distributed by the Copyright Holder(s).
"Modified Version" refers to any derivative made by adding to, deleting,
or substituting -- in part or in whole -- any of the components of the
Original Version, by changing formats or by porting the Font Software to a
new environment.
"Author" refers to any designer, engineer, programmer, technical
writer or other person who contributed to the Font Software.
PERMISSION & CONDITIONS
Permission is hereby granted, free of charge, to any person obtaining
a copy of the Font Software, to use, study, copy, merge, embed, modify,
redistribute, and sell modified and unmodified copies of the Font
Software, subject to the following conditions:
1) Neither the Font Software nor any of its individual components,
in Original or Modified Versions, may be sold by itself.
2) Original or Modified Versions of the Font Software may be bundled,
redistributed and/or sold with any software, provided that each copy
contains the above copyright notice and this license. These can be
included either as stand-alone text files, human-readable headers or
in the appropriate machine-readable metadata fields within text or
binary files as long as those fields can be easily viewed by the user.
3) No Modified Version of the Font Software may use the Reserved Font
Name(s) unless explicit written permission is granted by the corresponding
Copyright Holder. This restriction only applies to the primary font name as
presented to the users.
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
Software shall not be used to promote, endorse or advertise any
Modified Version, except to acknowledge the contribution(s) of the
Copyright Holder(s) and the Author(s) or with their explicit written
permission.
5) The Font Software, modified or unmodified, in part or in whole,
must be distributed entirely under this license, and must not be
distributed under any other license. The requirement for fonts to
remain under this license does not apply to any document created
using the Font Software.
TERMINATION
This license becomes null and void if any of the above conditions are
not met.
DISCLAIMER
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
OTHER DEALINGS IN THE FONT SOFTWARE.
+56
View File
@@ -0,0 +1,56 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
inkscape:version="1.0 (4035a4fb49, 2020-05-01)"
sodipodi:docname="tick.svg"
id="svg896"
viewBox="0 0 24 24"
height="24"
width="24"
version="1.2">
<metadata
id="metadata902">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs900" />
<sodipodi:namedview
inkscape:current-layer="svg896"
inkscape:window-maximized="1"
inkscape:window-y="1"
inkscape:window-x="2560"
inkscape:cy="13.298248"
inkscape:cx="11.288366"
inkscape:zoom="34.117902"
inkscape:pagecheckerboard="true"
showgrid="false"
id="namedview898"
inkscape:window-height="1370"
inkscape:window-width="2560"
inkscape:pageshadow="2"
inkscape:pageopacity="0"
guidetolerance="10"
gridtolerance="10"
objecttolerance="10"
borderopacity="1"
bordercolor="#666666"
pagecolor="#ffffff" />
<path
style="stroke-width:1.3846;fill:#aeaeae;fill-opacity:1"
id="path894"
d="M 19.576035,3.3487939 C 18.237131,2.6038813 16.550693,3.0884898 15.809935,4.4246248 L 10.66893,13.676495 7.726664,10.734229 c -1.0813694,-1.0813704 -2.8342677,-1.0813704 -3.9156371,0 -1.0813693,1.081369 -1.0813693,2.834267 0,3.915637 l 5.538383,5.538383 c 0.523378,0.524762 1.2295221,0.812758 1.9578191,0.812758 l 0.383533,-0.02769 c 0.859834,-0.12046 1.614439,-0.636914 2.03674,-1.397057 L 20.650482,7.1148966 C 21.39401,5.777375 20.91217,4.0923218 19.576035,3.3487939 Z" />
</svg>

After

Width:  |  Height:  |  Size: 2.0 KiB

+56
View File
@@ -0,0 +1,56 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
inkscape:version="1.0 (4035a4fb49, 2020-05-01)"
sodipodi:docname="tick.svg"
id="svg896"
viewBox="0 0 24 24"
height="24"
width="24"
version="1.2">
<metadata
id="metadata902">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs900" />
<sodipodi:namedview
inkscape:current-layer="svg896"
inkscape:window-maximized="1"
inkscape:window-y="1"
inkscape:window-x="2560"
inkscape:cy="13.298248"
inkscape:cx="11.288366"
inkscape:zoom="34.117902"
inkscape:pagecheckerboard="true"
showgrid="false"
id="namedview898"
inkscape:window-height="1370"
inkscape:window-width="2560"
inkscape:pageshadow="2"
inkscape:pageopacity="0"
guidetolerance="10"
gridtolerance="10"
objecttolerance="10"
borderopacity="1"
bordercolor="#666666"
pagecolor="#ffffff" />
<path
style="stroke-width:1.3846;fill:#000000;fill-opacity:0.77999997"
id="path894"
d="M 19.576035,3.3487939 C 18.237131,2.6038813 16.550693,3.0884898 15.809935,4.4246248 L 10.66893,13.676495 7.726664,10.734229 c -1.0813694,-1.0813704 -2.8342677,-1.0813704 -3.9156371,0 -1.0813693,1.081369 -1.0813693,2.834267 0,3.915637 l 5.538383,5.538383 c 0.523378,0.524762 1.2295221,0.812758 1.9578191,0.812758 l 0.383533,-0.02769 c 0.859834,-0.12046 1.614439,-0.636914 2.03674,-1.397057 L 20.650482,7.1148966 C 21.39401,5.777375 20.91217,4.0923218 19.576035,3.3487939 Z" />
</svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

+56
View File
@@ -0,0 +1,56 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
version="1.2"
width="24"
height="24"
viewBox="0 0 24 24"
id="svg8936"
sodipodi:docname="times.svg"
inkscape:version="1.0rc1 (09960d6f05, 2020-04-09)">
<metadata
id="metadata8942">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs8940" />
<sodipodi:namedview
inkscape:document-rotation="0"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="2560"
inkscape:window-height="1344"
id="namedview8938"
showgrid="false"
inkscape:zoom="38.125"
inkscape:cx="12"
inkscape:cy="12"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="svg8936" />
<path
d="m 19.0412,4.9586375 c -1.014432,-1.0157327 -2.663535,-1.0157327 -3.677967,0 L 12.000001,8.3218703 8.6367669,4.9586375 c -1.0144323,-1.0157327 -2.663535,-1.0157327 -3.6779673,0 -1.0157327,1.0157328 -1.0157327,2.6622343 0,3.6779673 L 8.3207319,11.999838 4.9587996,15.36307 c -1.0157327,1.015733 -1.0157327,2.662235 0,3.677968 0.5072161,0.508516 1.1730998,0.762124 1.8389836,0.762124 0.6658835,0 1.3317669,-0.253608 1.8389837,-0.762124 l 3.3632341,-3.363233 3.363232,3.363233 c 0.507216,0.508516 1.173099,0.762124 1.838984,0.762124 0.665882,0 1.331765,-0.253608 1.838983,-0.762124 1.015733,-1.015733 1.015733,-2.662235 0,-3.677968 L 15.679268,11.999838 19.0412,8.6366048 c 1.015733,-1.015733 1.015733,-2.6622345 0,-3.6779673 z"
id="path8934"
inkscape:connector-curvature="0"
style="fill:#aeaeae;fill-opacity:1;stroke-width:1.30056" />
</svg>

After

Width:  |  Height:  |  Size: 2.3 KiB

+55
View File
@@ -0,0 +1,55 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
inkscape:version="1.0rc1 (09960d6f05, 2020-04-09)"
sodipodi:docname="times.svg"
id="svg8936"
viewBox="0 0 24 24"
height="24"
width="24"
version="1.2">
<metadata
id="metadata8942">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs8940" />
<sodipodi:namedview
inkscape:current-layer="svg8936"
inkscape:window-maximized="1"
inkscape:window-y="0"
inkscape:window-x="0"
inkscape:cy="12"
inkscape:cx="12"
inkscape:zoom="38.125"
showgrid="false"
id="namedview8938"
inkscape:window-height="1344"
inkscape:window-width="2560"
inkscape:pageshadow="2"
inkscape:pageopacity="0"
guidetolerance="10"
gridtolerance="10"
objecttolerance="10"
borderopacity="1"
bordercolor="#666666"
pagecolor="#ffffff" />
<path
style="fill:#000000;fill-opacity:0.78;stroke-width:1.30056"
inkscape:connector-curvature="0"
id="path8934"
d="m 19.0412,4.9586375 c -1.014432,-1.0157327 -2.663535,-1.0157327 -3.677967,0 L 12.000001,8.3218703 8.6367669,4.9586375 c -1.0144323,-1.0157327 -2.663535,-1.0157327 -3.6779673,0 -1.0157327,1.0157328 -1.0157327,2.6622343 0,3.6779673 L 8.3207319,11.999838 4.9587996,15.36307 c -1.0157327,1.015733 -1.0157327,2.662235 0,3.677968 0.5072161,0.508516 1.1730998,0.762124 1.8389836,0.762124 0.6658835,0 1.3317669,-0.253608 1.8389837,-0.762124 l 3.3632341,-3.363233 3.363232,3.363233 c 0.507216,0.508516 1.173099,0.762124 1.838984,0.762124 0.665882,0 1.331765,-0.253608 1.838983,-0.762124 1.015733,-1.015733 1.015733,-2.662235 0,-3.677968 L 15.679268,11.999838 19.0412,8.6366048 c 1.015733,-1.015733 1.015733,-2.6622345 0,-3.6779673 z" />
</svg>

After

Width:  |  Height:  |  Size: 2.3 KiB

@@ -37,3 +37,5 @@ search-replace = search-replace.svg
clear = backspace.svg
save = download.svg
edit = pencil.svg
check = tick.svg
cross = times.svg
@@ -0,0 +1,56 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
inkscape:version="1.0 (4035a4fb49, 2020-05-01)"
sodipodi:docname="tick.svg"
id="svg896"
viewBox="0 0 24 24"
height="24"
width="24"
version="1.2">
<metadata
id="metadata902">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs900" />
<sodipodi:namedview
inkscape:current-layer="svg896"
inkscape:window-maximized="1"
inkscape:window-y="1"
inkscape:window-x="2560"
inkscape:cy="13.298248"
inkscape:cx="11.288366"
inkscape:zoom="34.117902"
inkscape:pagecheckerboard="true"
showgrid="false"
id="namedview898"
inkscape:window-height="1370"
inkscape:window-width="2560"
inkscape:pageshadow="2"
inkscape:pageopacity="0"
guidetolerance="10"
gridtolerance="10"
objecttolerance="10"
borderopacity="1"
bordercolor="#666666"
pagecolor="#ffffff" />
<path
style="stroke-width:1.3846;fill:#99cc99;fill-opacity:1"
id="path894"
d="M 19.576035,3.3487939 C 18.237131,2.6038813 16.550693,3.0884898 15.809935,4.4246248 L 10.66893,13.676495 7.726664,10.734229 c -1.0813694,-1.0813704 -2.8342677,-1.0813704 -3.9156371,0 -1.0813693,1.081369 -1.0813693,2.834267 0,3.915637 l 5.538383,5.538383 c 0.523378,0.524762 1.2295221,0.812758 1.9578191,0.812758 l 0.383533,-0.02769 c 0.859834,-0.12046 1.614439,-0.636914 2.03674,-1.397057 L 20.650482,7.1148966 C 21.39401,5.777375 20.91217,4.0923218 19.576035,3.3487939 Z" />
</svg>

After

Width:  |  Height:  |  Size: 2.0 KiB

@@ -37,3 +37,5 @@ search-replace = search-replace.svg
clear = backspace.svg
save = download.svg
edit = pencil.svg
check = tick.svg
cross = times.svg
@@ -0,0 +1,56 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
inkscape:version="1.0 (4035a4fb49, 2020-05-01)"
sodipodi:docname="tick.svg"
id="svg896"
viewBox="0 0 24 24"
height="24"
width="24"
version="1.2">
<metadata
id="metadata902">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs900" />
<sodipodi:namedview
inkscape:current-layer="svg896"
inkscape:window-maximized="1"
inkscape:window-y="1"
inkscape:window-x="2560"
inkscape:cy="13.298248"
inkscape:cx="11.288366"
inkscape:zoom="34.117902"
inkscape:pagecheckerboard="true"
showgrid="false"
id="namedview898"
inkscape:window-height="1370"
inkscape:window-width="2560"
inkscape:pageshadow="2"
inkscape:pageopacity="0"
guidetolerance="10"
gridtolerance="10"
objecttolerance="10"
borderopacity="1"
bordercolor="#666666"
pagecolor="#ffffff" />
<path
style="stroke-width:1.3846;fill:#718c00;fill-opacity:1"
id="path894"
d="M 19.576035,3.3487939 C 18.237131,2.6038813 16.550693,3.0884898 15.809935,4.4246248 L 10.66893,13.676495 7.726664,10.734229 c -1.0813694,-1.0813704 -2.8342677,-1.0813704 -3.9156371,0 -1.0813693,1.081369 -1.0813693,2.834267 0,3.915637 l 5.538383,5.538383 c 0.523378,0.524762 1.2295221,0.812758 1.9578191,0.812758 l 0.383533,-0.02769 c 0.859834,-0.12046 1.614439,-0.636914 2.03674,-1.397057 L 20.650482,7.1148966 C 21.39401,5.777375 20.91217,4.0923218 19.576035,3.3487939 Z" />
</svg>

After

Width:  |  Height:  |  Size: 2.0 KiB

@@ -36,3 +36,5 @@ search-replace = search-replace.svg
clear = backspace.svg
save = download.svg
edit = pencil.svg
check = tick.svg
cross = times.svg
@@ -0,0 +1,56 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
inkscape:version="1.0 (4035a4fb49, 2020-05-01)"
sodipodi:docname="tick.svg"
id="svg896"
viewBox="0 0 24 24"
height="24"
width="24"
version="1.2">
<metadata
id="metadata902">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs900" />
<sodipodi:namedview
inkscape:current-layer="svg896"
inkscape:window-maximized="1"
inkscape:window-y="1"
inkscape:window-x="2560"
inkscape:cy="13.298248"
inkscape:cx="11.288366"
inkscape:zoom="34.117902"
inkscape:pagecheckerboard="true"
showgrid="false"
id="namedview898"
inkscape:window-height="1370"
inkscape:window-width="2560"
inkscape:pageshadow="2"
inkscape:pageopacity="0"
guidetolerance="10"
gridtolerance="10"
objecttolerance="10"
borderopacity="1"
bordercolor="#666666"
pagecolor="#ffffff" />
<path
style="stroke-width:1.3846;fill:#aeaeae;fill-opacity:1"
id="path894"
d="M 19.576035,3.3487939 C 18.237131,2.6038813 16.550693,3.0884898 15.809935,4.4246248 L 10.66893,13.676495 7.726664,10.734229 c -1.0813694,-1.0813704 -2.8342677,-1.0813704 -3.9156371,0 -1.0813693,1.081369 -1.0813693,2.834267 0,3.915637 l 5.538383,5.538383 c 0.523378,0.524762 1.2295221,0.812758 1.9578191,0.812758 l 0.383533,-0.02769 c 0.859834,-0.12046 1.614439,-0.636914 2.03674,-1.397057 L 20.650482,7.1148966 C 21.39401,5.777375 20.91217,4.0923218 19.576035,3.3487939 Z" />
</svg>

After

Width:  |  Height:  |  Size: 2.0 KiB

@@ -36,3 +36,5 @@ search-replace = search-replace.svg
clear = backspace.svg
save = download.svg
edit = pencil.svg
check = tick.svg
cross = times.svg
@@ -0,0 +1,56 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
inkscape:version="1.0 (4035a4fb49, 2020-05-01)"
sodipodi:docname="tick.svg"
id="svg896"
viewBox="0 0 24 24"
height="24"
width="24"
version="1.2">
<metadata
id="metadata902">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs900" />
<sodipodi:namedview
inkscape:current-layer="svg896"
inkscape:window-maximized="1"
inkscape:window-y="1"
inkscape:window-x="2560"
inkscape:cy="13.298248"
inkscape:cx="11.288366"
inkscape:zoom="34.117902"
inkscape:pagecheckerboard="true"
showgrid="false"
id="namedview898"
inkscape:window-height="1370"
inkscape:window-width="2560"
inkscape:pageshadow="2"
inkscape:pageopacity="0"
guidetolerance="10"
gridtolerance="10"
objecttolerance="10"
borderopacity="1"
bordercolor="#666666"
pagecolor="#ffffff" />
<path
style="stroke-width:1.3846;fill:#000000;fill-opacity:0.77999997"
id="path894"
d="M 19.576035,3.3487939 C 18.237131,2.6038813 16.550693,3.0884898 15.809935,4.4246248 L 10.66893,13.676495 7.726664,10.734229 c -1.0813694,-1.0813704 -2.8342677,-1.0813704 -3.9156371,0 -1.0813693,1.081369 -1.0813693,2.834267 0,3.915637 l 5.538383,5.538383 c 0.523378,0.524762 1.2295221,0.812758 1.9578191,0.812758 l 0.383533,-0.02769 c 0.859834,-0.12046 1.614439,-0.636914 2.03674,-1.397057 L 20.650482,7.1148966 C 21.39401,5.777375 20.91217,4.0923218 19.576035,3.3487939 Z" />
</svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

+20 -12
View File
@@ -36,7 +36,6 @@ from time import time
from PyQt5.Qt import PYQT_VERSION_STR
from PyQt5.QtCore import QT_VERSION_STR, QStandardPaths, QSysInfo
from PyQt5.QtWidgets import QErrorMessage
from nw.constants import nwFiles, nwUnicode
from nw.common import splitVersionNumber, formatTimeStamp
@@ -82,11 +81,13 @@ class Config:
self.confChanged = False
## General
self.guiTheme = "default"
self.guiSyntax = "default_light"
self.guiIcons = "typicons_grey_light"
self.guiDark = False
self.guiLang = "en" # Hardcoded for now
self.guiTheme = "default"
self.guiSyntax = "default_light"
self.guiIcons = "typicons_grey_light"
self.guiDark = False
self.guiLang = "en" # Hardcoded for now
self.guiFont = ""
self.guiFontSize = 11
## Sizes
self.winGeometry = [1100, 650]
@@ -202,7 +203,6 @@ class Config:
"""Initialise the config class. The manual setting of confPath
and dataPath is mainly intended for the test suite.
"""
if confPath is None:
confRoot = QStandardPaths.writableLocation(QStandardPaths.ConfigLocation)
self.confPath = path.join(path.abspath(confRoot), self.appHandle)
@@ -318,6 +318,12 @@ class Config:
self.guiDark = self._parseLine(
cnfParse, cnfSec, "guidark", self.CNF_BOOL, self.guiDark
)
self.guiFont = self._parseLine(
cnfParse, cnfSec, "guifont", self.CNF_STR, self.guiFont
)
self.guiFontSize = self._parseLine(
cnfParse, cnfSec, "guifontsize", self.CNF_INT, self.guiFontSize
)
## Sizes
cnfSec = "Sizes"
@@ -464,11 +470,13 @@ class Config:
## Main
cnfSec = "Main"
cnfParse.add_section(cnfSec)
cnfParse.set(cnfSec,"timestamp", formatTimeStamp(time()))
cnfParse.set(cnfSec,"theme", str(self.guiTheme))
cnfParse.set(cnfSec,"syntax", str(self.guiSyntax))
cnfParse.set(cnfSec,"icons", str(self.guiIcons))
cnfParse.set(cnfSec,"guidark", str(self.guiDark))
cnfParse.set(cnfSec,"timestamp", formatTimeStamp(time()))
cnfParse.set(cnfSec,"theme", str(self.guiTheme))
cnfParse.set(cnfSec,"syntax", str(self.guiSyntax))
cnfParse.set(cnfSec,"icons", str(self.guiIcons))
cnfParse.set(cnfSec,"guidark", str(self.guiDark))
cnfParse.set(cnfSec,"guifont", str(self.guiFont))
cnfParse.set(cnfSec,"guifontsize", str(self.guiFontSize))
## Sizes
cnfSec = "Sizes"
+1
View File
@@ -45,6 +45,7 @@ class nwFiles():
INDEX_FILE = "tagsIndex.json"
OPTS_FILE = "guiOptions.json"
RECENT_FILE = "recentProjects.json"
BUILD_CACHE = "prevBuild.json"
# END Class nwFiles
+7 -1
View File
@@ -71,6 +71,9 @@ class NWDoc():
"""Open a document from handle, capturing potential file system
errors and parse meta data.
"""
if not isHandle(tHandle):
return None
# Always clear first, since the object will often be reused.
self.clearDocument()
@@ -170,7 +173,10 @@ class NWDoc():
"""Permanently delete a document source file and its backups
from the project data folder.
"""
docFile = self.docHandle+".nwd"
if not isHandle(tHandle):
return False
docFile = tHandle+".nwd"
chkList = []
chkList.append(path.join(self.theProject.projContent, docFile))
+24 -8
View File
@@ -152,15 +152,19 @@ class NWProject():
self.projTree.append(None, pHandle, newItem)
return newItem.itemHandle
def addTrash(self):
def trashFolder(self):
"""Add the special trash root folder to the project.
"""
newItem = NWItem(self)
newItem.setName("Trash")
newItem.setType(nwItemType.TRASH)
newItem.setClass(nwItemClass.TRASH)
self.projTree.append(None, None, newItem)
return newItem.itemHandle
trashHandle = self.projTree.trashRoot()
if trashHandle is None:
newItem = NWItem(self)
newItem.setName("Trash")
newItem.setType(nwItemType.TRASH)
newItem.setClass(nwItemClass.TRASH)
self.projTree.append(None, None, newItem)
return newItem.itemHandle
return trashHandle
##
# Project Methods
@@ -179,6 +183,7 @@ class NWProject():
hScene = self.newFile("New Scene", nwItemClass.NOVEL, hChapt)
self.projOpened = time()
self.setProjectChanged(True)
self.saveProject(autoSave=True)
return True
def clearProject(self):
@@ -674,7 +679,7 @@ class NWProject():
# Setters
##
def setProjectPath(self, projPath):
def setProjectPath(self, projPath, newProject=False):
"""Set the project storage path, and also expand ~ to the user
directory using the path library.
"""
@@ -684,7 +689,18 @@ class NWProject():
if projPath.startswith("~"):
projPath = path.expanduser(projPath)
self.projPath = path.abspath(projPath)
if newProject and self.mainConf.showGUI:
if listdir(self.projPath):
self.theParent.makeAlert((
"New project folder is not empty. "
"Each project requires a dedicated project folder."
), nwAlert.ERROR)
return False
self.ensureFolderStructure()
self.setProjectChanged(True)
return True
def setProjectName(self, projName):
+7 -1
View File
@@ -107,7 +107,7 @@ class QConfigLayout(QGridLayout):
return
def addRow(self, theLabel, theWidget, helpText=None, theUnit=None):
def addRow(self, theLabel, theWidget, helpText=None, theUnit=None, theButton=None):
"""Add a label and a widget as a new row of the grid.
"""
thisEntry = {
@@ -152,6 +152,12 @@ class QConfigLayout(QGridLayout):
controlBox.addWidget(QLabel(theUnit), 0, Qt.AlignVCenter)
controlBox.setSpacing(8)
self.addLayout(controlBox, self._nextRow, 1, 1, 1, Qt.AlignRight | Qt.AlignVCenter)
elif theButton is not None:
controlBox = QHBoxLayout()
controlBox.addWidget(qWidget, 0, Qt.AlignVCenter)
controlBox.addWidget(theButton, 0, Qt.AlignVCenter)
controlBox.setSpacing(8)
self.addLayout(controlBox, self._nextRow, 1, 1, 1, Qt.AlignRight | Qt.AlignVCenter)
else:
self.addWidget(qWidget, self._nextRow, 1, 1, 1, Qt.AlignRight | Qt.AlignVCenter)
+162 -23
View File
@@ -26,6 +26,7 @@
"""
import logging
import json
import nw
from os import path
@@ -39,25 +40,27 @@ from PyQt5.QtGui import (
from PyQt5.QtWidgets import (
QDialog, QVBoxLayout, QHBoxLayout, QTextBrowser, QPushButton, QLabel,
QLineEdit, QGroupBox, QGridLayout, QProgressBar, QMenu, QAction,
QFileDialog, QFontComboBox, QSpinBox
QFileDialog, QFontDialog, QSpinBox
)
from nw.gui.additions import QSwitch
from nw.core import ToHtml
from nw.constants import (
nwAlert, nwItemType, nwItemLayout, nwItemClass
nwAlert, nwFiles, nwItemType, nwItemLayout, nwItemClass
)
logger = logging.getLogger(__name__)
class GuiBuildNovel(QDialog):
FMT_ODT = 1
FMT_PDF = 2
FMT_HTM = 3
FMT_MD = 4
FMT_NWD = 5
FMT_TXT = 6
FMT_ODT = 1
FMT_PDF = 2
FMT_HTM = 3
FMT_MD = 4
FMT_NWD = 5
FMT_TXT = 6
FMT_JSON_H = 7
FMT_JSON_M = 8
def __init__(self, theParent, theProject):
QDialog.__init__(self, theParent)
@@ -170,19 +173,21 @@ class GuiBuildNovel(QDialog):
self.textForm = QGridLayout(self)
self.textGroup.setLayout(self.textForm)
self.textFont = QFontComboBox()
self.textFont.setFixedWidth(220)
self.textFont.setToolTip(
"The font is used for PDF and printing. Other formats have no font set."
)
self.textFont.setCurrentFont(
QFont(self.optState.getString("GuiBuildNovel", "textFont", self.mainConf.textFont))
## Font Family
self.textFont = QLineEdit()
self.textFont.setReadOnly(True)
self.textFont.setFixedWidth(182)
self.textFont.setText(
self.optState.getString("GuiBuildNovel", "textFont", self.mainConf.textFont)
)
self.fontButton = QPushButton("...")
self.fontButton.setMaximumWidth(30)
self.fontButton.clicked.connect(self._selectFont)
self.textSize = QSpinBox(self)
self.textSize.setFixedWidth(60)
self.textSize.setMinimum(5)
self.textSize.setMaximum(48)
self.textSize.setMinimum(6)
self.textSize.setMaximum(72)
self.textSize.setSingleStep(1)
self.textSize.setToolTip(
"The size is used for PDF and printing. Other formats have no size set."
@@ -201,13 +206,15 @@ class GuiBuildNovel(QDialog):
self.textForm.addWidget(QLabel("Font family"), 0, 0, 1, 1, Qt.AlignLeft)
self.textForm.addWidget(self.textFont, 0, 1, 1, 1, Qt.AlignRight)
self.textForm.addWidget(self.fontButton, 0, 2, 1, 1, Qt.AlignRight)
self.textForm.addWidget(QLabel("Font size"), 1, 0, 1, 1, Qt.AlignLeft)
self.textForm.addWidget(self.textSize, 1, 1, 1, 1, Qt.AlignRight)
self.textForm.addWidget(self.textSize, 1, 1, 1, 2, Qt.AlignRight)
self.textForm.addWidget(QLabel("Justify text"), 2, 0, 1, 1, Qt.AlignLeft)
self.textForm.addWidget(self.justifyText, 2, 1, 1, 1, Qt.AlignRight)
self.textForm.addWidget(self.justifyText, 2, 1, 1, 2, Qt.AlignRight)
self.textForm.setColumnStretch(0, 1)
self.textForm.setColumnStretch(1, 0)
self.textForm.setColumnStretch(2, 0)
# Include Switches
# ================
@@ -329,7 +336,7 @@ class GuiBuildNovel(QDialog):
self.saveMD.triggered.connect(lambda: self._saveDocument(self.FMT_MD))
self.saveMenu.addAction(self.saveMD)
self.saveNWD = QAction("novelWriter Markdown (.nwd)", self)
self.saveNWD = QAction("%s Markdown (.nwd)" % nw.__package__, self)
self.saveNWD.triggered.connect(lambda: self._saveDocument(self.FMT_NWD))
self.saveMenu.addAction(self.saveNWD)
@@ -337,6 +344,14 @@ class GuiBuildNovel(QDialog):
self.saveTXT.triggered.connect(lambda: self._saveDocument(self.FMT_TXT))
self.saveMenu.addAction(self.saveTXT)
self.saveJsonH = QAction("JSON + %s HTML (.json)" % nw.__package__, self)
self.saveJsonH.triggered.connect(lambda: self._saveDocument(self.FMT_JSON_H))
self.saveMenu.addAction(self.saveJsonH)
self.saveJsonM = QAction("JSON + %s Markdown (.json)" % nw.__package__, self)
self.saveJsonM.triggered.connect(lambda: self._saveDocument(self.FMT_JSON_M))
self.saveMenu.addAction(self.saveJsonM)
self.btnClose = QPushButton("Close")
self.btnClose.clicked.connect(self._doClose)
@@ -368,6 +383,20 @@ class GuiBuildNovel(QDialog):
logger.debug("GuiBuildNovel initialisation complete")
# Load from Cache
if self._loadCache():
textFont = self.textFont.text()
textSize = self.textSize.value()
justifyText = self.justifyText.isChecked()
self.docView.setTextFont(textFont, textSize)
self.docView.setJustify(justifyText)
self.docView.setStyleSheet(self.htmlStyle)
self.docView.setContent(self.htmlText)
else:
self.htmlText = []
self.htmlStyle = []
self.nwdText = []
return
##
@@ -385,7 +414,7 @@ class GuiBuildNovel(QDialog):
fmtScene = self.fmtScene.text().strip()
fmtSection = self.fmtSection.text().strip()
justifyText = self.justifyText.isChecked()
textFont = self.textFont.currentFont().family()
textFont = self.textFont.text()
textSize = self.textSize.value()
incSynopsis = self.includeSynopsis.isChecked()
incComments = self.includeComments.isChecked()
@@ -455,6 +484,8 @@ class GuiBuildNovel(QDialog):
self.docView.setStyleSheet(self.htmlStyle)
self.docView.setContent(self.htmlText)
self._saveCache()
return
def _checkInclude(self, theItem, noteFiles, novelFiles, ignoreFlag):
@@ -530,7 +561,7 @@ class GuiBuildNovel(QDialog):
elif theFormat == self.FMT_NWD:
fileExt = "nwd"
textFmt = "%s markdown" % nw.__package__
textFmt = "%s Markdown" % nw.__package__
outTool = "NW"
elif theFormat == self.FMT_TXT:
@@ -539,6 +570,16 @@ class GuiBuildNovel(QDialog):
textFmt = "Plain Text"
outTool = "Qt"
elif theFormat == self.FMT_JSON_H:
fileExt = "json"
textFmt = "JSON + %s HTML" % nw.__package__
outTool = "NW"
elif theFormat == self.FMT_JSON_M:
fileExt = "json"
textFmt = "JSON + %s Markdown" % nw.__package__
outTool = "NW"
else:
return False
@@ -612,6 +653,33 @@ class GuiBuildNovel(QDialog):
for aLine in self.nwdText:
outFile.write(aLine)
elif theFormat == self.FMT_JSON_H or theFormat == self.FMT_JSON_M:
jsonData = {
"meta" : {
"workingTitle" : self.theProject.projName,
"novelTitle" : self.theProject.bookTitle,
"authors" : self.theProject.bookAuthors,
}
}
if theFormat == self.FMT_JSON_H:
theBody = []
for htmlPage in self.htmlText:
theBody.append(htmlPage.rstrip("\n").split("\n"))
jsonData["text"] = {
"css" : self.htmlStyle,
"html" : theBody,
}
elif theFormat == self.FMT_JSON_M:
theBody = []
for nwdPage in self.nwdText:
theBody.append(nwdPage.split("\n"))
jsonData["text"] = {
"nwd" : theBody,
}
outFile.write(json.dumps(jsonData, indent=2))
wSuccess = True
except Exception as e:
@@ -667,6 +735,72 @@ class GuiBuildNovel(QDialog):
self.docView.qDocument.print(thePrinter)
return
def _selectFont(self):
"""Open the QFontDialog and set a font for the font style.
"""
currFont = QFont()
currFont.setFamily(self.textFont.text())
currFont.setPointSize(self.textSize.value())
theFont, theStatus = QFontDialog.getFont(currFont, self)
if theStatus:
self.textFont.setText(theFont.family())
self.textSize.setValue(theFont.pointSize())
return
def _loadCache(self):
"""Save the current data to cache.
"""
buildCache = path.join(self.theProject.projCache, nwFiles.BUILD_CACHE)
dataCount = 0
if path.isfile(buildCache):
logger.debug("Loading build cache")
try:
with open(buildCache, mode="r", encoding="utf8") as inFile:
theJson = inFile.read()
theData = json.loads(theJson)
except Exception as e:
logger.error("Failed to load build cache")
logger.error(str(e))
return False
if "htmlText" in theData.keys():
self.htmlText = theData["htmlText"]
dataCount += 1
if "htmlStyle" in theData.keys():
self.htmlStyle = theData["htmlStyle"]
dataCount += 1
if "nwdText" in theData.keys():
self.nwdText = theData["nwdText"]
dataCount += 1
return dataCount == 3
def _saveCache(self):
"""Save the current data to cache.
"""
buildCache = path.join(self.theProject.projCache, nwFiles.BUILD_CACHE)
if self.mainConf.debugInfo:
nIndent = 2
else:
nIndent = None
logger.debug("Saving build cache")
try:
with open(buildCache, mode="w+", encoding="utf8") as outFile:
outFile.write(json.dumps({
"htmlText" : self.htmlText,
"htmlStyle" : self.htmlStyle,
"nwdText" : self.nwdText,
}, indent=nIndent))
except Exception as e:
logger.error("Failed to save build cache")
logger.error(str(e))
return False
return True
def _doClose(self):
"""Close button was clicked.
"""
@@ -709,7 +843,7 @@ class GuiBuildNovel(QDialog):
self.optState.setValue("GuiBuildNovel", "winWidth", self.width())
self.optState.setValue("GuiBuildNovel", "winHeight", self.height())
self.optState.setValue("GuiBuildNovel", "justifyText", self.justifyText.isChecked())
self.optState.setValue("GuiBuildNovel", "textFont", self.textFont.currentFont().family())
self.optState.setValue("GuiBuildNovel", "textFont", self.textFont.text())
self.optState.setValue("GuiBuildNovel", "textSize", self.textSize.value())
self.optState.setValue("GuiBuildNovel", "addNovel", self.novelFiles.isChecked())
self.optState.setValue("GuiBuildNovel", "addNotes", self.noteFiles.isChecked())
@@ -746,6 +880,11 @@ class GuiBuildNovelDocView(QTextBrowser):
self.qDocument = self.document()
self.qDocument.setDocumentMargin(self.mainConf.textMargin)
self.setPlaceholderText(
"This area will show the content of the document to be "
"exported or printed. Press the \"Build Novel Project\" "
"button to generate content."
)
theFont = QFont()
if self.mainConf.textFont is None:
+78 -11
View File
@@ -33,9 +33,8 @@ from os import path
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QFont
from PyQt5.QtWidgets import (
QDialog, QWidget, QHBoxLayout, QVBoxLayout, QTabWidget, QComboBox, QSpinBox,
QPushButton, QFontComboBox, QLineEdit, QDialogButtonBox, QMessageBox,
QFileDialog
QDialog, QWidget, QComboBox, QSpinBox, QPushButton, QLineEdit, QMessageBox,
QDialogButtonBox, QFileDialog, QFontDialog
)
from nw.gui.additions import QSwitch, QConfigLayout, PagedDialog
@@ -183,6 +182,34 @@ class GuiConfigEditGeneralTab(QWidget):
"This may improve the look of icons on dark themes."
)
## Font Family
self.guiFont = QLineEdit()
self.guiFont.setReadOnly(True)
self.guiFont.setFixedWidth(162)
self.guiFont.setText(self.mainConf.guiFont)
self.fontButton = QPushButton("...")
self.fontButton.setMaximumWidth(30)
self.fontButton.clicked.connect(self._selectFont)
self.mainForm.addRow(
"Font family",
self.guiFont,
"Changing this requires restarting %s." % nw.__package__,
theButton = self.fontButton
)
## Font Size
self.guiFontSize = QSpinBox(self)
self.guiFontSize.setMinimum(8)
self.guiFontSize.setMaximum(60)
self.guiFontSize.setSingleStep(1)
self.guiFontSize.setValue(self.mainConf.guiFontSize)
self.mainForm.addRow(
"Font size",
self.guiFontSize,
"Changing this requires restarting %s." % nw.__package__,
theUnit = "pt"
)
# GUI Settings
# ============
self.mainForm.addGroupLabel("GUI Settings")
@@ -266,6 +293,8 @@ class GuiConfigEditGeneralTab(QWidget):
guiTheme = self.selectTheme.currentData()
guiIcons = self.selectIcons.currentData()
guiDark = self.preferDarkIcons.isChecked()
guiFont = self.guiFont.text()
guiFontSize = self.guiFontSize.value()
showFullPath = self.showFullPath.isChecked()
autoSaveDoc = self.autoSaveDoc.value()
autoSaveProj = self.autoSaveProj.value()
@@ -276,10 +305,14 @@ class GuiConfigEditGeneralTab(QWidget):
# Check if restart is needed
needsRestart |= self.mainConf.guiTheme != guiTheme
needsRestart |= self.mainConf.guiIcons != guiIcons
needsRestart |= self.mainConf.guiFont != guiFont
needsRestart |= self.mainConf.guiFontSize != guiFontSize
self.mainConf.guiTheme = guiTheme
self.mainConf.guiIcons = guiIcons
self.mainConf.guiDark = guiDark
self.mainConf.guiFont = guiFont
self.mainConf.guiFontSize = guiFontSize
self.mainConf.showFullPath = showFullPath
self.mainConf.autoSaveDoc = autoSaveDoc
self.mainConf.autoSaveProj = autoSaveProj
@@ -321,6 +354,18 @@ class GuiConfigEditGeneralTab(QWidget):
self.askBeforeBackup.setEnabled(theState)
return
def _selectFont(self):
"""Open the QFontDialog and set a font for the font style.
"""
currFont = QFont()
currFont.setFamily(self.mainConf.guiFont)
currFont.setPointSize(self.mainConf.guiFontSize)
theFont, theStatus = QFontDialog.getFont(currFont, self)
if theStatus:
self.guiFont.setText(theFont.family())
self.guiFontSize.setValue(theFont.pointSize())
return
# END Class GuiConfigEditGeneralTab
class GuiConfigEditLayoutTab(QWidget):
@@ -341,26 +386,32 @@ class GuiConfigEditLayoutTab(QWidget):
# ==========
self.mainForm.addGroupLabel("Text Style")
## Font Family
self.textStyleFont = QFontComboBox()
self.textStyleFont.setMaximumWidth(200)
self.textStyleFont.setCurrentFont(QFont(self.mainConf.textFont))
self.textStyleFont = QLineEdit()
self.textStyleFont.setReadOnly(True)
self.textStyleFont.setFixedWidth(162)
self.textStyleFont.setText(self.mainConf.textFont)
self.fontButton = QPushButton("...")
self.fontButton.setMaximumWidth(30)
self.fontButton.clicked.connect(self._selectFont)
self.mainForm.addRow(
"Font family",
self.textStyleFont,
"Font for the document editor and viewer."
"Font for the document editor and viewer.",
theButton = self.fontButton
)
## Font Size
self.textStyleSize = QSpinBox(self)
self.textStyleSize.setMinimum(5)
self.textStyleSize.setMaximum(120)
self.textStyleSize.setMinimum(8)
self.textStyleSize.setMaximum(60)
self.textStyleSize.setSingleStep(1)
self.textStyleSize.setValue(self.mainConf.textSize)
self.mainForm.addRow(
"Font size",
self.textStyleSize,
theUnit="pt"
theUnit = "pt"
)
# Text Flow
@@ -461,7 +512,7 @@ class GuiConfigEditLayoutTab(QWidget):
validEntries = True
needsRestart = False
textFont = self.textStyleFont.currentFont().family()
textFont = self.textStyleFont.text()
textSize = self.textStyleSize.value()
textWidth = self.textFlowMax.value()
zenWidth = self.zenDocWidth.value()
@@ -487,6 +538,22 @@ class GuiConfigEditLayoutTab(QWidget):
return validEntries, needsRestart
##
# Slots
##
def _selectFont(self):
"""Open the QFontDialog and set a font for the font style.
"""
currFont = QFont()
currFont.setFamily(self.mainConf.textFont)
currFont.setPointSize(self.mainConf.textSize)
theFont, theStatus = QFontDialog.getFont(currFont, self)
if theStatus:
self.textStyleFont.setText(theFont.family())
self.textStyleSize.setValue(theFont.pointSize())
return
# END Class GuiConfigEditLayoutTab
class GuiConfigEditEditingTab(QWidget):
+40 -22
View File
@@ -29,7 +29,7 @@ import logging
import nw
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QFont
from PyQt5.QtGui import QFont, QIcon, QPixmap
from PyQt5.QtWidgets import QFrame, QGridLayout, QLabel
from nw.constants import (
@@ -47,30 +47,34 @@ class GuiDocDetails(QFrame):
self.mainConf = nw.CONFIG
self.theParent = theParent
self.theProject = theProject
self.theTheme = theParent.theTheme
self.theHandle = None
self.mainBox = QGridLayout(self)
self.mainBox.setVerticalSpacing(1)
self.mainBox.setHorizontalSpacing(6)
self.setLayout(self.mainBox)
self.fntLabel = QFont()
self.fntLabel.setPointSize(10)
self.fntLabel.setBold(True)
self.pS = 0.9*self.theTheme.fontPointSize
self.iPx = self.theTheme.textIconSize
self.sPx = int(round(0.8*self.theTheme.textIconSize))
self.fntFixed = QFont()
self.fntFixed.setFamily("Monospace")
self.fntFixed.setPointSize(10)
self.expCheck = self.theTheme.getPixmap("check", (self.iPx, self.iPx))
self.expCross = self.theTheme.getPixmap("cross", (self.iPx, self.iPx))
self.fntLabel = QFont()
self.fntLabel.setBold(True)
self.fntLabel.setPointSizeF(self.pS)
self.fntValue = QFont()
self.fntValue.setPointSize(10)
self.fntValue.setPointSizeF(self.pS)
# Label
self.labelName = QLabel("Label ")
self.labelName = QLabel("Label")
self.labelName.setFont(self.fntLabel)
self.labelName.setAlignment(Qt.AlignLeft | Qt.AlignBaseline)
self.labelFlag = QLabel("")
self.labelFlag.setFont(self.fntFixed)
self.labelFlag.setAlignment(Qt.AlignRight | Qt.AlignBaseline)
self.labelData = QLabel("")
@@ -79,12 +83,11 @@ class GuiDocDetails(QFrame):
self.labelData.setWordWrap(True)
# Status
self.statusName = QLabel("Status ")
self.statusName = QLabel("Status")
self.statusName.setFont(self.fntLabel)
self.statusName.setAlignment(Qt.AlignLeft)
self.statusFlag = QLabel("")
self.statusFlag.setFont(self.fntFixed)
self.statusFlag.setAlignment(Qt.AlignRight | Qt.AlignVCenter)
self.statusData = QLabel("")
@@ -92,12 +95,12 @@ class GuiDocDetails(QFrame):
self.statusData.setAlignment(Qt.AlignLeft)
# Class
self.className = QLabel("Class ")
self.className = QLabel("Class")
self.className.setFont(self.fntLabel)
self.className.setAlignment(Qt.AlignLeft)
self.classFlag = QLabel("")
self.classFlag.setFont(self.fntFixed)
self.classFlag.setFont(self.fntValue)
self.classFlag.setAlignment(Qt.AlignRight)
self.classData = QLabel("")
@@ -105,12 +108,12 @@ class GuiDocDetails(QFrame):
self.classData.setAlignment(Qt.AlignLeft)
# Layout
self.layoutName = QLabel("Layout ")
self.layoutName = QLabel("Layout")
self.layoutName.setFont(self.fntLabel)
self.layoutName.setAlignment(Qt.AlignLeft)
self.layoutFlag = QLabel("")
self.layoutFlag.setFont(self.fntFixed)
self.layoutFlag.setFont(self.fntValue)
self.layoutFlag.setAlignment(Qt.AlignRight)
self.layoutData = QLabel("")
@@ -173,6 +176,12 @@ class GuiDocDetails(QFrame):
self.mainBox.setColumnStretch(3,0)
self.mainBox.setColumnStretch(4,0)
# Make sure the columns for flags and counts don't resize too often
flagWidth = self.theTheme.getTextWidth("Mm", self.fntValue)
countWidth = self.theTheme.getTextWidth("99,999", self.fntValue)
self.mainBox.setColumnMinimumWidth(1, flagWidth)
self.mainBox.setColumnMinimumWidth(4, countWidth)
logger.debug("DocDetails initialisation complete")
return
@@ -181,9 +190,20 @@ class GuiDocDetails(QFrame):
# Class Methods
##
def updateCounts(self, tHandle, cC, wC, pC):
"""Just update the counts if the handle is the same as the one
we're already showing.
"""
if tHandle == self.theHandle:
self.cCountData.setText("{:n}".format(cC))
self.wCountData.setText("{:n}".format(wC))
self.pCountData.setText("{:n}".format(pC))
return
def updateViewBox(self, tHandle):
"""Populate the details box from a given handle.
"""
self.theHandle = tHandle
nwItem = self.theProject.projTree[tHandle]
if nwItem is None:
@@ -214,14 +234,12 @@ class GuiDocDetails(QFrame):
if nwItem.itemType == nwItemType.FILE:
if nwItem.isExported:
exportFlag = nwUnicode.U_CHECK
self.labelFlag.setPixmap(self.expCheck)
else:
exportFlag = " "
self.labelFlag.setPixmap(self.expCross)
else:
exportFlag = "-"
self.labelFlag.setText(exportFlag)
self.statusFlag.setPixmap(flagIcon.pixmap(10, 10))
self.labelFlag.setPixmap(QPixmap(1,1))
self.statusFlag.setPixmap(flagIcon.pixmap(self.sPx, self.sPx))
self.classFlag.setText(nwLabels.CLASS_FLAG[nwItem.itemClass])
if nwItem.itemLayout == nwItemLayout.NO_LAYOUT:
self.layoutFlag.setText("-")
+19 -9
View File
@@ -300,15 +300,16 @@ class GuiDocEditor(QTextEdit):
docText = self.getText()
cursPos = self.getCursorPosition()
theItem = self.nwDocument.theItem
theItem.setCharCount(self.charCount)
theItem.setWordCount(self.wordCount)
theItem.setParaCount(self.paraCount)
theItem.setCursorPos(cursPos)
self.nwDocument.theItem.setCharCount(self.charCount)
self.nwDocument.theItem.setWordCount(self.wordCount)
self.nwDocument.theItem.setParaCount(self.paraCount)
self.nwDocument.theItem.setCursorPos(cursPos)
self.nwDocument.saveDocument(docText)
self.setDocumentChanged(False)
self.theParent.theIndex.scanText(theItem.itemHandle, docText)
self.theParent.theIndex.scanText(
self.nwDocument.theItem.itemHandle, docText
)
return True
@@ -737,15 +738,24 @@ class GuiDocEditor(QTextEdit):
def _updateCounts(self):
"""Slot for the word counter's finished signal
"""
if self.theHandle is None or self.nwDocument.theItem is None:
return
logger.verbose("Updating word count")
tHandle = self.nwDocument.docHandle
self.charCount = self.wCounter.charCount
self.wordCount = self.wCounter.wordCount
self.paraCount = self.wCounter.paraCount
self.theParent.statusBar.setCounts(self.charCount,self.wordCount,self.paraCount)
self.theParent.treeView.propagateCount(tHandle, self.wordCount)
self.nwDocument.theItem.setCharCount(self.charCount)
self.nwDocument.theItem.setWordCount(self.wordCount)
self.nwDocument.theItem.setParaCount(self.paraCount)
self.theParent.statusBar.setCounts(self.charCount, self.wordCount, self.paraCount)
self.theParent.treeView.propagateCount(self.theHandle, self.wordCount)
self.theParent.treeView.projectWordCount()
self.theParent.treeMeta.updateCounts(
self.theHandle, self.charCount, self.wordCount, self.paraCount
)
self._checkDocSize(self.charCount)
return
+3 -2
View File
@@ -52,19 +52,20 @@ class GuiDocTitleBar(QLabel):
self.setText("")
self.setIndent(0)
self.setMargin(0)
self.setContentsMargins(0,0,0,0)
self.setContentsMargins(0, 0, 0, 0)
self.setAutoFillBackground(True)
self.setAlignment(Qt.AlignCenter)
self.setWordWrap(True)
self.setFrameShape(QFrame.NoFrame)
self.setLineWidth(0)
lblPalette = self.palette()
lblPalette.setColor(QPalette.Window, QColor(*self.theTheme.colBack))
lblPalette.setColor(QPalette.Text, QColor(*self.theTheme.colText))
self.setPalette(lblPalette)
lblFont = self.font()
lblFont.setPointSizeF(0.9*self.theTheme.defFontSize)
lblFont.setPointSizeF(0.9*self.theTheme.fontPointSize)
self.setFont(lblFont)
logger.debug("DocTitleBar initialisation complete")
+38 -33
View File
@@ -29,7 +29,7 @@ import logging
import nw
from PyQt5.QtCore import Qt, QSize
from PyQt5.QtGui import QFont, QColor
from PyQt5.QtGui import QFont, QColor, QIcon
from PyQt5.QtWidgets import (
qApp, QTreeWidget, QTreeWidgetItem, QAbstractItemView, QMessageBox
)
@@ -45,8 +45,9 @@ class GuiDocTree(QTreeWidget):
C_NAME = 0
C_COUNT = 1
C_FLAGS = 2
C_HANDLE = 3
C_EXPORT = 2
C_FLAGS = 3
C_HANDLE = 4
def __init__(self, theParent, theProject):
QTreeWidget.__init__(self, theParent)
@@ -64,15 +65,20 @@ class GuiDocTree(QTreeWidget):
self.clearTree()
# Build GUI
self.setIconSize(QSize(13,13))
iPx = self.theTheme.textIconSize
self.setIconSize(QSize(iPx, iPx))
self.setExpandsOnDoubleClick(True)
self.setIndentation(13)
self.setColumnCount(4)
self.setHeaderLabels(["Label","Words","Flags","Handle"])
self.setIndentation(iPx)
self.setColumnCount(5)
self.setHeaderLabels(["Label", "Words", "Inc", "Flags", "Handle"])
self.hideColumn(self.C_HANDLE)
treeHead = self.headerItem()
treeHead.setTextAlignment(self.C_COUNT,Qt.AlignRight)
treeHead.setTextAlignment(self.C_COUNT, Qt.AlignRight)
treeHead.setToolTip(self.C_NAME, "Item label")
treeHead.setToolTip(self.C_COUNT, "Word count")
treeHead.setToolTip(self.C_EXPORT, "Include in build")
treeHead.setToolTip(self.C_FLAGS, "Status, class, and layout flags")
# Allow Move by Drag & Drop
self.setDragEnabled(True)
@@ -87,11 +93,11 @@ class GuiDocTree(QTreeWidget):
# self.setSelectionMode(QAbstractItemView.ExtendedSelection)
# self.setSelectionBehavior(QAbstractItemView.SelectRows)
for colN in range(len(self.mainConf.treeColWidth)):
self.setColumnWidth(colN,self.mainConf.treeColWidth[colN])
for colN, colW in enumerate(self.mainConf.treeColWidth):
self.setColumnWidth(colN, colW)
self.fontFlags = QFont("Monospace",10)
self.fontCount = QFont("Monospace",10)
self.resizeColumnToContents(self.C_EXPORT)
self.resizeColumnToContents(self.C_FLAGS)
logger.debug("DocTree initialisation complete")
@@ -200,8 +206,8 @@ class GuiDocTree(QTreeWidget):
def revealTreeItem(self, tHandle):
"""Reveal a newly added project item in the project tree.
"""
nwItem = self.theProject.projTree[tHandle]
trItem = self._addTreeItem(nwItem)
nwItem = self.theProject.projTree[tHandle]
trItem = self._addTreeItem(nwItem)
pHandle = nwItem.parHandle
if pHandle is not None and pHandle in self.theMap.keys():
self.theMap[pHandle].setExpanded(True)
@@ -271,7 +277,6 @@ class GuiDocTree(QTreeWidget):
retVals = [
self.columnWidth(0),
self.columnWidth(1),
self.columnWidth(2),
]
return retVals
@@ -422,30 +427,30 @@ class GuiDocTree(QTreeWidget):
tHandle = nwItem.itemHandle
pHandle = nwItem.parHandle
stExport = " "
stClass = nwLabels.CLASS_FLAG[nwItem.itemClass]
stLayout = ""
expIcon = QIcon()
stClass = nwLabels.CLASS_FLAG[nwItem.itemClass]
stLayout = ""
if nwItem.itemType == nwItemType.FILE:
stLayout = "."+nwLabels.LAYOUT_FLAG[nwItem.itemLayout]
if nwItem.isExported:
stExport = nwUnicode.U_CHECK
else:
stExport = "-"
tStatus = stExport+" "+stClass+stLayout
expIcon = self.theTheme.getIcon("check")
else:
expIcon = self.theTheme.getIcon("cross")
tStatus = stClass+stLayout
iStatus = nwItem.itemStatus
if tClass == nwItemClass.NOVEL:
iStatus = self.theProject.statusItems.checkEntry(iStatus) # Make sure it's valid
iStatus = self.theProject.statusItems.checkEntry(iStatus) # Make sure it's valid
flagIcon = self.theParent.statusIcons[iStatus]
else:
iStatus = self.theProject.importItems.checkEntry(iStatus) # Make sure it's valid
iStatus = self.theProject.importItems.checkEntry(iStatus) # Make sure it's valid
flagIcon = self.theParent.importIcons[iStatus]
trItem.setText(self.C_NAME, tName)
trItem.setText(self.C_FLAGS,tStatus)
trItem.setIcon(self.C_FLAGS,flagIcon)
trItem.setIcon(self.C_EXPORT, expIcon)
trItem.setText(self.C_FLAGS, tStatus)
trItem.setIcon(self.C_FLAGS, flagIcon)
return
@@ -569,12 +574,11 @@ class GuiDocTree(QTreeWidget):
newItem.setText(self.C_NAME, "")
newItem.setText(self.C_COUNT, "0")
newItem.setText(self.C_EXPORT, "")
newItem.setText(self.C_FLAGS, "")
newItem.setText(self.C_HANDLE, tHandle)
# newItem.setForeground(self.C_COUNT,QColor(*self.theParent.theTheme.treeWCount))
newItem.setTextAlignment(self.C_COUNT, Qt.AlignRight)
newItem.setFont(self.C_FLAGS, self.fontFlags)
self.theMap[tHandle] = newItem
if pHandle is None:
@@ -608,15 +612,15 @@ class GuiDocTree(QTreeWidget):
"""Adds the trash root folder if it doesn't already exist in the
project tree.
"""
trashHandle = self.theProject.projTree.trashRoot()
trashHandle = self.theProject.trashFolder()
if trashHandle is None:
self.theProject.addTrash()
return None
trItem = self._getTreeItem(trashHandle)
if trItem is None:
trItem = self._addTreeItem(
self.theProject.projTree[trashHandle]
)
trItem.setExpanded(True)
else:
trItem = self._getTreeItem(trashHandle)
return trItem
def _addOrphanedRoot(self):
@@ -627,6 +631,7 @@ class GuiDocTree(QTreeWidget):
newItem = QTreeWidgetItem([""]*4)
newItem.setText(self.C_NAME, "Orphaned Files")
newItem.setText(self.C_COUNT, "")
newItem.setText(self.C_EXPORT, "")
newItem.setText(self.C_FLAGS, "")
newItem.setText(self.C_HANDLE, "")
self.addTopLevelItem(newItem)
+2
View File
@@ -93,6 +93,8 @@ class GuiIcons:
"clear" : (QStyle.SP_LineEditClearButton, "clear_left"),
"save" : (QStyle.SP_DialogSaveButton, "document-save"),
"edit" : (None, None),
"check" : (None, None),
"cross" : (None, None),
## Other Icons
"warning" : (QStyle.SP_MessageBoxWarning, "dialog-warning"),
+13 -12
View File
@@ -48,6 +48,7 @@ class GuiMainStatus(QStatusBar):
self.mainConf = nw.CONFIG
self.theParent = theParent
self.theTheme = theParent.theTheme
self.refTime = None
self.charCount = 0
@@ -56,11 +57,11 @@ class GuiMainStatus(QStatusBar):
self.projWords = 0
self.sessWords = 0
self.monoFont = QFont("Monospace",10)
colNone = QColor(*self.theTheme.statNone)
colTrue = QColor(*self.theTheme.statUnsaved)
colFalse = QColor(*self.theTheme.statSaved)
colNone = QColor(*self.theParent.theTheme.statNone)
colTrue = QColor(*self.theParent.theTheme.statUnsaved)
colFalse = QColor(*self.theParent.theTheme.statSaved)
iPx = self.theTheme.textIconSize
# Permanent Widgets
# =================
@@ -68,14 +69,14 @@ class GuiMainStatus(QStatusBar):
## The Spell Checker Language
self.langIcon = QLabel("")
self.langText = QLabel("None")
self.langIcon.setPixmap(self.theParent.theTheme.getPixmap("status_lang",(14,14)))
self.langIcon.setPixmap(self.theTheme.getPixmap("status_lang", (iPx, iPx)))
self.langIcon.setContentsMargins(0, 0, 0, 0)
self.langText.setContentsMargins(0, 0, 8, 0)
self.addPermanentWidget(self.langIcon)
self.addPermanentWidget(self.langText)
## The Editor Status
self.docIcon = StatusLED(colNone, colTrue, colFalse, 14, 14, self)
self.docIcon = StatusLED(colNone, colTrue, colFalse, iPx, iPx, self)
self.docText = QLabel("Editor")
self.docIcon.setContentsMargins(0, 0, 0, 0)
self.docText.setContentsMargins(0, 0, 8, 0)
@@ -83,7 +84,7 @@ class GuiMainStatus(QStatusBar):
self.addPermanentWidget(self.docText)
## The Project Status
self.projIcon = StatusLED(colNone, colTrue, colFalse, 14, 14, self)
self.projIcon = StatusLED(colNone, colTrue, colFalse, iPx, iPx, self)
self.projText = QLabel("Project")
self.projIcon.setContentsMargins(0, 0, 0, 0)
self.projText.setContentsMargins(0, 0, 8, 0)
@@ -93,19 +94,19 @@ class GuiMainStatus(QStatusBar):
## The Project and Session Stats
self.statsIcon = QLabel()
self.statsText = QLabel("")
self.statsIcon.setPixmap(self.theParent.theTheme.getPixmap("status_stats",(14,14)))
self.statsIcon.setPixmap(self.theTheme.getPixmap("status_stats", (iPx, iPx)))
self.statsIcon.setContentsMargins(0, 0, 0, 0)
self.statsText.setContentsMargins(0, 0, 8, 0)
self.addPermanentWidget(self.statsIcon)
self.addPermanentWidget(self.statsText)
## The Session Clock
### Set the mimimum width so the label doesn't rescale every second
self.timeIcon = QLabel()
self.timeText = QLabel("")
self.timeIcon.setPixmap(self.theParent.theTheme.getPixmap("status_time",(14,14)))
self.timeIcon.setPixmap(self.theTheme.getPixmap("status_time", (iPx, iPx)))
self.timeText.setToolTip("Session Time")
self.timeText.setAlignment(Qt.AlignVCenter | Qt.AlignRight)
self.timeText.setFont(self.monoFont)
self.timeText.setMinimumWidth(self.theTheme.getTextWidth("00:00:00:"))
self.timeIcon.setContentsMargins(0, 0, 0, 0)
self.timeText.setContentsMargins(0, 0, 0, 0)
self.addPermanentWidget(self.timeIcon)
@@ -200,7 +201,7 @@ class GuiMainStatus(QStatusBar):
"""Update statistics.
"""
self.statsText.setToolTip(
"D: Document word count<br>P: Project word count"
"D: Document word count<br>P: Project word count (session change)"
)
self.statsText.setText((
"D:{wC:n} P:{pWC:n} ({sWC:+n})"
+78 -5
View File
@@ -30,9 +30,12 @@ import configparser
import nw
from os import path, listdir
from math import ceil
from PyQt5.QtWidgets import qApp
from PyQt5.QtGui import QPalette, QColor, QIcon
from PyQt5.QtGui import (
QPalette, QColor, QIcon, QFont, QFontMetrics, QFontDatabase
)
from nw.constants import nwAlert
from nw.gui.icons import GuiIcons
@@ -48,7 +51,7 @@ class GuiTheme:
self.theIcons = GuiIcons(self.theParent)
self.guiPalette = QPalette()
self.guiPath = "gui"
self.iconPath = "icons"
self.fontPath = "fonts"
self.syntaxPath = "syntax"
self.cssName = "style.qss"
self.confName = "theme.conf"
@@ -110,7 +113,10 @@ class GuiTheme:
self.syntaxFile = None
self.confFile = None
self.cssFile = None
self.guiFontDB = QFontDatabase()
self.loadFonts()
self.updateFont()
self.updateTheme()
self.theIcons.updateTheme()
@@ -119,19 +125,86 @@ class GuiTheme:
self.loadDecoration = self.theIcons.loadDecoration
# Extract Other Info
self.defFont = qApp.font()
self.defFontSize = self.defFont.pointSizeF()
self.guiDPI = qApp.primaryScreen().physicalDotsPerInch()
self.guiFont = qApp.font()
qMetric = QFontMetrics(self.guiFont)
self.fontPointSize = self.guiFont.pointSizeF()
self.fontPixelSize = int(round(qMetric.height()))
self.baseIconSize = int(round(qMetric.ascent()))
self.textIconSize = int(round(qMetric.ascent() + qMetric.leading()))
logger.verbose("GUI Font Family: %s" % self.guiFont.family())
logger.verbose("GUI Font Point Size: %.2f" % self.fontPointSize)
logger.verbose("GUI Font Pixel Size: %d" % self.fontPixelSize)
logger.verbose("GUI Base Icon Size: %d" % self.baseIconSize)
logger.verbose("GUI Text Icon Size: %d" % self.textIconSize)
return
##
# Methods
##
def getTextWidth(self, theText, theFont=None):
"""Returns the width needed to contain a given piece of text.
"""
if isinstance(theFont, QFont):
qMetrics = QFontMetrics(theFont)
else:
qMetrics = QFontMetrics(self.guiFont)
return int(ceil(qMetrics.boundingRect(theText).width()))
##
# Actions
##
def loadFonts(self):
"""Add the fonts in the assets fonts folder to the app.
"""
ttfList = []
fontAssets = path.join(self.mainConf.assetPath, self.fontPath)
for fontFam in listdir(fontAssets):
fontDir = path.join(fontAssets, fontFam)
if path.isdir(fontDir):
if not fontFam in self.guiFontDB.families():
for fontFile in listdir(fontDir):
ttfFile = path.join(fontDir, fontFile)
if path.isfile(ttfFile) and fontFile.endswith(".ttf"):
ttfList.append(ttfFile)
for ttfFile in ttfList:
logger.verbose("Font asset: %s" % path.relpath(ttfFile))
fontID = self.guiFontDB.addApplicationFont(ttfFile)
if fontID < 0:
logger.error("Failed to add font: %s" % path.relpath(ttfFile))
return
def updateFont(self):
"""Updated the GUI's font style from settings,
"""
theFont = QFont()
if self.mainConf.guiFont not in self.guiFontDB.families():
if self.mainConf.osWindows:
# On Windows, default to Cantarell provided by novelWriter
theFont.setFamily("Cantarell")
theFont.setPointSize(11)
else:
theFont = self.guiFontDB.systemFont(QFontDatabase.GeneralFont)
self.mainConf.guiFont = theFont.family()
self.mainConf.guiFontSize = theFont.pointSize()
else:
theFont.setFamily(self.mainConf.guiFont)
theFont.setPointSize(self.mainConf.guiFontSize)
qApp.setFont(theFont)
return
def updateTheme(self):
"""Update the GUI theme from theme files.
"""
self.guiTheme = self.mainConf.guiTheme
self.guiSyntax = self.mainConf.guiSyntax
self.themeRoot = self.mainConf.themeRoot
+27 -17
View File
@@ -294,12 +294,14 @@ class GuiMain(QMainWindow):
return False
logger.info("Creating new project")
self.theProject.newProject()
self.theProject.setProjectPath(projPath)
self.rebuildTree()
self.saveProject()
self.hasProject = True
self.statusBar.setRefTime(self.theProject.projOpened)
if self.theProject.setProjectPath(projPath, newProject=True):
self.theProject.newProject()
self.rebuildTree()
self.saveProject()
self.hasProject = True
self.statusBar.setRefTime(self.theProject.projOpened)
else:
return False
return True
@@ -1017,25 +1019,33 @@ class GuiMain(QMainWindow):
return
def _treeDoubleClick(self, tItem, colNo):
tHandle = tItem.text(3)
"""The user double-clicked an item in the tree. If it is a file,
we open it. Otherwise, we do nothing.
"""
tHandle = tItem.text(self.treeView.C_HANDLE)
logger.verbose("User double clicked tree item with handle %s" % tHandle)
nwItem = self.theProject.projTree[tHandle]
if nwItem.itemType == nwItemType.FILE:
logger.verbose("Requested item %s is a file" % tHandle)
self.openDocument(tHandle)
else:
logger.verbose("Requested item %s is a folder" % tHandle)
if nwItem is not None:
if nwItem.itemType == nwItemType.FILE:
logger.verbose("Requested item %s is a file" % tHandle)
self.openDocument(tHandle)
else:
logger.verbose("Requested item %s is a folder" % tHandle)
return
def _treeKeyPressReturn(self):
"""The user pressed return an item in the tree. If it is a file,
we open it. Otherwise, we do nothing.
"""
tHandle = self.treeView.getSelectedHandle()
logger.verbose("User pressed return on tree item with handle %s" % tHandle)
nwItem = self.theProject.projTree[tHandle]
if nwItem.itemType == nwItemType.FILE:
logger.verbose("Requested item %s is a file" % tHandle)
self.openDocument(tHandle)
else:
logger.verbose("Requested item %s is a folder" % tHandle)
if nwItem is not None:
if nwItem.itemType == nwItemType.FILE:
logger.verbose("Requested item %s is a file" % tHandle)
self.openDocument(tHandle)
else:
logger.verbose("Requested item %s is a folder" % tHandle)
return
def _keyPressEscape(self):
+10 -3
View File
@@ -1,5 +1,5 @@
<?xml version='1.0' encoding='utf-8'?>
<novelWriterXML appVersion="0.7.0rc1" hexVersion="0x000700c1" fileVersion="1.1" saveCount="4" autoCount="0" timeStamp="2020-05-29 23:06:02">
<novelWriterXML appVersion="0.7.0rc1" hexVersion="0x000700c1" fileVersion="1.1" saveCount="4" autoCount="1" timeStamp="2020-05-30 15:31:30" editTime="12">
<project>
<name>New Project</name>
<title></title>
@@ -9,7 +9,7 @@
<spellCheck>True</spellCheck>
<autoOutline>True</autoOutline>
<lastEdited>31489056e0916</lastEdited>
<lastViewed>31489056e0916</lastViewed>
<lastViewed>None</lastViewed>
<lastWordCount>86</lastWordCount>
<autoReplace/>
<titleFormat>
@@ -35,7 +35,7 @@
<entry blue="0" green="200" red="50">Main</entry>
</importance>
</settings>
<content count="9">
<content count="10">
<item handle="73475cb40a568" order="0" parent="None">
<name>Novel</name>
<type>ROOT</type>
@@ -119,5 +119,12 @@
<paraCount>1</paraCount>
<cursorPos>68</cursorPos>
</item>
<item handle="41cfc0d1f2d12" order="4" parent="None">
<name>Trash</name>
<type>TRASH</type>
<class>TRASH</class>
<status>None</status>
<expanded>True</expanded>
</item>
</content>
</novelWriterXML>
+2
View File
@@ -4,6 +4,8 @@ theme = default
syntax = default_light
icons = typicons_grey_light
guidark = False
guifont =
guifontsize = 11
[Sizes]
geometry = 1100, 650
+9
View File
@@ -235,6 +235,15 @@ def testMainWindows(qtbot, nwTempGUI, nwRef, nwTemp):
assert nwGUI.closeDocViewer()
qtbot.wait(stepDelay)
# Check a Quick Create and Delete
assert nwGUI.treeView.newTreeItem(nwItemType.FILE, None)
newHandle = nwGUI.treeView.getSelectedHandle()
assert nwGUI.theProject.projTree["031b4af5197ec"] is not None
assert nwGUI.treeView.deleteItem()
assert nwGUI.treeView.setSelectedHandle(newHandle)
assert nwGUI.treeView.deleteItem()
assert nwGUI.saveProject()
# Check the files
refFile = path.join(nwTempGUI, "nwProject.nwx")
assert cmpFiles(refFile, path.join(nwRef, "gui", "1_nwProject.nwx"), [2])