Merge branch 'master' into release_0.7
@@ -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.
|
||||
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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"
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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("-")
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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"),
|
||||
|
||||
@@ -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})"
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -4,6 +4,8 @@ theme = default
|
||||
syntax = default_light
|
||||
icons = typicons_grey_light
|
||||
guidark = False
|
||||
guifont =
|
||||
guifontsize = 11
|
||||
|
||||
[Sizes]
|
||||
geometry = 1100, 650
|
||||
|
||||
@@ -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])
|
||||
|
||||