Merge pull request #306 from vkbo/tweaks

Minor Tweaks and Fixes
This commit is contained in:
Veronica K. Berglyd Olsen
2020-06-11 18:11:27 +02:00
committed by GitHub
25 changed files with 719 additions and 452 deletions
+3 -1
View File
@@ -216,7 +216,9 @@ def main(sysArgs=None):
logger.addHandler(cHandle) logger.addHandler(cHandle)
logger.setLevel(debugLevel) logger.setLevel(debugLevel)
logger.info("This is %s %s" % (__package__, __version__)) logger.info("Starting %s" % __package__)
logger.info("Version: %s (%s)" % (__version__, __hexversion__))
logger.info("Last Release: %s" % __date__)
# Check Packages and Versions # Check Packages and Versions
errorData = [] errorData = []
+6 -6
View File
@@ -5,13 +5,13 @@
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"
id="svg2608" id="svg1321"
viewBox="0 0 24 24" viewBox="0 0 24 24"
height="24" height="24"
width="24" width="24"
version="1.2"> version="1.2">
<metadata <metadata
id="metadata2614"> id="metadata1327">
<rdf:RDF> <rdf:RDF>
<cc:Work <cc:Work
rdf:about=""> rdf:about="">
@@ -23,9 +23,9 @@
</rdf:RDF> </rdf:RDF>
</metadata> </metadata>
<defs <defs
id="defs2612" /> id="defs1325" />
<path <path
style="stroke-width:1.05081;fill:#aeaeae;fill-opacity:1" style="stroke-width:1.25;fill:#aeaeae;fill-opacity:1"
id="path2606" id="path1319"
d="M 16.203226,2 H 7.796774 C 6.05874,2 4.6443545,3.4143855 4.6443545,5.1524195 V 19.86371 c 0,0.540115 0.1092839,0.994063 0.3236484,1.350287 0.5926549,0.982504 1.9072138,1.059213 2.9559187,0.0084 L 11.25708,17.889239 c 0.394052,-0.393002 1.091787,-0.393002 1.485841,0 l 3.333158,3.333158 C 16.592024,21.738349 17.128987,22 17.673304,22 c 0.837492,0 1.682342,-0.660957 1.682342,-2.13629 V 5.1524195 C 19.355646,3.4143855 17.941259,2 16.203226,2 Z M 7.796774,4.101613 h 8.406452 c 0.578994,0 1.050806,0.4718121 1.050806,1.0508065 V 15.560658 l -2.575527,-2.361162 c -1.477434,-1.35449 -3.880628,-1.353439 -5.3580615,0 l -2.574476,2.361162 V 5.1524195 c 0,-0.5789944 0.4718121,-1.0508065 1.0508065,-1.0508065 z m 6.431987,12.301792 C 13.635055,15.809699 12.843798,15.482898 12,15.482898 c -0.843797,0 -1.635054,0.327852 -2.2287605,0.920507 l -3.025272,3.025272 v -2.442075 l 3.2848215,-3.011611 c 1.085483,-0.995114 2.851889,-0.995114 3.937372,0 l 3.285871,3.011611 v 2.442075 z" /> d="M 12,2 C 6.48625,2 2,6.48625 2,12 c 0,5.51375 4.48625,10 10,10 2.02,0 3.965,-0.59875 5.62375,-1.73 0.57,-0.39 0.7175,-1.1675 0.32875,-1.7375 -0.38875,-0.57125 -1.165,-0.715 -1.7375,-0.32875 C 14.9725,19.0525 13.515,19.5 12,19.5 7.86375,19.5 4.5,16.13625 4.5,12 4.5,7.86375 7.86375,4.5 12,4.5 c 4.13625,0 7.5,3.36375 7.5,7.5 v 0.625 c 0,0.69 -0.56,1.25 -1.25,1.25 -0.69,0 -1.25,-0.56 -1.25,-1.25 v -3.75 c 0,-0.69125 -0.55875,-1.25 -1.25,-1.25 -0.55125,0 -1.00625,0.3625 -1.1725,0.86 C 13.8525,7.95125 12.96625,7.625 12,7.625 9.5875,7.625 7.625,9.5875 7.625,12 c 0,2.4125 1.9625,4.375 4.375,4.375 1.30625,0 2.46875,-0.5875 3.27,-1.49875 0.685,0.90375 1.76,1.49875 2.98,1.49875 2.0675,0 3.75,-1.6825 3.75,-3.75 V 12 C 22,6.48625 17.51375,2 12,2 Z m 0,11.875 c -1.03375,0 -1.875,-0.84125 -1.875,-1.875 0,-1.03375 0.84125,-1.875 1.875,-1.875 1.03375,0 1.875,0.84125 1.875,1.875 0,1.03375 -0.84125,1.875 -1.875,1.875 z" />
</svg> </svg>

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

+9 -9
View File
@@ -5,13 +5,13 @@
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"
version="1.2" id="svg1321"
width="24"
height="24"
viewBox="0 0 24 24" viewBox="0 0 24 24"
id="svg2608"> height="24"
width="24"
version="1.2">
<metadata <metadata
id="metadata2614"> id="metadata1327">
<rdf:RDF> <rdf:RDF>
<cc:Work <cc:Work
rdf:about=""> rdf:about="">
@@ -23,9 +23,9 @@
</rdf:RDF> </rdf:RDF>
</metadata> </metadata>
<defs <defs
id="defs2612" /> id="defs1325" />
<path <path
d="M 16.203226,2 H 7.796774 C 6.05874,2 4.6443545,3.4143855 4.6443545,5.1524195 V 19.86371 c 0,0.540115 0.1092839,0.994063 0.3236484,1.350287 0.5926549,0.982504 1.9072138,1.059213 2.9559187,0.0084 L 11.25708,17.889239 c 0.394052,-0.393002 1.091787,-0.393002 1.485841,0 l 3.333158,3.333158 C 16.592024,21.738349 17.128987,22 17.673304,22 c 0.837492,0 1.682342,-0.660957 1.682342,-2.13629 V 5.1524195 C 19.355646,3.4143855 17.941259,2 16.203226,2 Z M 7.796774,4.101613 h 8.406452 c 0.578994,0 1.050806,0.4718121 1.050806,1.0508065 V 15.560658 l -2.575527,-2.361162 c -1.477434,-1.35449 -3.880628,-1.353439 -5.3580615,0 l -2.574476,2.361162 V 5.1524195 c 0,-0.5789944 0.4718121,-1.0508065 1.0508065,-1.0508065 z m 6.431987,12.301792 C 13.635055,15.809699 12.843798,15.482898 12,15.482898 c -0.843797,0 -1.635054,0.327852 -2.2287605,0.920507 l -3.025272,3.025272 v -2.442075 l 3.2848215,-3.011611 c 1.085483,-0.995114 2.851889,-0.995114 3.937372,0 l 3.285871,3.011611 v 2.442075 z" style="stroke-width:1.25;fill:#000000;fill-opacity:0.78039217"
id="path2606" id="path1319"
style="stroke-width:1.05081;fill:#000000;fill-opacity:0.78039217" /> d="M 12,2 C 6.48625,2 2,6.48625 2,12 c 0,5.51375 4.48625,10 10,10 2.02,0 3.965,-0.59875 5.62375,-1.73 0.57,-0.39 0.7175,-1.1675 0.32875,-1.7375 -0.38875,-0.57125 -1.165,-0.715 -1.7375,-0.32875 C 14.9725,19.0525 13.515,19.5 12,19.5 7.86375,19.5 4.5,16.13625 4.5,12 4.5,7.86375 7.86375,4.5 12,4.5 c 4.13625,0 7.5,3.36375 7.5,7.5 v 0.625 c 0,0.69 -0.56,1.25 -1.25,1.25 -0.69,0 -1.25,-0.56 -1.25,-1.25 v -3.75 c 0,-0.69125 -0.55875,-1.25 -1.25,-1.25 -0.55125,0 -1.00625,0.3625 -1.1725,0.86 C 13.8525,7.95125 12.96625,7.625 12,7.625 9.5875,7.625 7.625,9.5875 7.625,12 c 0,2.4125 1.9625,4.375 4.375,4.375 1.30625,0 2.46875,-0.5875 3.27,-1.49875 0.685,0.90375 1.76,1.49875 2.98,1.49875 2.0675,0 3.75,-1.6825 3.75,-3.75 V 12 C 22,6.48625 17.51375,2 12,2 Z m 0,11.875 c -1.03375,0 -1.875,-0.84125 -1.875,-1.875 0,-1.03375 0.84125,-1.875 1.875,-1.875 1.03375,0 1.875,0.84125 1.875,1.875 0,1.03375 -0.84125,1.875 -1.875,1.875 z" />
</svg> </svg>

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

@@ -0,0 +1,31 @@
<?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"
id="svg1321"
viewBox="0 0 24 24"
height="24"
width="24"
version="1.2">
<metadata
id="metadata1327">
<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="defs1325" />
<path
style="stroke-width:1.25;fill:#6699cc;fill-opacity:1"
id="path1319"
d="M 12,2 C 6.48625,2 2,6.48625 2,12 c 0,5.51375 4.48625,10 10,10 2.02,0 3.965,-0.59875 5.62375,-1.73 0.57,-0.39 0.7175,-1.1675 0.32875,-1.7375 -0.38875,-0.57125 -1.165,-0.715 -1.7375,-0.32875 C 14.9725,19.0525 13.515,19.5 12,19.5 7.86375,19.5 4.5,16.13625 4.5,12 4.5,7.86375 7.86375,4.5 12,4.5 c 4.13625,0 7.5,3.36375 7.5,7.5 v 0.625 c 0,0.69 -0.56,1.25 -1.25,1.25 -0.69,0 -1.25,-0.56 -1.25,-1.25 v -3.75 c 0,-0.69125 -0.55875,-1.25 -1.25,-1.25 -0.55125,0 -1.00625,0.3625 -1.1725,0.86 C 13.8525,7.95125 12.96625,7.625 12,7.625 9.5875,7.625 7.625,9.5875 7.625,12 c 0,2.4125 1.9625,4.375 4.375,4.375 1.30625,0 2.46875,-0.5875 3.27,-1.49875 0.685,0.90375 1.76,1.49875 2.98,1.49875 2.0675,0 3.75,-1.6825 3.75,-3.75 V 12 C 22,6.48625 17.51375,2 12,2 Z m 0,11.875 c -1.03375,0 -1.875,-0.84125 -1.875,-1.875 0,-1.03375 0.84125,-1.875 1.875,-1.875 1.03375,0 1.875,0.84125 1.875,1.875 0,1.03375 -0.84125,1.875 -1.875,1.875 z" />
</svg>

After

Width:  |  Height:  |  Size: 1.7 KiB

@@ -49,6 +49,6 @@ edit = pencil.svg
check = tick.svg check = tick.svg
cross = times.svg cross = times.svg
hash = hash.svg hash = hash.svg
reference = bookmark.svg reference = at.svg
sticky-on = pin.svg sticky-on = pin.svg
sticky-off = pin-outline.svg sticky-off = pin-outline.svg
@@ -0,0 +1,31 @@
<?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"
id="svg1321"
viewBox="0 0 24 24"
height="24"
width="24"
version="1.2">
<metadata
id="metadata1327">
<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="defs1325" />
<path
style="stroke-width:1.25;fill:#4271ae;fill-opacity:1"
id="path1319"
d="M 12,2 C 6.48625,2 2,6.48625 2,12 c 0,5.51375 4.48625,10 10,10 2.02,0 3.965,-0.59875 5.62375,-1.73 0.57,-0.39 0.7175,-1.1675 0.32875,-1.7375 -0.38875,-0.57125 -1.165,-0.715 -1.7375,-0.32875 C 14.9725,19.0525 13.515,19.5 12,19.5 7.86375,19.5 4.5,16.13625 4.5,12 4.5,7.86375 7.86375,4.5 12,4.5 c 4.13625,0 7.5,3.36375 7.5,7.5 v 0.625 c 0,0.69 -0.56,1.25 -1.25,1.25 -0.69,0 -1.25,-0.56 -1.25,-1.25 v -3.75 c 0,-0.69125 -0.55875,-1.25 -1.25,-1.25 -0.55125,0 -1.00625,0.3625 -1.1725,0.86 C 13.8525,7.95125 12.96625,7.625 12,7.625 9.5875,7.625 7.625,9.5875 7.625,12 c 0,2.4125 1.9625,4.375 4.375,4.375 1.30625,0 2.46875,-0.5875 3.27,-1.49875 0.685,0.90375 1.76,1.49875 2.98,1.49875 2.0675,0 3.75,-1.6825 3.75,-3.75 V 12 C 22,6.48625 17.51375,2 12,2 Z m 0,11.875 c -1.03375,0 -1.875,-0.84125 -1.875,-1.875 0,-1.03375 0.84125,-1.875 1.875,-1.875 1.03375,0 1.875,0.84125 1.875,1.875 0,1.03375 -0.84125,1.875 -1.875,1.875 z" />
</svg>

After

Width:  |  Height:  |  Size: 1.7 KiB

@@ -49,6 +49,6 @@ edit = pencil.svg
check = tick.svg check = tick.svg
cross = times.svg cross = times.svg
hash = hash.svg hash = hash.svg
reference = bookmark.svg reference = at.svg
sticky-on = pin.svg sticky-on = pin.svg
sticky-off = pin-outline.svg sticky-off = pin-outline.svg
+31
View File
@@ -0,0 +1,31 @@
<?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"
id="svg1321"
viewBox="0 0 24 24"
height="24"
width="24"
version="1.2">
<metadata
id="metadata1327">
<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="defs1325" />
<path
style="stroke-width:1.25;fill:#aeaeae;fill-opacity:1"
id="path1319"
d="M 12,2 C 6.48625,2 2,6.48625 2,12 c 0,5.51375 4.48625,10 10,10 2.02,0 3.965,-0.59875 5.62375,-1.73 0.57,-0.39 0.7175,-1.1675 0.32875,-1.7375 -0.38875,-0.57125 -1.165,-0.715 -1.7375,-0.32875 C 14.9725,19.0525 13.515,19.5 12,19.5 7.86375,19.5 4.5,16.13625 4.5,12 4.5,7.86375 7.86375,4.5 12,4.5 c 4.13625,0 7.5,3.36375 7.5,7.5 v 0.625 c 0,0.69 -0.56,1.25 -1.25,1.25 -0.69,0 -1.25,-0.56 -1.25,-1.25 v -3.75 c 0,-0.69125 -0.55875,-1.25 -1.25,-1.25 -0.55125,0 -1.00625,0.3625 -1.1725,0.86 C 13.8525,7.95125 12.96625,7.625 12,7.625 9.5875,7.625 7.625,9.5875 7.625,12 c 0,2.4125 1.9625,4.375 4.375,4.375 1.30625,0 2.46875,-0.5875 3.27,-1.49875 0.685,0.90375 1.76,1.49875 2.98,1.49875 2.0675,0 3.75,-1.6825 3.75,-3.75 V 12 C 22,6.48625 17.51375,2 12,2 Z m 0,11.875 c -1.03375,0 -1.875,-0.84125 -1.875,-1.875 0,-1.03375 0.84125,-1.875 1.875,-1.875 1.03375,0 1.875,0.84125 1.875,1.875 0,1.03375 -0.84125,1.875 -1.875,1.875 z" />
</svg>

After

Width:  |  Height:  |  Size: 1.7 KiB

@@ -49,6 +49,6 @@ edit = pencil.svg
check = tick.svg check = tick.svg
cross = times.svg cross = times.svg
hash = hash.svg hash = hash.svg
reference = bookmark.svg reference = at.svg
sticky-on = pin.svg sticky-on = pin.svg
sticky-off = pin-outline.svg sticky-off = pin-outline.svg
@@ -0,0 +1,31 @@
<?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"
id="svg1321"
viewBox="0 0 24 24"
height="24"
width="24"
version="1.2">
<metadata
id="metadata1327">
<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="defs1325" />
<path
style="stroke-width:1.25;fill:#000000;fill-opacity:0.78039217"
id="path1319"
d="M 12,2 C 6.48625,2 2,6.48625 2,12 c 0,5.51375 4.48625,10 10,10 2.02,0 3.965,-0.59875 5.62375,-1.73 0.57,-0.39 0.7175,-1.1675 0.32875,-1.7375 -0.38875,-0.57125 -1.165,-0.715 -1.7375,-0.32875 C 14.9725,19.0525 13.515,19.5 12,19.5 7.86375,19.5 4.5,16.13625 4.5,12 4.5,7.86375 7.86375,4.5 12,4.5 c 4.13625,0 7.5,3.36375 7.5,7.5 v 0.625 c 0,0.69 -0.56,1.25 -1.25,1.25 -0.69,0 -1.25,-0.56 -1.25,-1.25 v -3.75 c 0,-0.69125 -0.55875,-1.25 -1.25,-1.25 -0.55125,0 -1.00625,0.3625 -1.1725,0.86 C 13.8525,7.95125 12.96625,7.625 12,7.625 9.5875,7.625 7.625,9.5875 7.625,12 c 0,2.4125 1.9625,4.375 4.375,4.375 1.30625,0 2.46875,-0.5875 3.27,-1.49875 0.685,0.90375 1.76,1.49875 2.98,1.49875 2.0675,0 3.75,-1.6825 3.75,-3.75 V 12 C 22,6.48625 17.51375,2 12,2 Z m 0,11.875 c -1.03375,0 -1.875,-0.84125 -1.875,-1.875 0,-1.03375 0.84125,-1.875 1.875,-1.875 1.03375,0 1.875,0.84125 1.875,1.875 0,1.03375 -0.84125,1.875 -1.875,1.875 z" />
</svg>

After

Width:  |  Height:  |  Size: 1.7 KiB

@@ -49,6 +49,6 @@ edit = pencil.svg
check = tick.svg check = tick.svg
cross = times.svg cross = times.svg
hash = hash.svg hash = hash.svg
reference = bookmark.svg reference = at.svg
sticky-on = pin.svg sticky-on = pin.svg
sticky-off = pin-outline.svg sticky-off = pin-outline.svg
+3
View File
@@ -222,6 +222,7 @@ class Config:
"""Initialise the config class. The manual setting of confPath """Initialise the config class. The manual setting of confPath
and dataPath is mainly intended for the test suite. and dataPath is mainly intended for the test suite.
""" """
logger.debug("Initialising Config ...")
if confPath is None: if confPath is None:
confRoot = QStandardPaths.writableLocation(QStandardPaths.ConfigLocation) confRoot = QStandardPaths.writableLocation(QStandardPaths.ConfigLocation)
self.confPath = path.join(path.abspath(confRoot), self.appHandle) self.confPath = path.join(path.abspath(confRoot), self.appHandle)
@@ -304,6 +305,8 @@ class Config:
if self.spellLanguage is None: if self.spellLanguage is None:
self.spellLanguage = "en" self.spellLanguage = "en"
logger.debug("Config initialisation complete")
return True return True
def loadConfig(self): def loadConfig(self):
+1
View File
@@ -1041,6 +1041,7 @@ class NWProject():
return return
# Then check the files in the data folder # Then check the files in the data folder
logger.debug("Checking files in project content folder")
orphanFiles = [] orphanFiles = []
for fileItem in listdir(self.projContent): for fileItem in listdir(self.projContent):
if not fileItem.endswith(".nwd"): if not fileItem.endswith(".nwd"):
+2 -2
View File
@@ -115,12 +115,12 @@ class NWSpellCheck():
if not path.isfile(projectDict): if not path.isfile(projectDict):
return return
try: try:
with open(projectDict,mode="r",encoding="utf-8") as wordsFile: logger.debug("Loading project word list")
with open(projectDict, mode="r", encoding="utf-8") as wordsFile:
for theLine in wordsFile: for theLine in wordsFile:
theLine = theLine.strip() theLine = theLine.strip()
if len(theLine) > 0 and theLine not in self.PROJW: if len(theLine) > 0 and theLine not in self.PROJW:
self.PROJW.append(theLine) self.PROJW.append(theLine)
logger.debug("Project word list")
logger.debug("Project word list contains %d words" % len(self.PROJW)) logger.debug("Project word list contains %d words" % len(self.PROJW))
except Exception as e: except Exception as e:
logger.error("Failed to load project word list") logger.error("Failed to load project word list")
+3 -4
View File
@@ -2,11 +2,11 @@
from nw.gui.about import GuiAbout from nw.gui.about import GuiAbout
from nw.gui.build import GuiBuildNovel from nw.gui.build import GuiBuildNovel
from nw.gui.docbars import GuiDocTitleBar, GuiSearchBar, GuiDocViewDetails from nw.gui.docbars import GuiSearchBar
from nw.gui.doceditor import GuiDocEditor from nw.gui.doceditor import GuiDocEditor
from nw.gui.docmerge import GuiDocMerge from nw.gui.docmerge import GuiDocMerge
from nw.gui.docsplit import GuiDocSplit from nw.gui.docsplit import GuiDocSplit
from nw.gui.docviewer import GuiDocViewer from nw.gui.docviewer import GuiDocViewer, GuiDocViewDetails
from nw.gui.itemdetails import GuiItemDetails from nw.gui.itemdetails import GuiItemDetails
from nw.gui.itemeditor import GuiItemEditor from nw.gui.itemeditor import GuiItemEditor
from nw.gui.mainmenu import GuiMainMenu from nw.gui.mainmenu import GuiMainMenu
@@ -23,13 +23,12 @@ from nw.gui.theme import GuiIcons, GuiTheme
__all__ = [ __all__ = [
"GuiAbout", "GuiAbout",
"GuiBuildNovel", "GuiBuildNovel",
"GuiDocTitleBar",
"GuiSearchBar", "GuiSearchBar",
"GuiDocViewDetails",
"GuiDocEditor", "GuiDocEditor",
"GuiDocMerge", "GuiDocMerge",
"GuiDocSplit", "GuiDocSplit",
"GuiDocViewer", "GuiDocViewer",
"GuiDocViewDetails",
"GuiItemDetails", "GuiItemDetails",
"GuiItemEditor", "GuiItemEditor",
"GuiMainMenu", "GuiMainMenu",
+1 -1
View File
@@ -45,7 +45,7 @@ from nw.constants import nwUnicode
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
# =============================================================================================== # # =============================================================================================== #
# Config FOrm Layout # Config Form Layout
# =============================================================================================== # # =============================================================================================== #
class QConfigLayout(QGridLayout): class QConfigLayout(QGridLayout):
-382
View File
@@ -7,9 +7,6 @@
File History: File History:
Created: 2019-09-29 [0.2.1] GuiSearchBar Created: 2019-09-29 [0.2.1] GuiSearchBar
Created: 2019-10-31 [0.3.2] GuiDocViewDetails
Created: 2020-04-25 [0.4.5] GuiDocTitleBar
Created: 2020-06-09 [0.8.0] GuiDocViewFooter
This file is a part of novelWriter This file is a part of novelWriter
Copyright 2020, Veronica Berglyd Olsen Copyright 2020, Veronica Berglyd Olsen
@@ -169,382 +166,3 @@ class GuiSearchBar(QWidget):
return True return True
# END Class GuiSearchBar # END Class GuiSearchBar
class GuiDocTitleBar(QWidget):
def __init__(self, theParent, isEditor):
QWidget.__init__(self, theParent)
logger.debug("Initialising GuiDocTitleBar ...")
self.mainConf = nw.CONFIG
self.theParent = theParent
self.theProject = theParent.theProject
self.theTheme = theParent.theTheme
self.theHandle = None
self.isEditor = isEditor
# Make a QPalette that matches the Syntax Theme
self.thePalette = QPalette()
self.thePalette.setColor(QPalette.Window, QColor(*self.theTheme.colBack))
self.thePalette.setColor(QPalette.Text, QColor(*self.theTheme.colText))
fPx = int(0.9*self.theTheme.fontPixelSize)
hSp = self.mainConf.pxInt(6)
self.buttonSize = fPx + hSp
# Main Widget Settings
self.setContentsMargins(2*self.buttonSize, 0, 0, 0)
self.setAutoFillBackground(True)
self.setPalette(self.thePalette)
# Title Label
self.theTitle = QLabel()
self.theTitle.setText("")
self.theTitle.setIndent(0)
self.theTitle.setMargin(0)
self.theTitle.setContentsMargins(0, 0, 0, 0)
self.theTitle.setAutoFillBackground(True)
self.theTitle.setAlignment(Qt.AlignHCenter | Qt.AlignTop)
self.theTitle.setFixedHeight(fPx)
self.theTitle.setFrameShape(QFrame.NoFrame)
self.theTitle.setLineWidth(0)
self.theTitle.setPalette(self.thePalette)
lblFont = self.theTitle.font()
lblFont.setPointSizeF(0.9*self.theTheme.fontPointSize)
self.theTitle.setFont(lblFont)
buttonStyle = (
"QToolButton {{border: none; background: transparent;}} "
"QToolButton:hover {{border: none; background: rgba({0},{1},{2},0.2);}}"
).format(*self.theTheme.colText)
# Buttons
self.closeButton = QToolButton(self)
self.closeButton.setIcon(self.theTheme.getIcon("close"))
self.closeButton.setContentsMargins(0, 0, 0, 0)
self.closeButton.setIconSize(QSize(fPx, fPx))
self.closeButton.setFixedSize(fPx, fPx)
self.closeButton.setStyleSheet(buttonStyle)
self.closeButton.setToolButtonStyle(Qt.ToolButtonIconOnly)
self.closeButton.setVisible(False)
self.closeButton.clicked.connect(self._closeDocument)
if self.isEditor:
self.minmaxButton = QToolButton(self)
self.minmaxButton.setIcon(self.theTheme.getIcon("maximise"))
self.minmaxButton.setContentsMargins(0, 0, 0, 0)
self.minmaxButton.setIconSize(QSize(fPx, fPx))
self.minmaxButton.setFixedSize(fPx, fPx)
self.minmaxButton.setStyleSheet(buttonStyle)
self.minmaxButton.setToolButtonStyle(Qt.ToolButtonIconOnly)
self.minmaxButton.setVisible(False)
self.minmaxButton.clicked.connect(self._minmaxDocument)
else:
self.refreshButton = QToolButton(self)
self.refreshButton.setIcon(self.theTheme.getIcon("refresh"))
self.refreshButton.setContentsMargins(0, 0, 0, 0)
self.refreshButton.setIconSize(QSize(fPx, fPx))
self.refreshButton.setFixedSize(fPx, fPx)
self.refreshButton.setStyleSheet(buttonStyle)
self.refreshButton.setToolButtonStyle(Qt.ToolButtonIconOnly)
self.refreshButton.setVisible(False)
self.refreshButton.clicked.connect(self._refreshDocument)
# Assemble Layout
self.outerBox = QHBoxLayout()
self.outerBox.setSpacing(hSp)
self.outerBox.addWidget(self.theTitle, 1)
if self.isEditor:
self.outerBox.addWidget(self.minmaxButton, 0)
else:
self.outerBox.addWidget(self.refreshButton, 0)
self.outerBox.addWidget(self.closeButton, 0)
self.setLayout(self.outerBox)
logger.debug("GuiDocTitleBar initialisation complete")
return
##
# Setters
##
def setTitleFromHandle(self, tHandle):
"""Sets the document title from the handle, or alternatively,
set the whole document path.
"""
self.theTitle.setText("")
self.theHandle = tHandle
if tHandle is None:
self.closeButton.setVisible(False)
if self.isEditor:
self.minmaxButton.setVisible(False)
else:
self.refreshButton.setVisible(False)
return False
if self.mainConf.showFullPath:
tTitle = []
tTree = self.theProject.projTree.getItemPath(tHandle)
for aHandle in reversed(tTree):
nwItem = self.theProject.projTree[aHandle]
if nwItem is not None:
tTitle.append(nwItem.itemName)
sSep = " %s " % nwUnicode.U_RSAQUO
self.theTitle.setText(sSep.join(tTitle))
else:
nwItem = self.theProject.projTree[tHandle]
if nwItem is None:
return False
self.theTitle.setText(nwItem.itemName)
self.closeButton.setVisible(True)
if self.isEditor:
self.minmaxButton.setVisible(True)
else:
self.refreshButton.setVisible(True)
return True
##
# Slots
##
def _closeDocument(self):
"""Trigger the close editor/viewer on the main window.
"""
if self.isEditor:
self.theParent.theParent.closeDocEditor()
else:
self.theParent.theParent.closeDocViewer()
return
def _minmaxDocument(self):
"""Switch on or off zen mode.
"""
self.theParent.theParent.toggleZenMode()
if self.theParent.theParent.isZenMode:
self.minmaxButton.setIcon(self.theTheme.getIcon("minimise"))
self.setContentsMargins(self.buttonSize, 0, 0, 0)
self.closeButton.setVisible(False)
else:
self.minmaxButton.setIcon(self.theTheme.getIcon("maximise"))
self.setContentsMargins(2*self.buttonSize, 0, 0, 0)
self.closeButton.setVisible(True)
return
def _refreshDocument(self):
"""Reload the content of the document.
"""
self.theParent.reloadText()
return
##
# Events
##
def mousePressEvent(self, theEvent):
"""Capture a click on the title and ensure that the item is
selected in the project tree.
"""
self.theParent.setSelectedHandle(self.theHandle)
return
# END Class GuiDocTitleBar
class GuiDocViewFooter(QWidget):
def __init__(self, theParent):
QWidget.__init__(self, theParent)
logger.debug("Initialising GuiDocViewFooter ...")
self.mainConf = nw.CONFIG
self.theParent = theParent
self.theTheme = theParent.theTheme
self.optState = theParent.theProject.optState
self.viewMeta = theParent.theParent.viewMeta
self.theHandle = None
# Make a QPalette that matches the Syntax Theme
self.thePalette = QPalette()
self.thePalette.setColor(QPalette.Window, QColor(*self.theTheme.colBack))
self.thePalette.setColor(QPalette.Text, QColor(*self.theTheme.colText))
fPx = int(0.9*self.theTheme.fontPixelSize)
hSp = self.mainConf.pxInt(6)
# Main Widget Settings
self.setContentsMargins(0, 0, 0, 0)
self.setAutoFillBackground(True)
self.setPalette(self.thePalette)
buttonStyle = (
"QToolButton {{border: none; background: transparent;}} "
"QToolButton:hover {{border: none; background: rgba({0},{1},{2},0.2);}}"
).format(*self.theTheme.colText)
# Show/Hide Details
self.showHide = QToolButton(self)
self.showHide.setToolButtonStyle(Qt.ToolButtonIconOnly)
self.showHide.setStyleSheet(buttonStyle)
self.showHide.setIcon(self.theTheme.getIcon("reference"))
self.showHide.setIconSize(QSize(fPx, fPx))
self.showHide.setFixedSize(QSize(fPx, fPx))
self.showHide.clicked.connect(self._doShowHide)
# Sticky Button
stickyOn = self.theTheme.getPixmap("sticky-on", (fPx, fPx))
stickyOff = self.theTheme.getPixmap("sticky-off", (fPx, fPx))
stickyIcon = QIcon()
stickyIcon.addPixmap(stickyOn, QIcon.Normal, QIcon.On)
stickyIcon.addPixmap(stickyOff, QIcon.Normal, QIcon.Off)
self.stickyRefs = QToolButton(self)
self.stickyRefs.setCheckable(True)
self.stickyRefs.setToolButtonStyle(Qt.ToolButtonIconOnly)
self.stickyRefs.setStyleSheet(buttonStyle)
self.stickyRefs.setIcon(stickyIcon)
self.stickyRefs.setIconSize(QSize(fPx, fPx))
self.stickyRefs.setFixedSize(QSize(fPx, fPx))
self.stickyRefs.toggled.connect(self._doToggleSticky)
# Labels
self.lblRefs = QLabel("References")
self.lblRefs.setBuddy(self.showHide)
self.lblRefs.setIndent(0)
self.lblRefs.setMargin(0)
self.lblRefs.setContentsMargins(0, 0, 0, 0)
self.lblRefs.setAutoFillBackground(True)
self.lblRefs.setFixedHeight(fPx)
self.lblRefs.setAlignment(Qt.AlignLeft | Qt.AlignTop)
self.lblRefs.setPalette(self.thePalette)
self.lblSticky = QLabel("Sticky")
self.lblSticky.setBuddy(self.stickyRefs)
self.lblSticky.setIndent(0)
self.lblSticky.setMargin(0)
self.lblSticky.setContentsMargins(0, 0, 0, 0)
self.lblSticky.setAutoFillBackground(True)
self.lblSticky.setFixedHeight(fPx)
self.lblSticky.setAlignment(Qt.AlignLeft | Qt.AlignTop)
self.lblSticky.setPalette(self.thePalette)
lblFont = self.font()
lblFont.setPointSizeF(0.9*self.theTheme.fontPointSize)
self.lblRefs.setFont(lblFont)
self.lblSticky.setFont(lblFont)
# Assemble Layout
self.outerBox = QHBoxLayout()
self.outerBox.setSpacing(hSp)
self.outerBox.addWidget(self.showHide, 0)
self.outerBox.addWidget(self.lblRefs, 0)
self.outerBox.addWidget(self.stickyRefs, 0)
self.outerBox.addWidget(self.lblSticky, 0)
self.outerBox.addStretch(1)
self.setLayout(self.outerBox)
logger.debug("GuiDocViewFooter initialisation complete")
return
##
# Slots
##
def _doShowHide(self):
"""Toggle the expand/collapse of the panel.
"""
isVisible = self.viewMeta.isVisible()
self.viewMeta.setVisible(not isVisible)
return
def _doToggleSticky(self, theState):
"""Toggle the sticky flag for the reference panel.
"""
logger.verbose("Reference sticky is %s" % str(theState))
self.theParent.stickyRef = theState
if not theState and self.theParent.theHandle is not None:
self.viewMeta.refreshReferences(self.theParent.theHandle)
return
# END Class GuiDocViewFooter
class GuiDocViewDetails(QScrollArea):
def __init__(self, theParent):
QScrollArea.__init__(self, theParent)
logger.debug("Initialising DocViewDetails ...")
self.mainConf = nw.CONFIG
self.theParent = theParent
self.theProject = theParent.theProject
self.theTheme = theParent.theTheme
self.currHandle = None
self.refList = QLabel("None")
self.refList.setWordWrap(True)
self.refList.setAlignment(Qt.AlignTop)
self.refList.setScaledContents(True)
self.refList.linkActivated.connect(self._linkClicked)
hCol = self.palette().highlight().color()
self.linkStyle = "style='color: rgb({0},{1},{2})'".format(
*self.theTheme.colLink
)
# Assemble
self.outerWidget = QWidget()
self.outerBox = QHBoxLayout()
self.outerBox.addWidget(self.refList, 1)
self.outerWidget.setLayout(self.outerBox)
self.setWidget(self.outerWidget)
self.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded)
self.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded)
self.setWidgetResizable(True)
self.setMinimumHeight(self.mainConf.pxInt(50))
logger.debug("DocViewDetails initialisation complete")
return
def refreshReferences(self, tHandle):
"""Update the current list of document references from the
project index.
"""
self.currHandle = tHandle
if self.theParent.docViewer.stickyRef:
return
theRefs = self.theParent.theIndex.getBackReferenceList(tHandle)
theList = []
for tHandle in theRefs:
tItem = self.theProject.projTree[tHandle]
if tItem is not None:
theList.append("<a href='#head_%s:%s' %s>%s</a>" % (
tHandle, theRefs[tHandle], self.linkStyle, tItem.itemName
))
self.refList.setText(", ".join(theList))
return
##
# Internal Functions
##
def _linkClicked(self, theLink):
"""Capture the link-click and forward it to the document viewer
class for handling.
"""
logger.verbose("Clicked link: '%s'" % theLink)
if len(theLink) == 27:
tHandle = theLink[6:19]
self.theParent.viewDocument(tHandle, theLink)
return
# END Class GuiDocViewDetails
+168 -17
View File
@@ -8,6 +8,7 @@
File History: File History:
Created: 2018-09-29 [0.0.1] GuiDocEditor Created: 2018-09-29 [0.0.1] GuiDocEditor
Created: 2019-04-22 [0.0.1] WordCounter Created: 2019-04-22 [0.0.1] WordCounter
Created: 2020-04-25 [0.4.5] GuiDocEditHeader
This file is a part of novelWriter This file is a part of novelWriter
Copyright 2020, Veronica Berglyd Olsen Copyright 2020, Veronica Berglyd Olsen
@@ -31,18 +32,18 @@ import nw
from time import time from time import time
from PyQt5.QtCore import Qt, QThread, QTimer, pyqtSlot from PyQt5.QtCore import Qt, QSize, QThread, QTimer, pyqtSlot
from PyQt5.QtWidgets import (
qApp, QTextEdit, QAction, QMenu, QShortcut, QMessageBox
)
from PyQt5.QtGui import ( from PyQt5.QtGui import (
QTextCursor, QTextOption, QKeySequence, QFont, QColor, QPalette, QTextCursor, QTextOption, QKeySequence, QFont, QColor, QPalette,
QTextDocument, QCursor QTextDocument, QCursor
) )
from PyQt5.QtWidgets import (
qApp, QTextEdit, QAction, QMenu, QShortcut, QMessageBox, QWidget, QLabel,
QToolButton, QHBoxLayout
)
from nw.core import NWDoc from nw.core import NWDoc
from nw.gui.dochighlight import GuiDocHighlighter from nw.gui.dochighlight import GuiDocHighlighter
from nw.gui.docbars import GuiDocTitleBar
from nw.core import NWSpellSimple, countWords from nw.core import NWSpellSimple, countWords
from nw.constants import nwUnicode, nwDocAction from nw.constants import nwUnicode, nwDocAction
@@ -85,9 +86,7 @@ class GuiDocEditor(QTextEdit):
self.qDocument.contentsChange.connect(self._docChange) self.qDocument.contentsChange.connect(self._docChange)
# Document Title # Document Title
self.docTitle = GuiDocTitleBar(self, isEditor=True) self.docHeader = GuiDocEditHeader(self)
self.docTitle.setGeometry(0, 0, self.docTitle.width(), self.docTitle.height())
self.setViewportMargins(0, self.docTitle.height(), 0, 0)
# Syntax # Syntax
self.hLight = GuiDocHighlighter(self.qDocument, self.theParent) self.hLight = GuiDocHighlighter(self.qDocument, self.theParent)
@@ -134,9 +133,6 @@ class GuiDocEditor(QTextEdit):
logger.debug("GuiDocEditor initialisation complete") logger.debug("GuiDocEditor initialisation complete")
# Connect Functions
self.setSelectedHandle = self.theParent.treeView.setSelectedHandle
return return
def clearEditor(self): def clearEditor(self):
@@ -158,7 +154,7 @@ class GuiDocEditor(QTextEdit):
self.hasSelection = False self.hasSelection = False
self.setDocumentChanged(False) self.setDocumentChanged(False)
self.docTitle.setTitleFromHandle(self.theHandle) self.docHeader.setTitleFromHandle(self.theHandle)
return True return True
@@ -270,7 +266,7 @@ class GuiDocEditor(QTextEdit):
self.theHandle = tHandle self.theHandle = tHandle
self.setReadOnly(False) self.setReadOnly(False)
self.docTitle.setTitleFromHandle(self.theHandle) self.docHeader.setTitleFromHandle(self.theHandle)
self.updateDocMargins() self.updateDocMargins()
self.hLight.spellCheck = spTemp self.hLight.spellCheck = spTemp
qApp.restoreOverrideCursor() qApp.restoreOverrideCursor()
@@ -333,11 +329,11 @@ class GuiDocEditor(QTextEdit):
else: else:
tM = cM tM = cM
tB = self.lineWidth() tB = self.frameWidth()
tW = self.width() - 2*tB - sW tW = self.width() - 2*tB - sW
tH = self.docTitle.height() tH = self.docHeader.height()
tT = cM - tH tT = cM - tH
self.docTitle.setGeometry(tB, tB, tW, tH) self.docHeader.setGeometry(tB, tB, tW, tH)
self.setViewportMargins(0, tH, 0, 0) self.setViewportMargins(0, tH, 0, 0)
docFormat = self.qDocument.rootFrame().frameFormat() docFormat = self.qDocument.rootFrame().frameFormat()
@@ -368,7 +364,7 @@ class GuiDocEditor(QTextEdit):
title bar needs updating, title bar needs updating,
""" """
if tHandle == self.theHandle: if tHandle == self.theHandle:
self.docTitle.setTitleFromHandle(self.theHandle) self.docHeader.setTitleFromHandle(self.theHandle)
self.updateDocMargins() self.updateDocMargins()
return return
@@ -1105,3 +1101,158 @@ class WordCounter(QThread):
return return
## END Class WordCounter ## END Class WordCounter
class GuiDocEditHeader(QWidget):
def __init__(self, docEditor):
QWidget.__init__(self, docEditor)
logger.debug("Initialising GuiDocEditHeader ...")
self.mainConf = nw.CONFIG
self.docEditor = docEditor
self.theParent = docEditor.theParent
self.theProject = docEditor.theProject
self.theTheme = docEditor.theTheme
self.theHandle = None
# Make a QPalette that matches the Syntax Theme
self.thePalette = QPalette()
self.thePalette.setColor(QPalette.Window, QColor(*self.theTheme.colBack))
self.thePalette.setColor(QPalette.Text, QColor(*self.theTheme.colText))
fPx = int(0.9*self.theTheme.fontPixelSize)
hSp = self.mainConf.pxInt(6)
self.buttonSize = fPx + hSp
# Main Widget Settings
self.setContentsMargins(2*self.buttonSize, 0, 0, 0)
self.setAutoFillBackground(True)
self.setPalette(self.thePalette)
# Title Label
self.theTitle = QLabel()
self.theTitle.setText("")
self.theTitle.setIndent(0)
self.theTitle.setMargin(0)
self.theTitle.setContentsMargins(0, 0, 0, 0)
self.theTitle.setAutoFillBackground(True)
self.theTitle.setAlignment(Qt.AlignHCenter | Qt.AlignTop)
self.theTitle.setFixedHeight(fPx)
self.theTitle.setPalette(self.thePalette)
lblFont = self.theTitle.font()
lblFont.setPointSizeF(0.9*self.theTheme.fontPointSize)
self.theTitle.setFont(lblFont)
buttonStyle = (
"QToolButton {{border: none; background: transparent;}} "
"QToolButton:hover {{border: none; background: rgba({0},{1},{2},0.2);}}"
).format(*self.theTheme.colText)
# Buttons
self.minmaxButton = QToolButton(self)
self.minmaxButton.setIcon(self.theTheme.getIcon("maximise"))
self.minmaxButton.setContentsMargins(0, 0, 0, 0)
self.minmaxButton.setIconSize(QSize(fPx, fPx))
self.minmaxButton.setFixedSize(fPx, fPx)
self.minmaxButton.setStyleSheet(buttonStyle)
self.minmaxButton.setToolButtonStyle(Qt.ToolButtonIconOnly)
self.minmaxButton.setVisible(False)
self.minmaxButton.clicked.connect(self._minmaxDocument)
self.closeButton = QToolButton(self)
self.closeButton.setIcon(self.theTheme.getIcon("close"))
self.closeButton.setContentsMargins(0, 0, 0, 0)
self.closeButton.setIconSize(QSize(fPx, fPx))
self.closeButton.setFixedSize(fPx, fPx)
self.closeButton.setStyleSheet(buttonStyle)
self.closeButton.setToolButtonStyle(Qt.ToolButtonIconOnly)
self.closeButton.setVisible(False)
self.closeButton.clicked.connect(self._closeDocument)
# Assemble Layout
self.outerBox = QHBoxLayout()
self.outerBox.setSpacing(hSp)
self.outerBox.addWidget(self.theTitle, 1)
self.outerBox.addWidget(self.minmaxButton, 0)
self.outerBox.addWidget(self.closeButton, 0)
self.setLayout(self.outerBox)
logger.debug("GuiDocEditHeader initialisation complete")
return
##
# Setters
##
def setTitleFromHandle(self, tHandle):
"""Sets the document title from the handle, or alternatively,
set the whole document path.
"""
self.theHandle = tHandle
if tHandle is None:
self.theTitle.setText("")
self.closeButton.setVisible(False)
self.minmaxButton.setVisible(False)
return True
if self.mainConf.showFullPath:
tTitle = []
tTree = self.theProject.projTree.getItemPath(tHandle)
for aHandle in reversed(tTree):
nwItem = self.theProject.projTree[aHandle]
if nwItem is not None:
tTitle.append(nwItem.itemName)
sSep = " %s " % nwUnicode.U_RSAQUO
self.theTitle.setText(sSep.join(tTitle))
else:
nwItem = self.theProject.projTree[tHandle]
if nwItem is None:
return False
self.theTitle.setText(nwItem.itemName)
self.closeButton.setVisible(True)
self.minmaxButton.setVisible(True)
return True
##
# Slots
##
def _closeDocument(self):
"""Trigger the close editor/viewer on the main window.
"""
self.theParent.closeDocEditor()
self.closeButton.setVisible(False)
self.minmaxButton.setVisible(False)
return
def _minmaxDocument(self):
"""Switch on or off zen mode.
"""
self.theParent.toggleZenMode()
if self.theParent.isZenMode:
self.minmaxButton.setIcon(self.theTheme.getIcon("minimise"))
self.setContentsMargins(self.buttonSize, 0, 0, 0)
self.closeButton.setVisible(False)
else:
self.minmaxButton.setIcon(self.theTheme.getIcon("maximise"))
self.setContentsMargins(2*self.buttonSize, 0, 0, 0)
self.closeButton.setVisible(True)
return
##
# Events
##
def mousePressEvent(self, theEvent):
"""Capture a click on the title and ensure that the item is
selected in the project tree.
"""
self.theParent.treeView.setSelectedHandle(self.theHandle)
return
# END Class GuiDocEditHeader
+2 -2
View File
@@ -42,7 +42,7 @@ class GuiDocHighlighter(QSyntaxHighlighter):
def __init__(self, theDoc, theParent): def __init__(self, theDoc, theParent):
QSyntaxHighlighter.__init__(self, theDoc) QSyntaxHighlighter.__init__(self, theDoc)
logger.debug("Initialising DocHighlighter ...") logger.debug("Initialising GuiDocHighlighter ...")
self.mainConf = nw.CONFIG self.mainConf = nw.CONFIG
self.theDoc = theDoc self.theDoc = theDoc
self.theParent = theParent self.theParent = theParent
@@ -70,7 +70,7 @@ class GuiDocHighlighter(QSyntaxHighlighter):
self.initHighlighter() self.initHighlighter()
logger.debug("DocHighlighter initialisation complete") logger.debug("GuiDocHighlighter initialisation complete")
return return
+381 -18
View File
@@ -6,7 +6,10 @@
Class holding the document html viewer Class holding the document html viewer
File History: File History:
Created: 2019-05-10 [0.0.1] Created: 2019-05-10 [0.0.1] GuiDocViewer
Created: 2019-10-31 [0.3.2] GuiDocViewDetails
Created: 2020-04-25 [0.4.5] GuiDocViewHeader
Created: 2020-06-09 [0.8.0] GuiDocViewFooter
This file is a part of novelWriter This file is a part of novelWriter
Copyright 2020, Veronica Berglyd Olsen Copyright 2020, Veronica Berglyd Olsen
@@ -28,13 +31,16 @@
import logging import logging
import nw import nw
from PyQt5.QtCore import Qt, QUrl from PyQt5.QtCore import Qt, QUrl, QSize
from PyQt5.QtWidgets import QTextBrowser from PyQt5.QtGui import (
from PyQt5.QtGui import QTextOption, QFont, QPalette, QColor, QTextCursor QTextOption, QFont, QPalette, QColor, QTextCursor, QIcon
)
from PyQt5.QtWidgets import (
QTextBrowser, QWidget, QScrollArea, QLabel, QHBoxLayout, QToolButton
)
from nw.core import ToHtml from nw.core import ToHtml
from nw.constants import nwAlert, nwItemType, nwDocAction from nw.constants import nwAlert, nwItemType, nwDocAction, nwUnicode
from nw.gui.docbars import GuiDocTitleBar, GuiDocViewFooter
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@@ -57,8 +63,8 @@ class GuiDocViewer(QTextBrowser):
self.setOpenExternalLinks(False) self.setOpenExternalLinks(False)
self.initViewer() self.initViewer()
# Document Title and Footer # Document Header and Footer
self.docTitle = GuiDocTitleBar(self, isEditor=False) self.docHeader = GuiDocViewHeader(self)
self.docFooter = GuiDocViewFooter(self) self.docFooter = GuiDocViewFooter(self)
self.stickyRef = False self.stickyRef = False
@@ -72,9 +78,6 @@ class GuiDocViewer(QTextBrowser):
logger.debug("GuiDocViewer initialisation complete") logger.debug("GuiDocViewer initialisation complete")
# Connect Functions
self.setSelectedHandle = self.theParent.treeView.setSelectedHandle
return return
def clearViewer(self): def clearViewer(self):
@@ -83,7 +86,7 @@ class GuiDocViewer(QTextBrowser):
self.clear() self.clear()
self.setSearchPaths([""]) self.setSearchPaths([""])
self.theHandle = None self.theHandle = None
self.docTitle.setTitleFromHandle(self.theHandle) self.docHeader.setTitleFromHandle(self.theHandle)
return True return True
def initViewer(self): def initViewer(self):
@@ -156,7 +159,7 @@ class GuiDocViewer(QTextBrowser):
self.verticalScrollBar().setValue(sPos) self.verticalScrollBar().setValue(sPos)
self.theHandle = tHandle self.theHandle = tHandle
self.theProject.setLastViewed(tHandle) self.theProject.setLastViewed(tHandle)
self.docTitle.setTitleFromHandle(self.theHandle) self.docHeader.setTitleFromHandle(self.theHandle)
self.updateDocMargins() self.updateDocMargins()
# Make sure the main GUI knows we changed the content # Make sure the main GUI knows we changed the content
@@ -185,7 +188,10 @@ class GuiDocViewer(QTextBrowser):
) % theTag, nwAlert.ERROR) ) % theTag, nwAlert.ERROR)
return return
else: else:
self.loadText(tHandle) # Let the parent handle the opening as it also ensures that
# the doc view panel is visible in case this request comes
# from outside this class.
self.theParent.viewDocument(tHandle)
self.navigateTo("#head_%s:%s" % (tHandle, sTitle)) self.navigateTo("#head_%s:%s" % (tHandle, sTitle))
return True return True
@@ -230,14 +236,14 @@ class GuiDocViewer(QTextBrowser):
else: else:
sW = 0 sW = 0
tB = self.lineWidth() tB = self.frameWidth()
tW = self.width() - 2*tB - sW tW = self.width() - 2*tB - sW
tH = self.docTitle.height() tH = self.docHeader.height()
fH = self.docFooter.height() fH = self.docFooter.height()
fY = self.height() - fH - tB fY = self.height() - fH - tB
tT = self.mainConf.getTextMargin() - tH tT = self.mainConf.getTextMargin() - tH
bT = self.mainConf.getTextMargin() - fH bT = self.mainConf.getTextMargin() - fH
self.docTitle.setGeometry(tB, tB, tW, tH) self.docHeader.setGeometry(tB, tB, tW, tH)
self.docFooter.setGeometry(tB, fY, tW, fH) self.docFooter.setGeometry(tB, fY, tW, fH)
self.setViewportMargins(0, tH, 0, fH) self.setViewportMargins(0, tH, 0, fH)
@@ -256,7 +262,7 @@ class GuiDocViewer(QTextBrowser):
title bar needs updating, title bar needs updating,
""" """
if tHandle == self.theHandle: if tHandle == self.theHandle:
self.docTitle.setTitleFromHandle(self.theHandle) self.docHeader.setTitleFromHandle(self.theHandle)
self.updateDocMargins() self.updateDocMargins()
return return
@@ -387,3 +393,360 @@ class GuiDocViewer(QTextBrowser):
return True return True
# END Class GuiDocViewer # END Class GuiDocViewer
# =============================================================================================== #
# The Embedded Document Header
# Only used by DocViewer, and is at a fixed position in the QTextBrowser's viewport
# =============================================================================================== #
class GuiDocViewHeader(QWidget):
def __init__(self, docViewer):
QWidget.__init__(self, docViewer)
logger.debug("Initialising GuiDocViewHeader ...")
self.mainConf = nw.CONFIG
self.docViewer = docViewer
self.theParent = docViewer.theParent
self.theProject = docViewer.theProject
self.theTheme = docViewer.theTheme
self.theHandle = None
# Make a QPalette that matches the Syntax Theme
self.thePalette = QPalette()
self.thePalette.setColor(QPalette.Window, QColor(*self.theTheme.colBack))
self.thePalette.setColor(QPalette.Text, QColor(*self.theTheme.colText))
fPx = int(0.9*self.theTheme.fontPixelSize)
hSp = self.mainConf.pxInt(6)
self.buttonSize = fPx + hSp
# Main Widget Settings
self.setContentsMargins(2*self.buttonSize, 0, 0, 0)
self.setAutoFillBackground(True)
self.setPalette(self.thePalette)
# Title Label
self.theTitle = QLabel()
self.theTitle.setText("")
self.theTitle.setIndent(0)
self.theTitle.setMargin(0)
self.theTitle.setContentsMargins(0, 0, 0, 0)
self.theTitle.setAutoFillBackground(True)
self.theTitle.setAlignment(Qt.AlignHCenter | Qt.AlignTop)
self.theTitle.setFixedHeight(fPx)
self.theTitle.setPalette(self.thePalette)
lblFont = self.theTitle.font()
lblFont.setPointSizeF(0.9*self.theTheme.fontPointSize)
self.theTitle.setFont(lblFont)
buttonStyle = (
"QToolButton {{border: none; background: transparent;}} "
"QToolButton:hover {{border: none; background: rgba({0},{1},{2},0.2);}}"
).format(*self.theTheme.colText)
# Buttons
self.closeButton = QToolButton(self)
self.closeButton.setIcon(self.theTheme.getIcon("close"))
self.closeButton.setContentsMargins(0, 0, 0, 0)
self.closeButton.setIconSize(QSize(fPx, fPx))
self.closeButton.setFixedSize(fPx, fPx)
self.closeButton.setStyleSheet(buttonStyle)
self.closeButton.setToolButtonStyle(Qt.ToolButtonIconOnly)
self.closeButton.setVisible(False)
self.closeButton.clicked.connect(self._closeDocument)
self.refreshButton = QToolButton(self)
self.refreshButton.setIcon(self.theTheme.getIcon("refresh"))
self.refreshButton.setContentsMargins(0, 0, 0, 0)
self.refreshButton.setIconSize(QSize(fPx, fPx))
self.refreshButton.setFixedSize(fPx, fPx)
self.refreshButton.setStyleSheet(buttonStyle)
self.refreshButton.setToolButtonStyle(Qt.ToolButtonIconOnly)
self.refreshButton.setVisible(False)
self.refreshButton.clicked.connect(self._refreshDocument)
# Assemble Layout
self.outerBox = QHBoxLayout()
self.outerBox.setSpacing(hSp)
self.outerBox.addWidget(self.theTitle, 1)
self.outerBox.addWidget(self.refreshButton, 0)
self.outerBox.addWidget(self.closeButton, 0)
self.setLayout(self.outerBox)
logger.debug("GuiDocViewHeader initialisation complete")
return
##
# Setters
##
def setTitleFromHandle(self, tHandle):
"""Sets the document title from the handle, or alternatively,
set the whole document path.
"""
self.theHandle = tHandle
if tHandle is None:
self.theTitle.setText("")
self.closeButton.setVisible(False)
self.refreshButton.setVisible(False)
return True
if self.mainConf.showFullPath:
tTitle = []
tTree = self.theProject.projTree.getItemPath(tHandle)
for aHandle in reversed(tTree):
nwItem = self.theProject.projTree[aHandle]
if nwItem is not None:
tTitle.append(nwItem.itemName)
sSep = " %s " % nwUnicode.U_RSAQUO
self.theTitle.setText(sSep.join(tTitle))
else:
nwItem = self.theProject.projTree[tHandle]
if nwItem is None:
return False
self.theTitle.setText(nwItem.itemName)
self.closeButton.setVisible(True)
self.refreshButton.setVisible(True)
return True
##
# Slots
##
def _closeDocument(self):
"""Trigger the close editor/viewer on the main window.
"""
self.theParent.closeDocViewer()
return
def _refreshDocument(self):
"""Reload the content of the document.
"""
self.docViewer.reloadText()
return
##
# Events
##
def mousePressEvent(self, theEvent):
"""Capture a click on the title and ensure that the item is
selected in the project tree.
"""
self.theParent.treeView.setSelectedHandle(self.theHandle)
return
# END Class GuiDocViewHeader
# =============================================================================================== #
# The Embedded Document Footer
# Only used by DocViewer, and is at a fixed position in the QTextBrowser's viewport
# =============================================================================================== #
class GuiDocViewFooter(QWidget):
def __init__(self, theParent):
QWidget.__init__(self, theParent)
logger.debug("Initialising GuiDocViewFooter ...")
self.mainConf = nw.CONFIG
self.theParent = theParent
self.theTheme = theParent.theTheme
self.optState = theParent.theProject.optState
self.viewMeta = theParent.theParent.viewMeta
self.theHandle = None
# Make a QPalette that matches the Syntax Theme
self.thePalette = QPalette()
self.thePalette.setColor(QPalette.Window, QColor(*self.theTheme.colBack))
self.thePalette.setColor(QPalette.Text, QColor(*self.theTheme.colText))
fPx = int(0.9*self.theTheme.fontPixelSize)
bSp = self.mainConf.pxInt(2)
hSp = self.mainConf.pxInt(8)
# Main Widget Settings
self.setContentsMargins(0, 0, 0, 0)
self.setAutoFillBackground(True)
self.setPalette(self.thePalette)
buttonStyle = (
"QToolButton {{border: none; background: transparent;}} "
"QToolButton:hover {{border: none; background: rgba({0},{1},{2},0.2);}}"
).format(*self.theTheme.colText)
# Show/Hide Details
self.showHide = QToolButton(self)
self.showHide.setToolButtonStyle(Qt.ToolButtonIconOnly)
self.showHide.setStyleSheet(buttonStyle)
self.showHide.setIcon(self.theTheme.getIcon("reference"))
self.showHide.setIconSize(QSize(fPx, fPx))
self.showHide.setFixedSize(QSize(fPx, fPx))
self.showHide.clicked.connect(self._doShowHide)
# Sticky Button
stickyOn = self.theTheme.getPixmap("sticky-on", (fPx, fPx))
stickyOff = self.theTheme.getPixmap("sticky-off", (fPx, fPx))
stickyIcon = QIcon()
stickyIcon.addPixmap(stickyOn, QIcon.Normal, QIcon.On)
stickyIcon.addPixmap(stickyOff, QIcon.Normal, QIcon.Off)
self.stickyRefs = QToolButton(self)
self.stickyRefs.setCheckable(True)
self.stickyRefs.setToolButtonStyle(Qt.ToolButtonIconOnly)
self.stickyRefs.setStyleSheet(buttonStyle)
self.stickyRefs.setIcon(stickyIcon)
self.stickyRefs.setIconSize(QSize(fPx, fPx))
self.stickyRefs.setFixedSize(QSize(fPx, fPx))
self.stickyRefs.toggled.connect(self._doToggleSticky)
# Labels
self.lblRefs = QLabel("References")
self.lblRefs.setBuddy(self.showHide)
self.lblRefs.setIndent(0)
self.lblRefs.setMargin(0)
self.lblRefs.setContentsMargins(0, 0, 0, 0)
self.lblRefs.setAutoFillBackground(True)
self.lblRefs.setFixedHeight(fPx)
self.lblRefs.setAlignment(Qt.AlignLeft | Qt.AlignTop)
self.lblRefs.setPalette(self.thePalette)
self.lblSticky = QLabel("Sticky")
self.lblSticky.setBuddy(self.stickyRefs)
self.lblSticky.setIndent(0)
self.lblSticky.setMargin(0)
self.lblSticky.setContentsMargins(0, 0, 0, 0)
self.lblSticky.setAutoFillBackground(True)
self.lblSticky.setFixedHeight(fPx)
self.lblSticky.setAlignment(Qt.AlignLeft | Qt.AlignTop)
self.lblSticky.setPalette(self.thePalette)
lblFont = self.font()
lblFont.setPointSizeF(0.9*self.theTheme.fontPointSize)
self.lblRefs.setFont(lblFont)
self.lblSticky.setFont(lblFont)
# Assemble Layout
self.outerBox = QHBoxLayout()
self.outerBox.setSpacing(bSp)
self.outerBox.addWidget(self.showHide, 0)
self.outerBox.addWidget(self.lblRefs, 0)
self.outerBox.addSpacing(hSp)
self.outerBox.addWidget(self.stickyRefs, 0)
self.outerBox.addWidget(self.lblSticky, 0)
self.outerBox.addStretch(1)
self.setLayout(self.outerBox)
logger.debug("GuiDocViewFooter initialisation complete")
return
##
# Slots
##
def _doShowHide(self):
"""Toggle the expand/collapse of the panel.
"""
isVisible = self.viewMeta.isVisible()
self.viewMeta.setVisible(not isVisible)
return
def _doToggleSticky(self, theState):
"""Toggle the sticky flag for the reference panel.
"""
logger.verbose("Reference sticky is %s" % str(theState))
self.theParent.stickyRef = theState
if not theState and self.theParent.theHandle is not None:
self.viewMeta.refreshReferences(self.theParent.theHandle)
return
# END Class GuiDocViewFooter
# =============================================================================================== #
# The Document Back-Reference Panel
# Placed in a separate QSplitter position in the main GUI window
# =============================================================================================== #
class GuiDocViewDetails(QScrollArea):
def __init__(self, theParent):
QScrollArea.__init__(self, theParent)
logger.debug("Initialising GuiDocViewDetails ...")
self.mainConf = nw.CONFIG
self.theParent = theParent
self.theProject = theParent.theProject
self.theTheme = theParent.theTheme
self.currHandle = None
self.refList = QLabel("")
self.refList.setWordWrap(True)
self.refList.setAlignment(Qt.AlignTop)
self.refList.setScaledContents(True)
self.refList.linkActivated.connect(self._linkClicked)
hCol = self.palette().highlight().color()
self.linkStyle = "style='color: rgb({0},{1},{2})'".format(
*self.theTheme.colLink
)
# Assemble
self.outerWidget = QWidget()
self.outerBox = QHBoxLayout()
self.outerBox.addWidget(self.refList, 1)
self.outerWidget.setLayout(self.outerBox)
self.setWidget(self.outerWidget)
self.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded)
self.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded)
self.setWidgetResizable(True)
self.setMinimumHeight(self.mainConf.pxInt(50))
logger.debug("GuiDocViewDetails initialisation complete")
return
def refreshReferences(self, tHandle):
"""Update the current list of document references from the
project index.
"""
self.currHandle = tHandle
if self.theParent.docViewer.stickyRef:
return
theRefs = self.theParent.theIndex.getBackReferenceList(tHandle)
theList = []
for tHandle in theRefs:
tItem = self.theProject.projTree[tHandle]
if tItem is not None:
theList.append("<a href='#head_%s:%s' %s>%s</a>" % (
tHandle, theRefs[tHandle], self.linkStyle, tItem.itemName
))
self.refList.setText(", ".join(theList))
return
##
# Internal Functions
##
def _linkClicked(self, theLink):
"""Capture the link-click and forward it to the document viewer
class for handling.
"""
logger.verbose("Clicked link: '%s'" % theLink)
if len(theLink) == 27:
tHandle = theLink[6:19]
self.theParent.viewDocument(tHandle, theLink)
return
# END Class GuiDocViewDetails
-1
View File
@@ -277,7 +277,6 @@ class GuiOutlineDetails(QScrollArea):
theBits = theLink.split("=") theBits = theLink.split("=")
if len(theBits) == 2: if len(theBits) == 2:
self.theParent.docViewer.loadFromTag(theBits[1]) self.theParent.docViewer.loadFromTag(theBits[1])
self.theParent.tabWidget.setCurrentWidget(self.theParent.splitView)
return return
## ##
+4
View File
@@ -525,9 +525,13 @@ class GuiProjectTree(QTreeWidget):
always make sure items with a parent have had their parent item always make sure items with a parent have had their parent item
sent first. sent first.
""" """
logger.debug("Building project tree ...")
self.clear() self.clear()
iCount = 0
for nwItem in self.theProject.getProjectItems(): for nwItem in self.theProject.getProjectItems():
iCount += 1
self._addTreeItem(nwItem) self._addTreeItem(nwItem)
logger.debug("%d items added to project tree" % iCount)
return True return True
def getSelectedHandle(self): def getSelectedHandle(self):
+2 -2
View File
@@ -44,7 +44,7 @@ class GuiMainStatus(QStatusBar):
def __init__(self, theParent): def __init__(self, theParent):
QStatusBar.__init__(self, theParent) QStatusBar.__init__(self, theParent)
logger.debug("Initialising MainStatus ...") logger.debug("Initialising GuiMainStatus ...")
self.mainConf = nw.CONFIG self.mainConf = nw.CONFIG
self.theParent = theParent self.theParent = theParent
@@ -123,7 +123,7 @@ class GuiMainStatus(QStatusBar):
self.sessionTimer.timeout.connect(self._updateTime) self.sessionTimer.timeout.connect(self._updateTime)
self.sessionTimer.start() self.sessionTimer.start()
logger.debug("MainStatus initialisation complete") logger.debug("GuiMainStatus initialisation complete")
self.clearStatus() self.clearStatus()
+2 -2
View File
@@ -750,11 +750,11 @@ class GuiIcons:
self.mainConf.iconPath, self.fbackName, "%s-dark.svg" % iconKey self.mainConf.iconPath, self.fbackName, "%s-dark.svg" % iconKey
) )
if path.isfile(fbackIcon): if path.isfile(fbackIcon):
logger.verbose("Loading icon '%s' from fallback theme" % iconKey) logger.verbose("Loading icon '%s' from fallback theme (dark mode)" % iconKey)
return QIcon(fbackIcon) return QIcon(fbackIcon)
fbackIcon = path.join(self.mainConf.iconPath, self.fbackName, "%s.svg" % iconKey) fbackIcon = path.join(self.mainConf.iconPath, self.fbackName, "%s.svg" % iconKey)
if path.isfile(fbackIcon): if path.isfile(fbackIcon):
logger.verbose("Loading icon '%s' from fallback theme" % iconKey) logger.verbose("Loading icon '%s' from fallback theme (light mode)" % iconKey)
return QIcon(fbackIcon) return QIcon(fbackIcon)
# Give up and return an empty icon # Give up and return an empty icon
+4 -1
View File
@@ -55,7 +55,6 @@ class GuiMain(QMainWindow):
def __init__(self): def __init__(self):
QMainWindow.__init__(self) QMainWindow.__init__(self)
logger.info("Starting %s" % nw.__package__)
logger.debug("Initialising GUI ...") logger.debug("Initialising GUI ...")
self.mainConf = nw.CONFIG self.mainConf = nw.CONFIG
@@ -232,6 +231,8 @@ class GuiMain(QMainWindow):
else: else:
self.manageProjects() self.manageProjects()
logger.debug("%s is ready ..." % nw.__package__)
return return
def clearGUI(self): def clearGUI(self):
@@ -435,6 +436,8 @@ class GuiMain(QMainWindow):
if self.theIndex.indexBroken: if self.theIndex.indexBroken:
self.rebuildIndex() self.rebuildIndex()
logger.debug("Project load complete")
return True return True
def saveProject(self, autoSave=False): def saveProject(self, autoSave=False):