mirror of
https://github.com/qgis/QGIS.git
synced 2025-04-17 00:04:02 -04:00
Merge pull request #4253 from nyalldawson/multi_canvas2
[FEATURE] Multi canvas/additional map views
This commit is contained in:
commit
738f4415d9
@ -556,6 +556,9 @@
|
||||
<file>themes/default/processingAlgorithm.svg</file>
|
||||
<file>themes/default/processingResult.svg</file>
|
||||
<file>themes/default/search.svg</file>
|
||||
<file>themes/default/mActionNewMap.svg</file>
|
||||
<file>themes/default/mActionMapSettings.svg</file>
|
||||
<file>themes/default/mActionLockExtent.svg</file>
|
||||
</qresource>
|
||||
<qresource prefix="/images/tips">
|
||||
<file alias="symbol_levels.png">qgis_tips/symbol_levels.png</file>
|
||||
|
98
images/themes/default/mActionLockExtent.svg
Normal file
98
images/themes/default/mActionLockExtent.svg
Normal file
@ -0,0 +1,98 @@
|
||||
<?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"
|
||||
height="16"
|
||||
width="16"
|
||||
version="1.1"
|
||||
id="svg20"
|
||||
sodipodi:docname="mActionLockExtent.svg"
|
||||
inkscape:version="0.92.1 r">
|
||||
<metadata
|
||||
id="metadata26">
|
||||
<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="defs24" />
|
||||
<sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="1132"
|
||||
inkscape:window-height="916"
|
||||
id="namedview22"
|
||||
showgrid="true"
|
||||
inkscape:zoom="33.375"
|
||||
inkscape:cx="7.1310861"
|
||||
inkscape:cy="7.5927961"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="27"
|
||||
inkscape:window-maximized="0"
|
||||
inkscape:current-layer="svg20">
|
||||
<inkscape:grid
|
||||
type="xygrid"
|
||||
id="grid4526" />
|
||||
</sodipodi:namedview>
|
||||
<path
|
||||
style="fill:#6d97c4;fill-rule:evenodd;stroke:#415a75;stroke-width:1;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4"
|
||||
d="M 14.5,13.5 H 9.4999793 L 11.166653,11.833327 9.4999793,10.166653 11.166651,8.49998 12.833326,10.166653 14.499998,8.49998 Z" />
|
||||
<path
|
||||
style="opacity:0.7;fill:#fcffff;fill-rule:evenodd;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path10"
|
||||
d="m 6.0854127,4.570286 c 1.2542366,-1.881355 2.7858151,-2.1309826 3.76271,-1.2542367 0.9768953,0.8767459 -1.2542368,0.6271183 -2.5084734,1.881355 -1.2542366,1.2542366 0,3.7627099 -1.2542366,3.7627099 -1.2542366,0 -1.2542366,-2.5084733 0,-4.3898282 z" />
|
||||
<path
|
||||
style="fill:#6d97c4;fill-rule:evenodd;stroke:#415a75;stroke-width:1;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path14"
|
||||
d="M 14.5,1.5000002 V 6.5000209 L 12.833326,4.8333456 11.166652,6.5000209 9.4999793,4.8333468 11.166652,3.1666741 9.4999793,1.5000006 Z" />
|
||||
<path
|
||||
style="fill:#6d97c4;fill-rule:evenodd;stroke:#415a75;stroke-width:1;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path16"
|
||||
d="M 2.5,1.5000002 H 7.5000208 L 5.8333464,3.1666739 7.5000208,4.8333475 5.833347,6.500021 4.1666735,4.8333475 2.5000002,6.500021 Z" />
|
||||
<path
|
||||
style="fill:#6d97c4;fill-rule:evenodd;stroke:#415a75;stroke-width:0.99999994;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path14-3"
|
||||
d="M 2.5,14.499999 V 9.4999798 l 1.6666739,1.6666742 1.6666728,-1.6666742 1.6666739,1.6666732 -1.6666739,1.666672 1.6666739,1.666673 z" />
|
||||
<path
|
||||
id="path2"
|
||||
d="M 3.3724264,8.3336432 C 3.4582294,5.7125241 4.0588308,4.5258991 6.135095,4.6857259 8.2111253,4.8451683 8.67798,6.1128125 8.5917932,8.7341416"
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:none;stroke:#888a85;stroke-width:3;stroke-linecap:square;stroke-linejoin:round" />
|
||||
<path
|
||||
id="path4-6"
|
||||
d="M 3.3712993,8.3336432 C 3.4560835,5.6317535 4.0495536,4.3772911 6.1011648,4.542043 8.152545,4.7063986 8.6138563,6.0443769 8.528693,8.7464831"
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:none;stroke:#eeeeec;stroke-width:0.99999994;stroke-linecap:square;stroke-linejoin:round" />
|
||||
<rect
|
||||
id="rect6"
|
||||
y="8.4996204"
|
||||
x="1.4999999"
|
||||
width="9"
|
||||
ry="0.85714287"
|
||||
rx="0.69230771"
|
||||
height="6.0000005"
|
||||
style="fill:#f1db1e;stroke:#c4a000;stroke-width:0.99999976;stroke-linecap:square" />
|
||||
</svg>
|
After Width: | Height: | Size: 4.1 KiB |
177
images/themes/default/mActionMapSettings.svg
Normal file
177
images/themes/default/mActionMapSettings.svg
Normal file
@ -0,0 +1,177 @@
|
||||
<?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"
|
||||
height="24"
|
||||
width="24"
|
||||
version="1.1"
|
||||
id="svg23"
|
||||
sodipodi:docname="mActionMapSettings.svg"
|
||||
inkscape:version="0.92.1 r">
|
||||
<metadata
|
||||
id="metadata29">
|
||||
<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="defs27">
|
||||
<linearGradient
|
||||
id="a-3"
|
||||
gradientTransform="matrix(-0.10786508,0.87849049,0.87408031,0.10732357,-1.811623,758.65836)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="304.76001"
|
||||
x2="335.29999"
|
||||
y1="64.294998"
|
||||
y2="81.926003">
|
||||
<stop
|
||||
offset="0"
|
||||
stop-color="#d3d7cf"
|
||||
id="stop2-6" />
|
||||
<stop
|
||||
offset=".18304"
|
||||
stop-color="#babdb6"
|
||||
id="stop4-7" />
|
||||
<stop
|
||||
offset=".31893"
|
||||
stop-color="#fff"
|
||||
id="stop6" />
|
||||
<stop
|
||||
offset=".87644"
|
||||
stop-color="#babdb6"
|
||||
id="stop8" />
|
||||
<stop
|
||||
offset="1"
|
||||
stop-color="#eeeeec"
|
||||
id="stop10" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="b"
|
||||
gradientTransform="matrix(-0.34112292,0.26690344,0.34708506,0.44633485,7.3860378,1027.6433)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="-6.3077998"
|
||||
x2="-9.7747002"
|
||||
y1="44.229"
|
||||
y2="44.139999">
|
||||
<stop
|
||||
offset="0"
|
||||
id="stop13" />
|
||||
<stop
|
||||
offset="1"
|
||||
stop-opacity="0"
|
||||
id="stop15" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="c"
|
||||
gradientTransform="matrix(-0.67481701,0.52736572,0.29432462,0.37835898,77.717559,981.12162)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="97.442001"
|
||||
x2="90.221001"
|
||||
y1="35.152"
|
||||
y2="35.078999">
|
||||
<stop
|
||||
offset="0"
|
||||
stop-color="#f8e27e"
|
||||
id="stop18" />
|
||||
<stop
|
||||
offset="1"
|
||||
stop-color="#e3d189"
|
||||
id="stop20" />
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1016"
|
||||
id="namedview25"
|
||||
showgrid="false"
|
||||
inkscape:zoom="9.8333333"
|
||||
inkscape:cx="12.40678"
|
||||
inkscape:cy="11.59322"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="27"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg23" />
|
||||
<linearGradient
|
||||
id="a"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="3.5"
|
||||
x2="11.5"
|
||||
y1="19.5"
|
||||
y2="19.5">
|
||||
<stop
|
||||
offset="0"
|
||||
stop-color="#b7b7b7"
|
||||
id="stop2" />
|
||||
<stop
|
||||
offset="1"
|
||||
stop-color="#e6e6e6"
|
||||
id="stop4" />
|
||||
</linearGradient>
|
||||
<g
|
||||
transform="translate(0 -8)"
|
||||
id="g21">
|
||||
<path
|
||||
d="m21.5 29.5h-17c-1 0-1.977816-1.420625-2-2.5v-16.5h19z"
|
||||
fill="url(#a)"
|
||||
fill-rule="evenodd"
|
||||
stroke="#9a9a9a"
|
||||
id="path7" />
|
||||
<path
|
||||
d="m6.5 9.9999996c-1-.9999995-3-.9999995-4 0v16.0000004c1-1 3-1 4 0z"
|
||||
fill="#e6e6e6"
|
||||
fill-rule="evenodd"
|
||||
stroke="#9a9a9a"
|
||||
id="path9" />
|
||||
<g
|
||||
transform="matrix(.69230769 0 0 .69230769 1.8461539 9.8461539)"
|
||||
id="g19" />
|
||||
</g>
|
||||
<g
|
||||
id="g73"
|
||||
transform="matrix(0.77430229,0,0,0.77430229,-0.92444663,-790.99716)">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path63"
|
||||
style="fill:url(#a-3);fill-rule:evenodd;stroke:#3b3b3b;stroke-width:1.0266068;stroke-linecap:round;stroke-linejoin:round;stroke-dashoffset:0.3612"
|
||||
d="m 10.457382,1032.309 c -0.0557,-0.8562 0.634116,-0.2492 0.875491,0 1.024776,0.7434 2.030407,1.5156 3.067343,2.2407 0.725037,0.2552 1.421475,-0.3125 1.904389,-0.793 0.69153,-0.772 1.365424,-1.7692 1.239142,-2.855 -0.0999,-0.5511 -0.678194,-0.7556 -1.060023,-1.087 -0.948649,-0.7006 -1.905189,-1.3938 -2.848652,-2.099 0.0499,-0.5363 0.921102,-0.4312 1.352206,-0.4538 1.799481,0.032 3.760889,0.6193 4.847708,2.1483 0.893786,1.2432 1.095967,2.9098 0.645088,4.3593 0.248756,1.355 0.749129,2.6839 1.605411,3.7751 -1.055028,0.7755 -2.110005,1.5509 -3.165032,2.3264 -0.74403,-0.9699 -1.666431,-1.8128 -2.743678,-2.3982 -1.597268,0.2334 -3.230567,-0.5195 -4.193648,-1.7921 -0.762442,-0.9748 -1.327479,-2.1438 -1.525916,-3.3671 z" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
style="opacity:0.23106001;fill:url(#b)"
|
||||
id="path65"
|
||||
d="m 20.569654,1038.9536 c -0.377958,0.2957 -0.449831,0.8327 -0.161152,1.2039 l 5.276506,7.7275 c 0.288677,0.3713 1.28112,0.076 1.659095,-0.2199 0.377957,-0.2957 0.905829,-1.1891 0.617119,-1.5603 l -6.181727,-7.0148 c -0.288677,-0.3712 -0.825389,-0.432 -1.203364,-0.1363 z" />
|
||||
<path
|
||||
style="fill:#f0f3f2;fill-rule:evenodd"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path67"
|
||||
d="m 10.776308,1032.3503 c 0.0041,0.017 0.02652,0.01 0.02736,0 l 3.280939,2.4093 c 0.441955,0.3249 1.026164,0.2014 1.532663,-0.063 0.511499,-0.2667 1.030216,-0.7135 1.465827,-1.3248 0.436534,-0.6127 0.691989,-1.2801 0.782256,-1.8547 0.09008,-0.5733 -0.0071,-1.1337 -0.432392,-1.4464 l -3.308254,-2.4126 c -3.27e-4,-0.012 0.0053,-0.029 0.0034,-0.028 -0.02145,0.016 0.01356,0.01 0.02736,0 1.60773,-0.1726 3.391001,0.2382 4.500933,1.0542 1.518297,1.1161 2.06238,3.1241 1.496172,4.9767 -0.567334,1.8439 -2.398541,3.2549 -4.002325,3.466 -1.037771,0.1302 -2.105965,-0.1107 -2.984774,-0.7566 -1.106711,-0.8138 -2.046256,-2.4203 -2.389076,-4.0275 h -9.3e-5 z" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path69"
|
||||
style="fill:url(#c);stroke:#3b3b3b;stroke-width:0.86699998;stroke-linecap:round;stroke-linejoin:round;stroke-dashoffset:0.69999999"
|
||||
d="m 21.969626,1036.9102 9.581585,11.1009 c 0.570734,0.7337 -0.03271,2.1379 -1.34119,3.1605 -1.308483,1.0226 -2.814237,1.2668 -3.384954,0.5331 l -8.399386,-12.0247 3.546142,-2.7701 z m 6.345662,11.8213 c -0.650481,0.5084 -0.785855,1.4312 -0.461469,1.8482 0.324412,0.4169 1.282238,0.4855 1.932707,-0.023 0.650479,-0.5084 0.754739,-1.407 0.430357,-1.8239 -0.324413,-0.417 -1.251126,-0.5098 -1.901595,0 z" />
|
||||
<path
|
||||
style="fill:#ffffff;fill-opacity:0.57758622;stroke:#3b3b3b;stroke-width:1.28935945"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path71"
|
||||
transform="matrix(0.82455744,-0.56577825,0.66205623,0.74945417,0,0)"
|
||||
d="m -679.10767,874.67072 h 3.57105 v 0.57711 h -3.57105 z" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 6.8 KiB |
98
images/themes/default/mActionNewMap.svg
Normal file
98
images/themes/default/mActionNewMap.svg
Normal file
@ -0,0 +1,98 @@
|
||||
<?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"
|
||||
height="24"
|
||||
width="24"
|
||||
version="1.1"
|
||||
id="svg23"
|
||||
sodipodi:docname="mActionNewMap.svg"
|
||||
inkscape:version="0.92.1 r">
|
||||
<metadata
|
||||
id="metadata29">
|
||||
<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="defs27" />
|
||||
<sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="1463"
|
||||
inkscape:window-height="554"
|
||||
id="namedview25"
|
||||
showgrid="false"
|
||||
inkscape:zoom="9.8333333"
|
||||
inkscape:cx="1.3220339"
|
||||
inkscape:cy="12"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="27"
|
||||
inkscape:window-maximized="0"
|
||||
inkscape:current-layer="svg23" />
|
||||
<linearGradient
|
||||
id="a"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="3.5"
|
||||
x2="11.5"
|
||||
y1="19.5"
|
||||
y2="19.5"
|
||||
gradientTransform="translate(0,-8)">
|
||||
<stop
|
||||
offset="0"
|
||||
stop-color="#b7b7b7"
|
||||
id="stop2" />
|
||||
<stop
|
||||
offset="1"
|
||||
stop-color="#e6e6e6"
|
||||
id="stop4" />
|
||||
</linearGradient>
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:url(#a);fill-rule:evenodd;stroke:#9a9a9a"
|
||||
id="path7"
|
||||
d="m 21.5,21.5 h -17 c -1,0 -1.977816,-1.420625 -2,-2.5 V 2.5 h 19 z" />
|
||||
<path
|
||||
style="fill:#e6e6e6;fill-rule:evenodd;stroke:#9a9a9a"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path9"
|
||||
d="m 6.5,1.9999996 c -1,-0.9999995 -3,-0.9999995 -4,0 V 18 c 1,-1 3,-1 4,0 z" />
|
||||
<g
|
||||
id="g16"
|
||||
transform="translate(33)">
|
||||
<rect
|
||||
style="fill:#c4a000"
|
||||
id="rect10"
|
||||
y="13"
|
||||
x="-20"
|
||||
width="11"
|
||||
rx="2.0114901"
|
||||
height="11" />
|
||||
<path
|
||||
style="fill:#fcffff"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path12"
|
||||
d="m -15,14 v 2.0625 c -0.537663,0.111041 -1.024662,0.383291 -1.375,0.78125 l -1.78125,-1.03125 -0.5,0.875 1.78125,1.03125 C -16.957063,17.966182 -17,18.225145 -17,18.5 c 0,0.274855 0.04294,0.533818 0.125,0.78125 l -1.78125,1.03125 0.5,0.875 1.78125,-1.03125 c 0.352503,0.40042 0.832682,0.670182 1.375,0.78125 V 23 h 1 v -2.0625 c 0.537663,-0.111041 1.024662,-0.383291 1.375,-0.78125 l 1.78125,1.03125 0.5,-0.875 -1.78125,-1.03125 C -12.042937,19.033818 -12,18.774855 -12,18.5 c 0,-0.274855 -0.04294,-0.533818 -0.125,-0.78125 l 1.78125,-1.03125 -0.5,-0.875 -1.78125,1.03125 C -12.977503,16.44333 -13.457682,16.173568 -14,16.0625 V 14 Z m 0.5,3.5 c 0.552,0 1,0.448 1,1 0,0.552 -0.448,1 -1,1 -0.552,0 -1,-0.448 -1,-1 0,-0.552 0.448,-1 1,-1 z" />
|
||||
<path
|
||||
style="opacity:0.3;fill:#fcffff;fill-rule:evenodd"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path14"
|
||||
d="m -19,19 9,-0.0096 c 0,0 0,0 0,-2 C -10,14 -11,14 -14.5,14 c -3.5,0 -4.5,0 -4.5,3 0,2 0,2 0,2 z" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 3.4 KiB |
@ -58,7 +58,17 @@ class QgisInterface : QObject
|
||||
|
||||
/* Exposed functions */
|
||||
|
||||
//! Zoom to full extent of map layers
|
||||
virtual QList< QgsMapCanvas* > mapCanvases() = 0;
|
||||
|
||||
virtual QgsMapCanvas* createNewMapCanvas( const QString& name ) = 0;
|
||||
|
||||
virtual void closeMapCanvas( const QString &name ) = 0;
|
||||
|
||||
public slots:
|
||||
|
||||
|
||||
|
||||
|
||||
virtual void zoomFull() = 0;
|
||||
|
||||
//! Zoom to previous view extent
|
||||
|
@ -97,6 +97,10 @@ class QgsMapCanvas : QGraphicsView
|
||||
void setSegmentationTolerance( double tolerance );
|
||||
void setSegmentationToleranceType( QgsAbstractGeometry::SegmentationToleranceType type );
|
||||
|
||||
QList< QgsMapCanvasAnnotationItem *> annotationItems() const;
|
||||
bool annotationsVisible() const;
|
||||
void setAnnotationsVisible( bool visible );
|
||||
|
||||
public slots:
|
||||
|
||||
//! Repaints the canvas map
|
||||
|
@ -47,6 +47,7 @@ SET(QGIS_APP_SRCS
|
||||
qgslabelinggui.cpp
|
||||
qgslabelingwidget.cpp
|
||||
qgsloadstylefromdbdialog.cpp
|
||||
qgsmapcanvasdockwidget.cpp
|
||||
qgsmaplayerstyleguiutils.cpp
|
||||
qgsrulebasedlabelingwidget.cpp
|
||||
qgssavestyletodbdialog.cpp
|
||||
@ -225,6 +226,7 @@ SET (QGIS_APP_MOC_HDRS
|
||||
qgslabelingwidget.h
|
||||
qgslabelpropertydialog.h
|
||||
qgsloadstylefromdbdialog.h
|
||||
qgsmapcanvasdockwidget.h
|
||||
qgsmaplayerstyleguiutils.h
|
||||
qgsrulebasedlabelingwidget.h
|
||||
qgssavestyletodbdialog.h
|
||||
|
@ -185,6 +185,7 @@
|
||||
#include "qgslayertreeviewdefaultactions.h"
|
||||
#include "qgslogger.h"
|
||||
#include "qgsmapcanvas.h"
|
||||
#include "qgsmapcanvasdockwidget.h"
|
||||
#include "qgsmapcanvassnappingutils.h"
|
||||
#include "qgsmapcanvastracer.h"
|
||||
#include "qgsmaplayer.h"
|
||||
@ -266,6 +267,7 @@
|
||||
#include "qgsvectorlayerutils.h"
|
||||
#include "qgshelp.h"
|
||||
#include "qgsvectorfilewritertask.h"
|
||||
#include "qgsnewnamedialog.h"
|
||||
|
||||
#include "qgssublayersdialog.h"
|
||||
#include "ogr/qgsopenvectorlayerdialog.h"
|
||||
@ -493,8 +495,8 @@ void QgisApp::layerTreeViewDoubleClicked( const QModelIndex &index )
|
||||
|
||||
void QgisApp::activeLayerChanged( QgsMapLayer *layer )
|
||||
{
|
||||
if ( mMapCanvas )
|
||||
mMapCanvas->setCurrentLayer( layer );
|
||||
Q_FOREACH ( QgsMapCanvas *canvas, mapCanvases() )
|
||||
canvas->setCurrentLayer( layer );
|
||||
|
||||
if ( mUndoWidget )
|
||||
{
|
||||
@ -786,7 +788,10 @@ QgisApp::QgisApp( QSplashScreen *splash, bool restorePlugins, bool skipVersionCh
|
||||
functionProfile( &QgisApp::createToolBars, this, QStringLiteral( "Toolbars" ) );
|
||||
functionProfile( &QgisApp::createStatusBar, this, QStringLiteral( "Status bar" ) );
|
||||
functionProfile( &QgisApp::createCanvasTools, this, QStringLiteral( "Create canvas tools" ) );
|
||||
|
||||
mMapCanvas->freeze();
|
||||
applyDefaultSettingsToCanvas( mMapCanvas );
|
||||
|
||||
functionProfile( &QgisApp::initLayerTreeView, this, QStringLiteral( "Init Layer tree view" ) );
|
||||
functionProfile( &QgisApp::createOverview, this, QStringLiteral( "Create overview" ) );
|
||||
functionProfile( &QgisApp::createMapTips, this, QStringLiteral( "Create map tips" ) );
|
||||
@ -1294,7 +1299,7 @@ QgisApp::QgisApp()
|
||||
|
||||
QgisApp::~QgisApp()
|
||||
{
|
||||
mMapCanvas->stopRendering();
|
||||
stopRendering();
|
||||
|
||||
delete mInternalClipboard;
|
||||
delete mQgisInterface;
|
||||
@ -1465,7 +1470,7 @@ void QgisApp::dropEvent( QDropEvent *event )
|
||||
|
||||
void QgisApp::dropEventTimeout()
|
||||
{
|
||||
mMapCanvas->freeze();
|
||||
freezeCanvases();
|
||||
QStringList files = sender()->property( "files" ).toStringList();
|
||||
sender()->deleteLater();
|
||||
|
||||
@ -1480,15 +1485,18 @@ void QgisApp::dropEventTimeout()
|
||||
handleDropUriList( lst );
|
||||
}
|
||||
|
||||
mMapCanvas->freeze( false );
|
||||
mMapCanvas->refresh();
|
||||
freezeCanvases( false );
|
||||
refreshMapCanvas();
|
||||
}
|
||||
|
||||
void QgisApp::annotationCreated( QgsAnnotation *annotation )
|
||||
{
|
||||
// create canvas annotation item for annotation
|
||||
QgsMapCanvasAnnotationItem *canvasItem = new QgsMapCanvasAnnotationItem( annotation, mMapCanvas );
|
||||
Q_UNUSED( canvasItem ); //item is already added automatically to canvas scene
|
||||
Q_FOREACH ( QgsMapCanvas *canvas, mapCanvases() )
|
||||
{
|
||||
QgsMapCanvasAnnotationItem *canvasItem = new QgsMapCanvasAnnotationItem( annotation, canvas );
|
||||
Q_UNUSED( canvasItem ); //item is already added automatically to canvas scene
|
||||
}
|
||||
}
|
||||
|
||||
void QgisApp::registerCustomDropHandler( QgsCustomDropHandler *handler )
|
||||
@ -1627,6 +1635,19 @@ void QgisApp::applyProjectSettingsToCanvas( QgsMapCanvas *canvas )
|
||||
canvas->setSelectionColor( myColor );
|
||||
}
|
||||
|
||||
void QgisApp::applyDefaultSettingsToCanvas( QgsMapCanvas *canvas )
|
||||
{
|
||||
QgsSettings settings;
|
||||
canvas->enableAntiAliasing( settings.value( QStringLiteral( "qgis/enable_anti_aliasing" ), true ).toBool() );
|
||||
double zoomFactor = settings.value( QStringLiteral( "qgis/zoom_factor" ), 2 ).toDouble();
|
||||
canvas->setWheelFactor( zoomFactor );
|
||||
canvas->setCachingEnabled( settings.value( QStringLiteral( "qgis/enable_render_caching" ), true ).toBool() );
|
||||
canvas->setParallelRenderingEnabled( settings.value( QStringLiteral( "qgis/parallel_rendering" ), true ).toBool() );
|
||||
canvas->setMapUpdateInterval( settings.value( QStringLiteral( "qgis/map_update_interval" ), 250 ).toInt() );
|
||||
canvas->setSegmentationTolerance( settings.value( QStringLiteral( "qgis/segmentationTolerance" ), "0.01745" ).toDouble() );
|
||||
canvas->setSegmentationToleranceType( QgsAbstractGeometry::SegmentationToleranceType( settings.value( QStringLiteral( "qgis/segmentationToleranceType" ), "0" ).toInt() ) );
|
||||
}
|
||||
|
||||
void QgisApp::readSettings()
|
||||
{
|
||||
QgsSettings settings;
|
||||
@ -1663,6 +1684,7 @@ void QgisApp::createActions()
|
||||
connect( mActionSaveProject, SIGNAL( triggered() ), this, SLOT( fileSave() ) );
|
||||
connect( mActionSaveProjectAs, SIGNAL( triggered() ), this, SLOT( fileSaveAs() ) );
|
||||
connect( mActionSaveMapAsImage, SIGNAL( triggered() ), this, SLOT( saveMapAsImage() ) );
|
||||
connect( mActionNewMapCanvas, &QAction::triggered, this, &QgisApp::newMapCanvas );
|
||||
connect( mActionNewPrintComposer, SIGNAL( triggered() ), this, SLOT( newPrintComposer() ) );
|
||||
connect( mActionShowComposerManager, SIGNAL( triggered() ), this, SLOT( showComposerManager() ) );
|
||||
connect( mActionExit, SIGNAL( triggered() ), this, SLOT( fileExit() ) );
|
||||
@ -2539,7 +2561,7 @@ void QgisApp::createStatusBar()
|
||||
"the rotation" ) );
|
||||
mRotationEdit->setToolTip( tr( "Current clockwise map rotation in degrees" ) );
|
||||
statusBar()->addPermanentWidget( mRotationEdit, 0 );
|
||||
connect( mRotationEdit, SIGNAL( valueChanged( double ) ), this, SLOT( userRotation() ) );
|
||||
connect( mRotationEdit, static_cast < void ( QgsDoubleSpinBox::* )( double ) > ( &QgsDoubleSpinBox::valueChanged ), this, &QgisApp::userRotation );
|
||||
|
||||
showRotation();
|
||||
|
||||
@ -2831,7 +2853,12 @@ void QgisApp::setupConnections()
|
||||
connect( mMapCanvas, &QgsMapCanvas::zoomNextStatusChanged,
|
||||
mActionZoomNext, &QAction::setEnabled );
|
||||
connect( mRenderSuppressionCBox, &QAbstractButton::toggled,
|
||||
mMapCanvas, &QgsMapCanvas::setRenderFlag );
|
||||
this, [ = ]( bool flag )
|
||||
{
|
||||
Q_FOREACH ( QgsMapCanvas *canvas, mapCanvases() )
|
||||
canvas->setRenderFlag( flag );
|
||||
}
|
||||
);
|
||||
|
||||
connect( mMapCanvas, &QgsMapCanvas::destinationCrsChanged,
|
||||
this, &QgisApp::reprojectAnnotations );
|
||||
@ -3032,20 +3059,6 @@ void QgisApp::createOverview()
|
||||
mPanelMenu->addAction( mOverviewDock->toggleViewAction() );
|
||||
|
||||
mLayerTreeCanvasBridge->setOvervewCanvas( mOverviewCanvas );
|
||||
|
||||
// moved here to set anti aliasing to both map canvas and overview
|
||||
QgsSettings mySettings;
|
||||
// Anti Aliasing enabled by default as of QGIS 1.7
|
||||
mMapCanvas->enableAntiAliasing( mySettings.value( QStringLiteral( "qgis/enable_anti_aliasing" ), true ).toBool() );
|
||||
|
||||
double zoomFactor = mySettings.value( QStringLiteral( "qgis/zoom_factor" ), 2 ).toDouble();
|
||||
mMapCanvas->setWheelFactor( zoomFactor );
|
||||
|
||||
mMapCanvas->setCachingEnabled( mySettings.value( QStringLiteral( "qgis/enable_render_caching" ), true ).toBool() );
|
||||
|
||||
mMapCanvas->setParallelRenderingEnabled( mySettings.value( QStringLiteral( "qgis/parallel_rendering" ), true ).toBool() );
|
||||
|
||||
mMapCanvas->setMapUpdateInterval( mySettings.value( QStringLiteral( "qgis/map_update_interval" ), 250 ).toInt() );
|
||||
}
|
||||
|
||||
void QgisApp::addDockWidget( Qt::DockWidgetArea area, QDockWidget *thepDockWidget )
|
||||
@ -3063,7 +3076,7 @@ void QgisApp::addDockWidget( Qt::DockWidgetArea area, QDockWidget *thepDockWidge
|
||||
thepDockWidget->show();
|
||||
|
||||
// refresh the map canvas
|
||||
mMapCanvas->refresh();
|
||||
refreshMapCanvas();
|
||||
}
|
||||
|
||||
void QgisApp::removeDockWidget( QDockWidget *thepDockWidget )
|
||||
@ -3105,6 +3118,101 @@ QgsMapCanvas *QgisApp::mapCanvas()
|
||||
return mMapCanvas;
|
||||
}
|
||||
|
||||
QgsMapCanvas *QgisApp::createNewMapCanvas( const QString &name, bool isFloating, const QRect &dockGeometry, bool synced, bool showCursor, bool scaleSynced, double scaleFactor )
|
||||
{
|
||||
Q_FOREACH ( QgsMapCanvas *canvas, mapCanvases() )
|
||||
{
|
||||
if ( canvas->objectName() == name )
|
||||
{
|
||||
QString errorMessage = tr( "A map canvas with name '%1' already exists!" ).arg( name );
|
||||
QgsDebugMsg( errorMessage );
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
QgsMapCanvasDockWidget *mapCanvasWidget = new QgsMapCanvasDockWidget( name, this );
|
||||
mapCanvasWidget->setAllowedAreas( Qt::AllDockWidgetAreas );
|
||||
mapCanvasWidget->setMainCanvas( mMapCanvas );
|
||||
|
||||
mapCanvasWidget->setFloating( isFloating );
|
||||
if ( dockGeometry.isEmpty() )
|
||||
{
|
||||
// try to guess a nice initial placement for view - about 3/4 along, half way down
|
||||
mapCanvasWidget->setGeometry( QRect( rect().width() * 0.75, rect().height() * 0.5, 400, 400 ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
mapCanvasWidget->setGeometry( dockGeometry );
|
||||
}
|
||||
|
||||
QgsMapCanvas *mapCanvas = mapCanvasWidget->mapCanvas();
|
||||
mapCanvas->freeze( true );
|
||||
mapCanvas->setObjectName( name );
|
||||
connect( mapCanvas, &QgsMapCanvas::messageEmitted, this, &QgisApp::displayMessage );
|
||||
connect( mLayerTreeCanvasBridge, &QgsLayerTreeMapCanvasBridge::canvasLayersChanged, mapCanvas, &QgsMapCanvas::setLayers );
|
||||
|
||||
applyProjectSettingsToCanvas( mapCanvas );
|
||||
applyDefaultSettingsToCanvas( mapCanvas );
|
||||
|
||||
mapCanvas->setLayers( mMapCanvas->layers() );
|
||||
mapCanvas->setExtent( mMapCanvas->extent() );
|
||||
|
||||
mapCanvas->setDestinationCrs( QgsProject::instance()->crs() );
|
||||
|
||||
|
||||
// add existing annotations to canvas
|
||||
Q_FOREACH ( QgsAnnotation *annotation, QgsProject::instance()->annotationManager()->annotations() )
|
||||
{
|
||||
QgsMapCanvasAnnotationItem *canvasItem = new QgsMapCanvasAnnotationItem( annotation, mapCanvas );
|
||||
Q_UNUSED( canvasItem ); //item is already added automatically to canvas scene
|
||||
}
|
||||
|
||||
addDockWidget( Qt::RightDockWidgetArea, mapCanvasWidget );
|
||||
mapCanvas->freeze( false );
|
||||
markDirty();
|
||||
connect( mapCanvasWidget, &QgsMapCanvasDockWidget::closed, this, &QgisApp::markDirty );
|
||||
connect( mapCanvasWidget, &QgsMapCanvasDockWidget::renameTriggered, this, &QgisApp::renameView );
|
||||
|
||||
mapCanvasWidget->setViewCenterSynchronized( synced );
|
||||
mapCanvasWidget->setCursorMarkerVisible( showCursor );
|
||||
mapCanvasWidget->setScaleFactor( scaleFactor );
|
||||
mapCanvasWidget->setViewScaleSynchronized( scaleSynced );
|
||||
|
||||
return mapCanvas;
|
||||
}
|
||||
|
||||
void QgisApp::closeMapCanvas( const QString &name )
|
||||
{
|
||||
Q_FOREACH ( QgsMapCanvasDockWidget *w, findChildren< QgsMapCanvasDockWidget * >() )
|
||||
{
|
||||
if ( w->mapCanvas()->objectName() == name )
|
||||
{
|
||||
w->close();
|
||||
delete w;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void QgisApp::closeAdditionalMapCanvases()
|
||||
{
|
||||
freezeCanvases( true ); // closing docks may cause canvases to resize, and we don't want a map refresh occurring
|
||||
Q_FOREACH ( QgsMapCanvasDockWidget *w, findChildren< QgsMapCanvasDockWidget * >() )
|
||||
{
|
||||
w->close();
|
||||
delete w;
|
||||
}
|
||||
freezeCanvases( false );
|
||||
}
|
||||
|
||||
void QgisApp::freezeCanvases( bool frozen )
|
||||
{
|
||||
Q_FOREACH ( QgsMapCanvas *canvas, mapCanvases() )
|
||||
{
|
||||
canvas->freeze( frozen );
|
||||
}
|
||||
}
|
||||
|
||||
QgsMessageBar *QgisApp::messageBar()
|
||||
{
|
||||
Q_ASSERT( mInfoBar );
|
||||
@ -3664,7 +3772,7 @@ QString QgisApp::crsAndFormatAdjustedLayerUri( const QString &uri, const QString
|
||||
*/
|
||||
void QgisApp::addVectorLayer()
|
||||
{
|
||||
mMapCanvas->freeze();
|
||||
freezeCanvases();
|
||||
QgsOpenVectorLayerDialog *ovl = new QgsOpenVectorLayerDialog( this );
|
||||
|
||||
if ( ovl->exec() )
|
||||
@ -3677,8 +3785,8 @@ void QgisApp::addVectorLayer()
|
||||
}
|
||||
}
|
||||
|
||||
mMapCanvas->freeze( false );
|
||||
mMapCanvas->refresh();
|
||||
freezeCanvases( false );
|
||||
refreshMapCanvas();
|
||||
|
||||
delete ovl;
|
||||
}
|
||||
@ -3729,7 +3837,7 @@ bool QgisApp::addVectorLayers( const QStringList &layerQStringList, const QStrin
|
||||
|
||||
if ( ! layer )
|
||||
{
|
||||
mMapCanvas->freeze( false );
|
||||
freezeCanvases( false );
|
||||
|
||||
// Let render() do its own cursor management
|
||||
// QApplication::restoreOverrideCursor();
|
||||
@ -3807,8 +3915,8 @@ bool QgisApp::addVectorLayers( const QStringList &layerQStringList, const QStrin
|
||||
// Let the caller do it otherwise
|
||||
if ( !wasfrozen )
|
||||
{
|
||||
mMapCanvas->freeze( false );
|
||||
mMapCanvas->refresh();
|
||||
freezeCanvases( false );
|
||||
refreshMapCanvas();
|
||||
}
|
||||
// Let render() do its own cursor management
|
||||
// QApplication::restoreOverrideCursor();
|
||||
@ -4210,11 +4318,11 @@ void QgisApp::addDatabaseLayers( QStringList const &layerPathList, QString const
|
||||
// no layers to add so bail out, but
|
||||
// allow mMapCanvas to handle events
|
||||
// first
|
||||
mMapCanvas->freeze( false );
|
||||
freezeCanvases( false );
|
||||
return;
|
||||
}
|
||||
|
||||
mMapCanvas->freeze( true );
|
||||
freezeCanvases( true );
|
||||
|
||||
QApplication::setOverrideCursor( Qt::WaitCursor );
|
||||
|
||||
@ -4228,7 +4336,7 @@ void QgisApp::addDatabaseLayers( QStringList const &layerPathList, QString const
|
||||
|
||||
if ( ! layer )
|
||||
{
|
||||
mMapCanvas->freeze( false );
|
||||
freezeCanvases( false );
|
||||
QApplication::restoreOverrideCursor();
|
||||
|
||||
// XXX insert meaningful whine to the user here
|
||||
@ -4264,8 +4372,8 @@ void QgisApp::addDatabaseLayers( QStringList const &layerPathList, QString const
|
||||
}
|
||||
|
||||
// draw the map
|
||||
mMapCanvas->freeze( false );
|
||||
mMapCanvas->refresh();
|
||||
freezeCanvases( false );
|
||||
refreshMapCanvas();
|
||||
|
||||
QApplication::restoreOverrideCursor();
|
||||
}
|
||||
@ -4474,10 +4582,10 @@ void QgisApp::addAfsLayer()
|
||||
this, SLOT( addAfsLayer( QString, QString ) ) );
|
||||
|
||||
bool wasFrozen = mapCanvas()->isFrozen();
|
||||
mapCanvas()->freeze( true );
|
||||
freezeCanvases();
|
||||
afss->exec();
|
||||
if ( !wasFrozen )
|
||||
mapCanvas()->freeze( false );
|
||||
freezeCanvases( false );
|
||||
delete afss;
|
||||
}
|
||||
|
||||
@ -4508,10 +4616,10 @@ void QgisApp::addAmsLayer()
|
||||
this, SLOT( addAmsLayer( QString, QString ) ) );
|
||||
|
||||
bool wasFrozen = mapCanvas()->isFrozen();
|
||||
mapCanvas()->freeze( true );
|
||||
freezeCanvases();
|
||||
amss->exec();
|
||||
if ( !wasFrozen )
|
||||
mapCanvas()->freeze( false );
|
||||
freezeCanvases( false );
|
||||
delete amss;
|
||||
}
|
||||
|
||||
@ -5656,11 +5764,11 @@ void QgisApp::toggleFullScreen()
|
||||
// would otherwise cause two re-renders of the map, which can take a
|
||||
// long time.
|
||||
bool wasFrozen = mapCanvas()->isFrozen();
|
||||
mapCanvas()->freeze();
|
||||
freezeCanvases();
|
||||
showNormal();
|
||||
showMaximized();
|
||||
if ( !wasFrozen )
|
||||
mapCanvas()->freeze( false );
|
||||
freezeCanvases( false );
|
||||
mPrevScreenModeMaximized = false;
|
||||
}
|
||||
else
|
||||
@ -5798,8 +5906,8 @@ void QgisApp::removeWindow( QAction *action )
|
||||
|
||||
void QgisApp::stopRendering()
|
||||
{
|
||||
if ( mMapCanvas )
|
||||
mMapCanvas->stopRendering();
|
||||
Q_FOREACH ( QgsMapCanvas *canvas, mapCanvases() )
|
||||
canvas->stopRendering();
|
||||
}
|
||||
|
||||
//reimplements method from base (gui) class
|
||||
@ -7044,6 +7152,11 @@ QList<QgsMapCanvasAnnotationItem *> QgisApp::annotationItems()
|
||||
return itemList;
|
||||
}
|
||||
|
||||
QList<QgsMapCanvas *> QgisApp::mapCanvases()
|
||||
{
|
||||
return findChildren< QgsMapCanvas * >();
|
||||
}
|
||||
|
||||
void QgisApp::removeAnnotationItems()
|
||||
{
|
||||
if ( !mMapCanvas )
|
||||
@ -7162,10 +7275,7 @@ void QgisApp::mergeAttributesOfSelectedFeatures()
|
||||
|
||||
vl->endEditCommand();
|
||||
|
||||
if ( mapCanvas() )
|
||||
{
|
||||
vl->triggerRepaint();
|
||||
}
|
||||
vl->triggerRepaint();
|
||||
}
|
||||
|
||||
void QgisApp::modifyAttributesOfSelectedFeatures()
|
||||
@ -7341,10 +7451,7 @@ void QgisApp::mergeSelectedFeatures()
|
||||
|
||||
vl->endEditCommand();
|
||||
|
||||
if ( mapCanvas() )
|
||||
{
|
||||
vl->triggerRepaint();
|
||||
}
|
||||
vl->triggerRepaint();
|
||||
}
|
||||
|
||||
void QgisApp::nodeTool()
|
||||
@ -7421,7 +7528,7 @@ void QgisApp::deselectAll()
|
||||
{
|
||||
// Turn off rendering to improve speed.
|
||||
bool wasFrozen = mMapCanvas->isFrozen();
|
||||
mMapCanvas->freeze();
|
||||
freezeCanvases();
|
||||
|
||||
QMap<QString, QgsMapLayer *> layers = QgsProject::instance()->mapLayers();
|
||||
for ( QMap<QString, QgsMapLayer *>::iterator it = layers.begin(); it != layers.end(); ++it )
|
||||
@ -7435,7 +7542,7 @@ void QgisApp::deselectAll()
|
||||
|
||||
// Turn on rendering (if it was on previously)
|
||||
if ( !wasFrozen )
|
||||
mMapCanvas->freeze( false );
|
||||
freezeCanvases( false );
|
||||
}
|
||||
|
||||
void QgisApp::invertSelection()
|
||||
@ -7453,13 +7560,13 @@ void QgisApp::invertSelection()
|
||||
|
||||
// Turn off rendering to improve speed.
|
||||
bool wasFrozen = mMapCanvas->isFrozen();
|
||||
mMapCanvas->freeze();
|
||||
freezeCanvases();
|
||||
|
||||
vlayer->invertSelection();
|
||||
|
||||
// Turn on rendering (if it was on previously)
|
||||
if ( !wasFrozen )
|
||||
mMapCanvas->freeze( false );
|
||||
freezeCanvases( false );
|
||||
}
|
||||
|
||||
void QgisApp::selectAll()
|
||||
@ -7477,13 +7584,13 @@ void QgisApp::selectAll()
|
||||
|
||||
// Turn off rendering to improve speed.
|
||||
bool wasFrozen = mMapCanvas->isFrozen();
|
||||
mMapCanvas->freeze();
|
||||
freezeCanvases();
|
||||
|
||||
vlayer->selectAll();
|
||||
|
||||
// Turn on rendering (if it was on previously)
|
||||
if ( !wasFrozen )
|
||||
mMapCanvas->freeze( false );
|
||||
freezeCanvases( false );
|
||||
}
|
||||
|
||||
void QgisApp::selectByExpression()
|
||||
@ -7723,12 +7830,12 @@ QgsVectorLayer *QgisApp::pasteAsNewMemoryVector( const QString &layerName )
|
||||
|
||||
layer->setName( layerNameCopy );
|
||||
|
||||
mMapCanvas->freeze();
|
||||
freezeCanvases();
|
||||
|
||||
QgsProject::instance()->addMapLayer( layer );
|
||||
|
||||
mMapCanvas->freeze( false );
|
||||
mMapCanvas->refresh();
|
||||
freezeCanvases( false );
|
||||
refreshMapCanvas();
|
||||
|
||||
return layer;
|
||||
}
|
||||
@ -7936,10 +8043,12 @@ void QgisApp::copyFeatures( QgsFeatureStore &featureStore )
|
||||
|
||||
void QgisApp::refreshMapCanvas()
|
||||
{
|
||||
//stop any current rendering
|
||||
mMapCanvas->stopRendering();
|
||||
|
||||
mMapCanvas->refreshAllLayers();
|
||||
Q_FOREACH ( QgsMapCanvas *canvas, mapCanvases() )
|
||||
{
|
||||
//stop any current rendering
|
||||
canvas->stopRendering();
|
||||
canvas->refreshAllLayers();
|
||||
}
|
||||
}
|
||||
|
||||
void QgisApp::canvasRefreshStarted()
|
||||
@ -8065,7 +8174,7 @@ bool QgisApp::toggleEditing( QgsMapLayer *layer, bool allowCancel )
|
||||
case QMessageBox::Discard:
|
||||
QApplication::setOverrideCursor( Qt::WaitCursor );
|
||||
|
||||
mMapCanvas->freeze( true );
|
||||
freezeCanvases();
|
||||
if ( !vlayer->rollBack() )
|
||||
{
|
||||
messageBar()->pushMessage( tr( "Error" ),
|
||||
@ -8073,7 +8182,7 @@ bool QgisApp::toggleEditing( QgsMapLayer *layer, bool allowCancel )
|
||||
QgsMessageBar::CRITICAL );
|
||||
res = false;
|
||||
}
|
||||
mMapCanvas->freeze( false );
|
||||
freezeCanvases( false );
|
||||
|
||||
vlayer->triggerRepaint();
|
||||
|
||||
@ -8086,9 +8195,9 @@ bool QgisApp::toggleEditing( QgsMapLayer *layer, bool allowCancel )
|
||||
}
|
||||
else //layer not modified
|
||||
{
|
||||
mMapCanvas->freeze( true );
|
||||
freezeCanvases();
|
||||
vlayer->rollBack();
|
||||
mMapCanvas->freeze( false );
|
||||
freezeCanvases( false );
|
||||
res = true;
|
||||
vlayer->triggerRepaint();
|
||||
}
|
||||
@ -8143,7 +8252,7 @@ void QgisApp::cancelEdits( QgsMapLayer *layer, bool leaveEditable, bool triggerR
|
||||
if ( vlayer == activeLayer() && leaveEditable )
|
||||
mSaveRollbackInProgress = true;
|
||||
|
||||
mMapCanvas->freeze( true );
|
||||
freezeCanvases();
|
||||
if ( !vlayer->rollBack( !leaveEditable ) )
|
||||
{
|
||||
mSaveRollbackInProgress = false;
|
||||
@ -8154,7 +8263,7 @@ void QgisApp::cancelEdits( QgsMapLayer *layer, bool leaveEditable, bool triggerR
|
||||
vlayer->name(),
|
||||
vlayer->commitErrors().join( QStringLiteral( "\n " ) ) ) );
|
||||
}
|
||||
mMapCanvas->freeze( false );
|
||||
freezeCanvases( false );
|
||||
|
||||
if ( leaveEditable )
|
||||
{
|
||||
@ -8172,7 +8281,7 @@ void QgisApp::saveEdits()
|
||||
{
|
||||
saveEdits( layer, true, false );
|
||||
}
|
||||
mMapCanvas->refresh();
|
||||
refreshMapCanvas();
|
||||
activateDeactivateLayerRelatedActions( activeLayer() );
|
||||
}
|
||||
|
||||
@ -8188,7 +8297,7 @@ void QgisApp::saveAllEdits( bool verifyAction )
|
||||
{
|
||||
saveEdits( layer, true, false );
|
||||
}
|
||||
mMapCanvas->refresh();
|
||||
refreshMapCanvas();
|
||||
activateDeactivateLayerRelatedActions( activeLayer() );
|
||||
}
|
||||
|
||||
@ -8198,7 +8307,7 @@ void QgisApp::rollbackEdits()
|
||||
{
|
||||
cancelEdits( layer, true, false );
|
||||
}
|
||||
mMapCanvas->refresh();
|
||||
refreshMapCanvas();
|
||||
activateDeactivateLayerRelatedActions( activeLayer() );
|
||||
}
|
||||
|
||||
@ -8214,7 +8323,7 @@ void QgisApp::rollbackAllEdits( bool verifyAction )
|
||||
{
|
||||
cancelEdits( layer, true, false );
|
||||
}
|
||||
mMapCanvas->refresh();
|
||||
refreshMapCanvas();
|
||||
activateDeactivateLayerRelatedActions( activeLayer() );
|
||||
}
|
||||
|
||||
@ -8224,7 +8333,7 @@ void QgisApp::cancelEdits()
|
||||
{
|
||||
cancelEdits( layer, false, false );
|
||||
}
|
||||
mMapCanvas->refresh();
|
||||
refreshMapCanvas();
|
||||
activateDeactivateLayerRelatedActions( activeLayer() );
|
||||
}
|
||||
|
||||
@ -8240,7 +8349,7 @@ void QgisApp::cancelAllEdits( bool verifyAction )
|
||||
{
|
||||
cancelEdits( layer, false, false );
|
||||
}
|
||||
mMapCanvas->refresh();
|
||||
refreshMapCanvas();
|
||||
activateDeactivateLayerRelatedActions( activeLayer() );
|
||||
}
|
||||
|
||||
@ -8527,7 +8636,7 @@ void QgisApp::removeLayer()
|
||||
|
||||
showStatusMessage( tr( "%n legend entries removed.", "number of removed legend entries", selectedNodes.count() ) );
|
||||
|
||||
mMapCanvas->refresh();
|
||||
refreshMapCanvas();
|
||||
}
|
||||
|
||||
void QgisApp::duplicateLayers( const QList<QgsMapLayer *> &lyrList )
|
||||
@ -8543,7 +8652,7 @@ void QgisApp::duplicateLayers( const QList<QgsMapLayer *> &lyrList )
|
||||
return;
|
||||
}
|
||||
|
||||
mMapCanvas->freeze();
|
||||
freezeCanvases();
|
||||
QgsMapLayer *dupLayer = nullptr;
|
||||
QString layerDupName, unSppType;
|
||||
QList<QgsMessageBarItem *> msgBars;
|
||||
@ -8672,7 +8781,7 @@ void QgisApp::duplicateLayers( const QList<QgsMapLayer *> &lyrList )
|
||||
|
||||
dupLayer = nullptr;
|
||||
|
||||
mMapCanvas->freeze( false );
|
||||
freezeCanvases( false );
|
||||
|
||||
// display errors in message bar after duplication of layers
|
||||
Q_FOREACH ( QgsMessageBarItem *msgBar, msgBars )
|
||||
@ -8701,15 +8810,15 @@ void QgisApp::setLayerScaleVisibility()
|
||||
}
|
||||
if ( dlg->exec() )
|
||||
{
|
||||
mMapCanvas->freeze();
|
||||
freezeCanvases();
|
||||
Q_FOREACH ( QgsMapLayer *layer, layers )
|
||||
{
|
||||
layer->setScaleBasedVisibility( dlg->hasScaleVisibility() );
|
||||
layer->setMinimumScale( 1.0 / dlg->maximumScale() );
|
||||
layer->setMaximumScale( 1.0 / dlg->minimumScale() );
|
||||
}
|
||||
mMapCanvas->freeze( false );
|
||||
mMapCanvas->refresh();
|
||||
freezeCanvases( false );
|
||||
refreshMapCanvas();
|
||||
}
|
||||
delete dlg;
|
||||
}
|
||||
@ -8781,7 +8890,7 @@ void QgisApp::setLayerCrs()
|
||||
}
|
||||
}
|
||||
|
||||
mMapCanvas->refresh();
|
||||
refreshMapCanvas();
|
||||
}
|
||||
|
||||
void QgisApp::setProjectCrsFromLayer()
|
||||
@ -8849,7 +8958,7 @@ void QgisApp::legendLayerStretchUsingCurrentExtent()
|
||||
layer->refreshContrastEnhancement( myRectangle );
|
||||
|
||||
mLayerTreeView->refreshLayerSymbology( layer->id() );
|
||||
mMapCanvas->refresh();
|
||||
refreshMapCanvas();
|
||||
}
|
||||
}
|
||||
|
||||
@ -9133,16 +9242,10 @@ void QgisApp::showOptionsDialog( QWidget *parent, const QString ¤tPage )
|
||||
|
||||
setupLayerTreeViewFromSettings();
|
||||
|
||||
mMapCanvas->enableAntiAliasing( mySettings.value( QStringLiteral( "qgis/enable_anti_aliasing" ) ).toBool() );
|
||||
|
||||
double zoomFactor = mySettings.value( QStringLiteral( "qgis/zoom_factor" ), 2 ).toDouble();
|
||||
mMapCanvas->setWheelFactor( zoomFactor );
|
||||
|
||||
mMapCanvas->setCachingEnabled( mySettings.value( QStringLiteral( "qgis/enable_render_caching" ), true ).toBool() );
|
||||
|
||||
mMapCanvas->setParallelRenderingEnabled( mySettings.value( QStringLiteral( "qgis/parallel_rendering" ), true ).toBool() );
|
||||
|
||||
mMapCanvas->setMapUpdateInterval( mySettings.value( QStringLiteral( "qgis/map_update_interval" ), 250 ).toInt() );
|
||||
Q_FOREACH ( QgsMapCanvas *canvas, mapCanvases() )
|
||||
{
|
||||
applyDefaultSettingsToCanvas( canvas );
|
||||
}
|
||||
|
||||
if ( oldCapitalize != mySettings.value( QStringLiteral( "qgis/capitalizeLayerName" ), QVariant( false ) ).toBool() )
|
||||
{
|
||||
@ -9163,7 +9266,10 @@ void QgisApp::showOptionsDialog( QWidget *parent, const QString ¤tPage )
|
||||
}
|
||||
|
||||
//do we need this? TS
|
||||
mMapCanvas->refresh();
|
||||
Q_FOREACH ( QgsMapCanvas *canvas, mapCanvases() )
|
||||
{
|
||||
canvas->refresh();
|
||||
}
|
||||
|
||||
mRasterFileFilter = QgsProviderRegistry::instance()->fileRasterFilters();
|
||||
|
||||
@ -9176,9 +9282,6 @@ void QgisApp::showOptionsDialog( QWidget *parent, const QString ¤tPage )
|
||||
qobject_cast<QgsMeasureTool *>( mMapTools.mMeasureArea )->updateSettings();
|
||||
qobject_cast<QgsMapToolMeasureAngle *>( mMapTools.mMeasureAngle )->updateSettings();
|
||||
|
||||
mMapCanvas->setSegmentationTolerance( mySettings.value( QStringLiteral( "qgis/segmentationTolerance" ), "0.01745" ).toDouble() );
|
||||
mMapCanvas->setSegmentationToleranceType( QgsAbstractGeometry::SegmentationToleranceType( mySettings.value( QStringLiteral( "qgis/segmentationToleranceType" ), "0" ).toInt() ) );
|
||||
|
||||
double factor = mySettings.value( QStringLiteral( "qgis/magnifier_factor_default" ), 1.0 ).toDouble();
|
||||
mMagnifierWidget->setDefaultFactor( factor );
|
||||
mMagnifierWidget->updateMagnification( factor );
|
||||
@ -9439,7 +9542,7 @@ QgsVectorLayer *QgisApp::addVectorLayer( const QString &vectorLayerPath, const Q
|
||||
{
|
||||
bool wasfrozen = mMapCanvas->isFrozen();
|
||||
|
||||
mMapCanvas->freeze();
|
||||
freezeCanvases();
|
||||
|
||||
// Let render() do its own cursor management
|
||||
// QApplication::setOverrideCursor(Qt::WaitCursor);
|
||||
@ -9499,7 +9602,7 @@ QgsVectorLayer *QgisApp::addVectorLayer( const QString &vectorLayerPath, const Q
|
||||
messageBar()->pushMessage( tr( "Layer is not valid" ), msg, QgsMessageBar::CRITICAL, messageTimeout() );
|
||||
|
||||
delete layer;
|
||||
mMapCanvas->freeze( false );
|
||||
freezeCanvases( false );
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@ -9507,8 +9610,8 @@ QgsVectorLayer *QgisApp::addVectorLayer( const QString &vectorLayerPath, const Q
|
||||
// Let the caller do it otherwise
|
||||
if ( !wasfrozen )
|
||||
{
|
||||
mMapCanvas->freeze( false );
|
||||
mMapCanvas->refresh();
|
||||
freezeCanvases( false );
|
||||
refreshMapCanvas();
|
||||
}
|
||||
|
||||
// Let render() do its own cursor management
|
||||
@ -9522,7 +9625,7 @@ QgsVectorLayer *QgisApp::addVectorLayer( const QString &vectorLayerPath, const Q
|
||||
|
||||
void QgisApp::addMapLayer( QgsMapLayer *mapLayer )
|
||||
{
|
||||
mMapCanvas->freeze();
|
||||
freezeCanvases();
|
||||
|
||||
// Let render() do its own cursor management
|
||||
// QApplication::setOverrideCursor(Qt::WaitCursor);
|
||||
@ -9543,8 +9646,8 @@ void QgisApp::addMapLayer( QgsMapLayer *mapLayer )
|
||||
}
|
||||
|
||||
// draw the map
|
||||
mMapCanvas->freeze( false );
|
||||
mMapCanvas->refresh();
|
||||
freezeCanvases( false );
|
||||
refreshMapCanvas();
|
||||
|
||||
// Let render() do its own cursor management
|
||||
// QApplication::restoreOverrideCursor();
|
||||
@ -9557,7 +9660,7 @@ void QgisApp::embedLayers()
|
||||
QgsProjectLayerGroupDialog d( this );
|
||||
if ( d.exec() == QDialog::Accepted && d.isValid() )
|
||||
{
|
||||
mMapCanvas->freeze( true );
|
||||
freezeCanvases();
|
||||
|
||||
QString projectFile = d.selectedProjectFile();
|
||||
|
||||
@ -9588,14 +9691,38 @@ void QgisApp::embedLayers()
|
||||
}
|
||||
}
|
||||
|
||||
mMapCanvas->freeze( false );
|
||||
freezeCanvases( false );
|
||||
if ( !groups.isEmpty() || !layerIds.isEmpty() )
|
||||
{
|
||||
mMapCanvas->refresh();
|
||||
refreshMapCanvas();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void QgisApp::newMapCanvas()
|
||||
{
|
||||
int i = 1;
|
||||
|
||||
bool existing = true;
|
||||
QList< QgsMapCanvas * > existingCanvases = mapCanvases();
|
||||
QString name;
|
||||
while ( existing )
|
||||
{
|
||||
name = tr( "Map %1" ).arg( i++ );
|
||||
existing = false;
|
||||
Q_FOREACH ( QgsMapCanvas *canvas, existingCanvases )
|
||||
{
|
||||
if ( canvas->objectName() == name )
|
||||
{
|
||||
existing = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
createNewMapCanvas( name, true );
|
||||
}
|
||||
|
||||
void QgisApp::setExtent( const QgsRectangle &rect )
|
||||
{
|
||||
mMapCanvas->setExtent( rect );
|
||||
@ -9639,7 +9766,7 @@ bool QgisApp::saveDirty()
|
||||
}
|
||||
|
||||
QMessageBox::StandardButton answer( QMessageBox::Discard );
|
||||
mMapCanvas->freeze( true );
|
||||
freezeCanvases();
|
||||
|
||||
//QgsDebugMsg(QString("Layer count is %1").arg(mMapCanvas->layerCount()));
|
||||
//QgsDebugMsg(QString("Project is %1dirty").arg( QgsProject::instance()->isDirty() ? "" : "not "));
|
||||
@ -9669,7 +9796,7 @@ bool QgisApp::saveDirty()
|
||||
}
|
||||
}
|
||||
|
||||
mMapCanvas->freeze( false );
|
||||
freezeCanvases( false );
|
||||
|
||||
return answer != QMessageBox::Cancel;
|
||||
}
|
||||
@ -9715,6 +9842,8 @@ void QgisApp::closeProject()
|
||||
mLegendExpressionFilterButton->setChecked( false );
|
||||
mActionFilterLegend->setChecked( false );
|
||||
|
||||
closeAdditionalMapCanvases();
|
||||
|
||||
deletePrintComposers();
|
||||
removeAnnotationItems();
|
||||
// clear out any stuff from project
|
||||
@ -10433,7 +10562,7 @@ void QgisApp::layersWereAdded( const QList<QgsMapLayer *> &layers )
|
||||
if ( provider )
|
||||
{
|
||||
connect( provider, &QgsDataProvider::dataChanged, layer, [layer] { layer->triggerRepaint(); } );
|
||||
connect( provider, &QgsDataProvider::dataChanged, mMapCanvas, &QgsMapCanvas::refresh );
|
||||
connect( provider, &QgsDataProvider::dataChanged, this, &QgisApp::refreshMapCanvas );
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -10536,11 +10665,6 @@ void QgisApp::projectProperties()
|
||||
&QgsStatusBarScaleWidget::updateScales );
|
||||
QApplication::restoreOverrideCursor();
|
||||
|
||||
//pass any refresh signals off to canvases
|
||||
// Line below was commented out by wonder three years ago (r4949).
|
||||
// It is needed to refresh scale bar after changing display units.
|
||||
connect( pp, SIGNAL( refresh() ), mMapCanvas, SLOT( refresh() ) );
|
||||
|
||||
// Display the modal dialog box.
|
||||
pp->exec();
|
||||
|
||||
@ -10553,7 +10677,7 @@ void QgisApp::projectProperties()
|
||||
|
||||
// delete the property sheet object
|
||||
delete pp;
|
||||
} // QgisApp::projectProperties
|
||||
}
|
||||
|
||||
|
||||
QgsClipboard *QgisApp::clipboard()
|
||||
@ -11068,6 +11192,37 @@ void QgisApp::refreshActionFeatureAction()
|
||||
mActionFeatureAction->setEnabled( layerHasActions );
|
||||
}
|
||||
|
||||
void QgisApp::renameView()
|
||||
{
|
||||
QgsMapCanvasDockWidget *view = qobject_cast< QgsMapCanvasDockWidget * >( sender() );
|
||||
if ( !view )
|
||||
return;
|
||||
|
||||
// calculate existing names
|
||||
QStringList names;
|
||||
Q_FOREACH ( QgsMapCanvas *c, mapCanvases() )
|
||||
{
|
||||
if ( c == view->mapCanvas() )
|
||||
continue;
|
||||
|
||||
names << c->objectName();
|
||||
}
|
||||
|
||||
QString currentName = view->mapCanvas()->objectName();
|
||||
|
||||
QgsNewNameDialog renameDlg( currentName, currentName, QStringList(), names, QRegExp(), Qt::CaseSensitive, this );
|
||||
renameDlg.setWindowTitle( tr( "Map Views" ) );
|
||||
//renameDlg.setHintString( tr( "Name of the new view" ) );
|
||||
renameDlg.setOverwriteEnabled( false );
|
||||
renameDlg.setConflictingNameWarning( tr( "A view with this name already exists" ) );
|
||||
if ( renameDlg.exec() || renameDlg.name().isEmpty() )
|
||||
{
|
||||
QString newName = renameDlg.name();
|
||||
view->setWindowTitle( newName );
|
||||
view->mapCanvas()->setObjectName( newName );
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
//
|
||||
//
|
||||
@ -11143,7 +11298,7 @@ QgsRasterLayer *QgisApp::addRasterLayerPrivate(
|
||||
{
|
||||
// let the user know we're going to possibly be taking a while
|
||||
// QApplication::setOverrideCursor( Qt::WaitCursor );
|
||||
mMapCanvas->freeze( true );
|
||||
freezeCanvases();
|
||||
}
|
||||
|
||||
QgsDebugMsg( "Creating new raster layer using " + uri
|
||||
@ -11200,7 +11355,7 @@ QgsRasterLayer *QgisApp::addRasterLayerPrivate(
|
||||
if ( !ok )
|
||||
{
|
||||
if ( guiUpdate )
|
||||
mMapCanvas->freeze( false );
|
||||
freezeCanvases( false );
|
||||
|
||||
// don't show the gui warning if we are loading from command line
|
||||
if ( guiWarning )
|
||||
@ -11219,8 +11374,8 @@ QgsRasterLayer *QgisApp::addRasterLayerPrivate(
|
||||
if ( guiUpdate )
|
||||
{
|
||||
// draw the map
|
||||
mMapCanvas->freeze( false );
|
||||
mMapCanvas->refresh();
|
||||
freezeCanvases( false );
|
||||
refreshMapCanvas();
|
||||
// Let render() do its own cursor management
|
||||
// QApplication::restoreOverrideCursor();
|
||||
}
|
||||
@ -11262,11 +11417,11 @@ bool QgisApp::addRasterLayers( QStringList const &fileNameQStringList, bool guiW
|
||||
// no files selected so bail out, but
|
||||
// allow mMapCanvas to handle events
|
||||
// first
|
||||
mMapCanvas->freeze( false );
|
||||
freezeCanvases( false );;
|
||||
return false;
|
||||
}
|
||||
|
||||
mMapCanvas->freeze( true );
|
||||
freezeCanvases();
|
||||
|
||||
// this is messy since some files in the list may be rasters and others may
|
||||
// be ogr layers. We'll set returnValue to false if one or more layers fail
|
||||
@ -11331,8 +11486,8 @@ bool QgisApp::addRasterLayers( QStringList const &fileNameQStringList, bool guiW
|
||||
}
|
||||
}
|
||||
|
||||
mMapCanvas->freeze( false );
|
||||
mMapCanvas->refresh();
|
||||
freezeCanvases( false );
|
||||
refreshMapCanvas();
|
||||
|
||||
// Let render() do its own cursor management
|
||||
// QApplication::restoreOverrideCursor();
|
||||
@ -11593,10 +11748,30 @@ void QgisApp::writeProject( QDomDocument &doc )
|
||||
QDomElement oldLegendElem = QgsLayerTreeUtils::writeOldLegend( doc, QgsLayerTree::toGroup( clonedRoot ),
|
||||
mLayerTreeCanvasBridge->hasCustomLayerOrder(), mLayerTreeCanvasBridge->customLayerOrder() );
|
||||
delete clonedRoot;
|
||||
doc.firstChildElement( QStringLiteral( "qgis" ) ).appendChild( oldLegendElem );
|
||||
QDomElement qgisNode = doc.firstChildElement( QStringLiteral( "qgis" ) );
|
||||
qgisNode.appendChild( oldLegendElem );
|
||||
|
||||
QgsProject::instance()->writeEntry( QStringLiteral( "Legend" ), QStringLiteral( "filterByMap" ), static_cast< bool >( layerTreeView()->layerTreeModel()->legendFilterMapSettings() ) );
|
||||
|
||||
// Save the position of the map view docks
|
||||
QDomElement mapViewNode = doc.createElement( QStringLiteral( "mapViewDocks" ) );
|
||||
Q_FOREACH ( QgsMapCanvasDockWidget *w, findChildren< QgsMapCanvasDockWidget * >() )
|
||||
{
|
||||
QDomElement node = doc.createElement( QStringLiteral( "view" ) );
|
||||
node.setAttribute( QStringLiteral( "name" ), w->mapCanvas()->objectName() );
|
||||
node.setAttribute( QStringLiteral( "x" ), w->x() );
|
||||
node.setAttribute( QStringLiteral( "y" ), w->y() );
|
||||
node.setAttribute( QStringLiteral( "width" ), w->width() );
|
||||
node.setAttribute( QStringLiteral( "height" ), w->height() );
|
||||
node.setAttribute( QStringLiteral( "floating" ), w->isFloating() );
|
||||
node.setAttribute( QStringLiteral( "synced" ), w->isViewCenterSynchronized() );
|
||||
node.setAttribute( QStringLiteral( "showCursor" ), w->isCursorMarkerVisible() );
|
||||
node.setAttribute( QStringLiteral( "scaleSynced" ), w->isViewScaleSynchronized() );
|
||||
node.setAttribute( QStringLiteral( "scaleFactor" ), w->scaleFactor() );
|
||||
mapViewNode.appendChild( node );
|
||||
}
|
||||
qgisNode.appendChild( mapViewNode );
|
||||
|
||||
projectChanged( doc );
|
||||
}
|
||||
|
||||
@ -11612,6 +11787,30 @@ void QgisApp::readProject( const QDomDocument &doc )
|
||||
|
||||
if ( autoSetupOnFirstLayer )
|
||||
mLayerTreeCanvasBridge->setAutoSetupOnFirstLayer( true );
|
||||
|
||||
QDomNodeList nodes = doc.elementsByTagName( QStringLiteral( "mapViewDocks" ) );
|
||||
if ( !nodes.isEmpty() )
|
||||
{
|
||||
QDomNode viewNode = nodes.at( 0 );
|
||||
nodes = viewNode.childNodes();
|
||||
for ( int i = 0; i < nodes.size(); ++i )
|
||||
{
|
||||
QDomElement elementNode = nodes.at( i ).toElement();
|
||||
QString mapName = elementNode.attribute( QStringLiteral( "name" ) );
|
||||
int x = elementNode.attribute( QStringLiteral( "x" ), QStringLiteral( "0" ) ).toInt();
|
||||
int y = elementNode.attribute( QStringLiteral( "y" ), QStringLiteral( "0" ) ).toInt();
|
||||
int w = elementNode.attribute( QStringLiteral( "width" ), QStringLiteral( "400" ) ).toInt();
|
||||
int h = elementNode.attribute( QStringLiteral( "height" ), QStringLiteral( "400" ) ).toInt();
|
||||
bool floating = elementNode.attribute( QStringLiteral( "floating" ), QStringLiteral( "0" ) ).toInt();
|
||||
bool synced = elementNode.attribute( QStringLiteral( "synced" ), QStringLiteral( "0" ) ).toInt();
|
||||
bool showCursor = elementNode.attribute( QStringLiteral( "showCursor" ), QStringLiteral( "0" ) ).toInt();
|
||||
bool scaleSynced = elementNode.attribute( QStringLiteral( "scaleSynced" ), QStringLiteral( "0" ) ).toInt();
|
||||
double scaleFactor = elementNode.attribute( QStringLiteral( "scaleFactor" ), QStringLiteral( "1" ) ).toDouble();
|
||||
|
||||
QgsMapCanvas *mapCanvas = createNewMapCanvas( mapName, floating, QRect( x, y, w, h ), synced, showCursor, scaleSynced, scaleFactor );
|
||||
mapCanvas->readProject( doc );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void QgisApp::showLayerProperties( QgsMapLayer *ml )
|
||||
|
@ -231,6 +231,36 @@ class APP_EXPORT QgisApp : public QMainWindow, private Ui::MainWindow
|
||||
//! Get the mapcanvas object from the app
|
||||
QgsMapCanvas *mapCanvas();
|
||||
|
||||
/**
|
||||
* Returns a list of all map canvases open in the app.
|
||||
*/
|
||||
QList< QgsMapCanvas * > mapCanvases();
|
||||
|
||||
/**
|
||||
* Create a new map canvas with the specified unique \a name. The \a isFloating
|
||||
* and \a dockGeometry arguments can be used to specify an initial floating state
|
||||
* and widget geometry rect for the dock.
|
||||
*/
|
||||
QgsMapCanvas *createNewMapCanvas( const QString &name, bool isFloating = false, const QRect &dockGeometry = QRect(),
|
||||
bool synced = false, bool showCursor = true, bool scaleSynced = false,
|
||||
double scaleFactor = 1.0 );
|
||||
|
||||
/**
|
||||
* Closes the additional map canvas with matching \a name.
|
||||
*/
|
||||
void closeMapCanvas( const QString &name );
|
||||
|
||||
/**
|
||||
* Closes any additional map canvases. The main map canvas will not
|
||||
* be affected.
|
||||
*/
|
||||
void closeAdditionalMapCanvases();
|
||||
|
||||
/**
|
||||
* Freezes all map canvases (or thaws them if the \a frozen argument is false).
|
||||
*/
|
||||
void freezeCanvases( bool frozen = true );
|
||||
|
||||
//! Return the messageBar object which allows displaying unobtrusive messages to the user.
|
||||
QgsMessageBar *messageBar();
|
||||
|
||||
@ -736,6 +766,8 @@ class APP_EXPORT QgisApp : public QMainWindow, private Ui::MainWindow
|
||||
|
||||
QMenu *panelMenu() { return mPanelMenu; }
|
||||
|
||||
void renameView();
|
||||
|
||||
protected:
|
||||
|
||||
//! Handle state changes (WindowTitleChange)
|
||||
@ -1024,6 +1056,9 @@ class APP_EXPORT QgisApp : public QMainWindow, private Ui::MainWindow
|
||||
void showAlignRasterTool();
|
||||
void embedLayers();
|
||||
|
||||
//! Creates a new map canvas view
|
||||
void newMapCanvas();
|
||||
|
||||
//! Create a new empty vector layer
|
||||
void newVectorLayer();
|
||||
//! Create a new memory layer
|
||||
@ -1514,6 +1549,7 @@ class APP_EXPORT QgisApp : public QMainWindow, private Ui::MainWindow
|
||||
|
||||
//! Returns all annotation items in the canvas
|
||||
QList<QgsMapCanvasAnnotationItem *> annotationItems();
|
||||
|
||||
//! Removes annotation items in the canvas
|
||||
void removeAnnotationItems();
|
||||
|
||||
@ -1551,6 +1587,11 @@ class APP_EXPORT QgisApp : public QMainWindow, private Ui::MainWindow
|
||||
*/
|
||||
void applyProjectSettingsToCanvas( QgsMapCanvas *canvas );
|
||||
|
||||
/**
|
||||
* Applies global qgis settings to the specified canvas
|
||||
*/
|
||||
void applyDefaultSettingsToCanvas( QgsMapCanvas *canvas );
|
||||
|
||||
QgisAppStyleSheet *mStyleSheetBuilder = nullptr;
|
||||
|
||||
// actions for menus and toolbars -----------------
|
||||
@ -1754,6 +1795,7 @@ class APP_EXPORT QgisApp : public QMainWindow, private Ui::MainWindow
|
||||
QSplashScreen *mSplash = nullptr;
|
||||
//! list of recently opened/saved project files
|
||||
QList<QgsWelcomePageItemsModel::RecentProjectData> mRecentProjects;
|
||||
|
||||
//! Print composers of this project, accessible by id string
|
||||
QSet<QgsComposer *> mPrintComposers;
|
||||
//! QGIS-internal vector feature clipboard
|
||||
|
@ -331,6 +331,21 @@ QgsMapCanvas *QgisAppInterface::mapCanvas()
|
||||
return qgis->mapCanvas();
|
||||
}
|
||||
|
||||
QList<QgsMapCanvas *> QgisAppInterface::mapCanvases()
|
||||
{
|
||||
return qgis->mapCanvases();
|
||||
}
|
||||
|
||||
QgsMapCanvas *QgisAppInterface::createNewMapCanvas( const QString &name )
|
||||
{
|
||||
return qgis->createNewMapCanvas( name );
|
||||
}
|
||||
|
||||
void QgisAppInterface::closeMapCanvas( const QString &name )
|
||||
{
|
||||
qgis->closeMapCanvas( name );
|
||||
}
|
||||
|
||||
QgsLayerTreeMapCanvasBridge *QgisAppInterface::layerTreeCanvasBridge()
|
||||
{
|
||||
return qgis->layerTreeCanvasBridge();
|
||||
|
@ -179,6 +179,10 @@ class APP_EXPORT QgisAppInterface : public QgisInterface
|
||||
//! Return a pointer to the map canvas used by qgisapp
|
||||
QgsMapCanvas *mapCanvas() override;
|
||||
|
||||
QList< QgsMapCanvas * > mapCanvases() override;
|
||||
QgsMapCanvas *createNewMapCanvas( const QString &name ) override;
|
||||
virtual void closeMapCanvas( const QString &name ) override;
|
||||
|
||||
/**
|
||||
* Returns a pointer to the layer tree canvas bridge
|
||||
*
|
||||
|
@ -130,7 +130,7 @@ bool QgsGuiVectorLayerTools::stopEditing( QgsVectorLayer *layer, bool allowCance
|
||||
break;
|
||||
|
||||
case QMessageBox::Discard:
|
||||
QgisApp::instance()->mapCanvas()->freeze( true );
|
||||
QgisApp::instance()->freezeCanvases();
|
||||
if ( !layer->rollBack() )
|
||||
{
|
||||
QgisApp::instance()->messageBar()->pushMessage( tr( "Error" ),
|
||||
@ -138,7 +138,7 @@ bool QgsGuiVectorLayerTools::stopEditing( QgsVectorLayer *layer, bool allowCance
|
||||
QgsMessageBar::CRITICAL );
|
||||
res = false;
|
||||
}
|
||||
QgisApp::instance()->mapCanvas()->freeze( false );
|
||||
QgisApp::instance()->freezeCanvases( false );
|
||||
|
||||
layer->triggerRepaint();
|
||||
break;
|
||||
@ -149,9 +149,9 @@ bool QgsGuiVectorLayerTools::stopEditing( QgsVectorLayer *layer, bool allowCance
|
||||
}
|
||||
else //layer not modified
|
||||
{
|
||||
QgisApp::instance()->mapCanvas()->freeze( true );
|
||||
QgisApp::instance()->freezeCanvases( true );
|
||||
layer->rollBack();
|
||||
QgisApp::instance()->mapCanvas()->freeze( false );
|
||||
QgisApp::instance()->freezeCanvases( false );
|
||||
res = true;
|
||||
layer->triggerRepaint();
|
||||
}
|
||||
|
464
src/app/qgsmapcanvasdockwidget.cpp
Normal file
464
src/app/qgsmapcanvasdockwidget.cpp
Normal file
@ -0,0 +1,464 @@
|
||||
/***************************************************************************
|
||||
qgsmapcanvasdockwidget.cpp
|
||||
--------------------------
|
||||
begin : February 2017
|
||||
copyright : (C) 2017 by Nyall Dawson
|
||||
email : nyall dot dawson at gmail dot com
|
||||
***************************************************************************
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
#include "qgsmapcanvasdockwidget.h"
|
||||
#include "qgsmapcanvas.h"
|
||||
#include "qgscsexception.h"
|
||||
#include "qgsprojectionselectiondialog.h"
|
||||
#include "qgsscalecombobox.h"
|
||||
#include "qgsdoublespinbox.h"
|
||||
#include "qgssettings.h"
|
||||
#include "qgsmaptoolpan.h"
|
||||
#include "qgsmapthemecollection.h"
|
||||
#include "qgsproject.h"
|
||||
#include "qgsmapthemes.h"
|
||||
#include "qgslayertreeview.h"
|
||||
#include "qgslayertreeviewdefaultactions.h"
|
||||
#include "qgisapp.h"
|
||||
#include "qgsvertexmarker.h"
|
||||
#include <QMessageBox>
|
||||
#include <QMenu>
|
||||
#include <QToolBar>
|
||||
#include <QToolButton>
|
||||
|
||||
QgsMapCanvasDockWidget::QgsMapCanvasDockWidget( const QString &name, QWidget *parent )
|
||||
: QgsDockWidget( parent )
|
||||
{
|
||||
setupUi( this );
|
||||
setAttribute( Qt::WA_DeleteOnClose );
|
||||
|
||||
mContents->layout()->setContentsMargins( 0, 0, 0, 0 );
|
||||
mContents->layout()->setMargin( 0 );
|
||||
static_cast< QVBoxLayout * >( mContents->layout() )->setSpacing( 0 );
|
||||
|
||||
setWindowTitle( name );
|
||||
mMapCanvas = new QgsMapCanvas( this );
|
||||
mXyMarker = new QgsVertexMarker( mMapCanvas );
|
||||
mXyMarker->setIconType( QgsVertexMarker::ICON_CIRCLE );
|
||||
mXyMarker->setIconSize( 6 );
|
||||
mXyMarker->setColor( QColor( 30, 30, 30, 225 ) );
|
||||
mPanTool = new QgsMapToolPan( mMapCanvas );
|
||||
mMapCanvas->setMapTool( mPanTool );
|
||||
|
||||
mMainWidget->setLayout( new QVBoxLayout() );
|
||||
mMainWidget->layout()->setContentsMargins( 0, 0, 0, 0 );
|
||||
mMainWidget->layout()->setMargin( 0 );
|
||||
|
||||
mMainWidget->layout()->addWidget( mMapCanvas );
|
||||
|
||||
connect( mActionSyncView, &QAction::toggled, this, [ = ]
|
||||
{
|
||||
syncViewCenter( mMainCanvas );
|
||||
} );
|
||||
|
||||
mMenu = new QMenu();
|
||||
connect( mMenu, &QMenu::aboutToShow, this, &QgsMapCanvasDockWidget::menuAboutToShow );
|
||||
|
||||
QToolButton *btnMapThemes = new QToolButton;
|
||||
btnMapThemes->setAutoRaise( true );
|
||||
btnMapThemes->setToolTip( tr( "Set View Theme" ) );
|
||||
btnMapThemes->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionShowAllLayers.svg" ) ) );
|
||||
btnMapThemes->setPopupMode( QToolButton::InstantPopup );
|
||||
btnMapThemes->setMenu( mMenu );
|
||||
mToolbar->addWidget( btnMapThemes );
|
||||
|
||||
QMenu *settingsMenu = new QMenu();
|
||||
QToolButton *settingsButton = new QToolButton();
|
||||
settingsButton->setAutoRaise( true );
|
||||
settingsButton->setToolTip( tr( "View Settings" ) );
|
||||
settingsButton->setMenu( settingsMenu );
|
||||
settingsButton->setPopupMode( QToolButton::InstantPopup );
|
||||
settingsButton->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionMapSettings.svg" ) ) );
|
||||
mToolbar->addWidget( settingsButton );
|
||||
|
||||
connect( mActionSetCrs, &QAction::triggered, this, &QgsMapCanvasDockWidget::setMapCrs );
|
||||
connect( mMapCanvas, &QgsMapCanvas::destinationCrsChanged, this, &QgsMapCanvasDockWidget::mapCrsChanged );
|
||||
connect( mActionZoomFullExtent, &QAction::triggered, mMapCanvas, &QgsMapCanvas::zoomToFullExtent );
|
||||
connect( mActionZoomToLayer, &QAction::triggered, mMapCanvas, [ = ] { QgisApp::instance()->layerTreeView()->defaultActions()->zoomToLayer( mMapCanvas ); } );
|
||||
connect( mActionZoomToSelected, &QAction::triggered, mMapCanvas, [ = ] { mMapCanvas->zoomToSelected(); } );
|
||||
mapCrsChanged();
|
||||
|
||||
QgsMapSettingsAction *settingsAction = new QgsMapSettingsAction( settingsMenu );
|
||||
settingsMenu->addAction( settingsAction );
|
||||
|
||||
settingsMenu->addSeparator();
|
||||
settingsMenu->addAction( mActionSetCrs );
|
||||
settingsMenu->addAction( mActionShowAnnotations );
|
||||
settingsMenu->addAction( mActionShowCursor );
|
||||
settingsMenu->addAction( mActionRename );
|
||||
|
||||
connect( settingsMenu, &QMenu::aboutToShow, this, &QgsMapCanvasDockWidget::settingsMenuAboutToShow );
|
||||
|
||||
connect( mActionRename, &QAction::triggered, this, &QgsMapCanvasDockWidget::renameTriggered );
|
||||
mActionShowAnnotations->setChecked( mMapCanvas->annotationsVisible() );
|
||||
connect( mActionShowAnnotations, &QAction::toggled, this, [ = ]( bool checked ) { mMapCanvas->setAnnotationsVisible( checked ); } );
|
||||
mActionShowCursor->setChecked( true );
|
||||
connect( mActionShowCursor, &QAction::toggled, this, [ = ]( bool checked ) { mXyMarker->setVisible( checked ); } );
|
||||
|
||||
mScaleCombo = settingsAction->scaleCombo();
|
||||
mRotationEdit = settingsAction->rotationSpinBox();
|
||||
mMagnificationEdit = settingsAction->magnifierSpinBox();
|
||||
mSyncScaleCheckBox = settingsAction->syncScaleCheckBox();
|
||||
mScaleFactorWidget = settingsAction->scaleFactorSpinBox();
|
||||
|
||||
connect( mScaleCombo, &QgsScaleComboBox::scaleChanged, this, [ = ]( double scale )
|
||||
{
|
||||
if ( !mBlockScaleUpdate )
|
||||
{
|
||||
mBlockScaleUpdate = true;
|
||||
mMapCanvas->zoomScale( 1.0 / scale );
|
||||
mBlockScaleUpdate = false;
|
||||
}
|
||||
} );
|
||||
connect( mMapCanvas, &QgsMapCanvas::scaleChanged, this, [ = ]( double scale )
|
||||
{
|
||||
if ( !mBlockScaleUpdate )
|
||||
{
|
||||
mBlockScaleUpdate = true;
|
||||
mScaleCombo->setScale( 1.0 / scale );
|
||||
mBlockScaleUpdate = false;
|
||||
}
|
||||
} );
|
||||
|
||||
connect( mRotationEdit, static_cast < void ( QgsDoubleSpinBox::* )( double ) > ( &QgsDoubleSpinBox::valueChanged ), this, [ = ]( double value )
|
||||
{
|
||||
if ( !mBlockRotationUpdate )
|
||||
{
|
||||
mBlockRotationUpdate = true;
|
||||
mMapCanvas->setRotation( value );
|
||||
mMapCanvas->refresh();
|
||||
mBlockRotationUpdate = false;
|
||||
}
|
||||
} );
|
||||
|
||||
connect( mMapCanvas, &QgsMapCanvas::rotationChanged, this, [ = ]( double rotation )
|
||||
{
|
||||
if ( !mBlockRotationUpdate )
|
||||
{
|
||||
mBlockRotationUpdate = true;
|
||||
mRotationEdit->setValue( rotation );
|
||||
mBlockRotationUpdate = false;
|
||||
}
|
||||
} );
|
||||
|
||||
connect( mMagnificationEdit, static_cast < void ( QgsDoubleSpinBox::* )( double ) > ( &QgsDoubleSpinBox::valueChanged ), this, [ = ]( double value )
|
||||
{
|
||||
if ( !mBlockMagnificationUpdate )
|
||||
{
|
||||
mBlockMagnificationUpdate = true;
|
||||
mMapCanvas->setMagnificationFactor( value / 100 );
|
||||
mMapCanvas->refresh();
|
||||
mBlockMagnificationUpdate = false;
|
||||
}
|
||||
} );
|
||||
|
||||
connect( mMapCanvas, &QgsMapCanvas::magnificationChanged, this, [ = ]( double factor )
|
||||
{
|
||||
if ( !mBlockMagnificationUpdate )
|
||||
{
|
||||
mBlockMagnificationUpdate = true;
|
||||
mMagnificationEdit->setValue( factor * 100 );
|
||||
mBlockMagnificationUpdate = false;
|
||||
}
|
||||
} );
|
||||
|
||||
connect( mScaleFactorWidget, static_cast < void ( QgsDoubleSpinBox::* )( double ) > ( &QgsDoubleSpinBox::valueChanged ), this, &QgsMapCanvasDockWidget::mapScaleChanged );
|
||||
connect( mSyncScaleCheckBox, &QCheckBox::toggled, this, [ = ]( bool checked )
|
||||
{
|
||||
if ( checked )
|
||||
mapScaleChanged();
|
||||
}
|
||||
);
|
||||
|
||||
mResizeTimer.setSingleShot( true );
|
||||
connect( &mResizeTimer, &QTimer::timeout, this, [ = ]
|
||||
{
|
||||
mBlockExtentSync = false;
|
||||
syncViewCenter( mMainCanvas );
|
||||
} );
|
||||
}
|
||||
|
||||
void QgsMapCanvasDockWidget::setMainCanvas( QgsMapCanvas *canvas )
|
||||
{
|
||||
if ( mMainCanvas )
|
||||
{
|
||||
disconnect( mMainCanvas, &QgsMapCanvas::xyCoordinates, this, &QgsMapCanvasDockWidget::syncMarker );
|
||||
disconnect( mMainCanvas, &QgsMapCanvas::scaleChanged, this, &QgsMapCanvasDockWidget::mapScaleChanged );
|
||||
disconnect( mMainCanvas, &QgsMapCanvas::extentsChanged, this, &QgsMapCanvasDockWidget::mapExtentChanged );
|
||||
}
|
||||
|
||||
mMainCanvas = canvas;
|
||||
connect( mMainCanvas, &QgsMapCanvas::xyCoordinates, this, &QgsMapCanvasDockWidget::syncMarker );
|
||||
connect( mMainCanvas, &QgsMapCanvas::scaleChanged, this, &QgsMapCanvasDockWidget::mapScaleChanged );
|
||||
connect( mMainCanvas, &QgsMapCanvas::extentsChanged, this, &QgsMapCanvasDockWidget::mapExtentChanged );
|
||||
connect( mMapCanvas, &QgsMapCanvas::extentsChanged, this, &QgsMapCanvasDockWidget::mapExtentChanged, Qt::UniqueConnection );
|
||||
}
|
||||
|
||||
QgsMapCanvas *QgsMapCanvasDockWidget::mapCanvas()
|
||||
{
|
||||
return mMapCanvas;
|
||||
}
|
||||
|
||||
void QgsMapCanvasDockWidget::setViewCenterSynchronized( bool enabled )
|
||||
{
|
||||
mActionSyncView->setChecked( enabled );
|
||||
}
|
||||
|
||||
bool QgsMapCanvasDockWidget::isViewCenterSynchronized() const
|
||||
{
|
||||
return mActionSyncView->isChecked();
|
||||
}
|
||||
|
||||
void QgsMapCanvasDockWidget::setCursorMarkerVisible( bool visible )
|
||||
{
|
||||
mActionShowCursor->setChecked( visible );
|
||||
}
|
||||
|
||||
bool QgsMapCanvasDockWidget::isCursorMarkerVisible() const
|
||||
{
|
||||
return mXyMarker->isVisible();
|
||||
}
|
||||
|
||||
void QgsMapCanvasDockWidget::setScaleFactor( double factor )
|
||||
{
|
||||
mScaleFactorWidget->setValue( factor );
|
||||
}
|
||||
|
||||
void QgsMapCanvasDockWidget::setViewScaleSynchronized( bool enabled )
|
||||
{
|
||||
mSyncScaleCheckBox->setChecked( enabled );
|
||||
}
|
||||
|
||||
bool QgsMapCanvasDockWidget::isViewScaleSynchronized() const
|
||||
{
|
||||
return mSyncScaleCheckBox->isChecked();
|
||||
}
|
||||
|
||||
double QgsMapCanvasDockWidget::scaleFactor() const
|
||||
{
|
||||
return mScaleFactorWidget->value();
|
||||
}
|
||||
|
||||
void QgsMapCanvasDockWidget::resizeEvent( QResizeEvent * )
|
||||
{
|
||||
mBlockExtentSync = true;
|
||||
mResizeTimer.start( 500 );
|
||||
}
|
||||
|
||||
void QgsMapCanvasDockWidget::setMapCrs()
|
||||
{
|
||||
QgsProjectionSelectionDialog dlg;
|
||||
dlg.setShowNoProjection( true );
|
||||
dlg.setCrs( mMapCanvas->mapSettings().destinationCrs() );
|
||||
|
||||
if ( dlg.exec() )
|
||||
{
|
||||
mMapCanvas->setDestinationCrs( dlg.crs() );
|
||||
}
|
||||
}
|
||||
|
||||
void QgsMapCanvasDockWidget::syncViewCenter( QgsMapCanvas *sourceCanvas )
|
||||
{
|
||||
// avoid infinite recursion
|
||||
mBlockExtentSync = true;
|
||||
|
||||
QgsMapCanvas *destCanvas = sourceCanvas == mMapCanvas ? mMainCanvas : mMapCanvas;
|
||||
|
||||
// reproject extent
|
||||
QgsCoordinateTransform ct( sourceCanvas->mapSettings().destinationCrs(),
|
||||
destCanvas->mapSettings().destinationCrs() );
|
||||
try
|
||||
{
|
||||
destCanvas->setCenter( ct.transform( sourceCanvas->center() ) );
|
||||
}
|
||||
catch ( QgsCsException & )
|
||||
{
|
||||
destCanvas->setCenter( sourceCanvas->center() );
|
||||
}
|
||||
destCanvas->refresh();
|
||||
|
||||
mBlockExtentSync = false;
|
||||
}
|
||||
|
||||
void QgsMapCanvasDockWidget::mapExtentChanged()
|
||||
{
|
||||
if ( mBlockExtentSync )
|
||||
return;
|
||||
|
||||
QgsMapCanvas *sourceCanvas = qobject_cast< QgsMapCanvas * >( sender() );
|
||||
if ( !sourceCanvas )
|
||||
return;
|
||||
|
||||
if ( sourceCanvas == mMapCanvas && mSyncScaleCheckBox->isChecked() )
|
||||
{
|
||||
double newScaleFactor = mMainCanvas->scale() / mMapCanvas->scale();
|
||||
mScaleFactorWidget->setValue( newScaleFactor );
|
||||
}
|
||||
|
||||
if ( mActionSyncView->isChecked() )
|
||||
syncViewCenter( sourceCanvas );
|
||||
}
|
||||
|
||||
void QgsMapCanvasDockWidget::mapCrsChanged()
|
||||
{
|
||||
mActionSetCrs->setText( tr( "Change Map CRS (%1)…" ).arg( mMapCanvas->mapSettings().destinationCrs().isValid() ?
|
||||
mMapCanvas->mapSettings().destinationCrs().authid() :
|
||||
tr( "No projection" ) ) );
|
||||
}
|
||||
|
||||
void QgsMapCanvasDockWidget::menuAboutToShow()
|
||||
{
|
||||
qDeleteAll( mMenuPresetActions );
|
||||
mMenuPresetActions.clear();
|
||||
|
||||
QString currentTheme = mMapCanvas->theme();
|
||||
|
||||
QAction *actionFollowMain = new QAction( tr( "(default)" ), mMenu );
|
||||
actionFollowMain->setCheckable( true );
|
||||
if ( currentTheme.isEmpty() || !QgsProject::instance()->mapThemeCollection()->hasMapTheme( currentTheme ) )
|
||||
{
|
||||
actionFollowMain->setChecked( true );
|
||||
}
|
||||
connect( actionFollowMain, &QAction::triggered, this, [ = ]
|
||||
{
|
||||
mMapCanvas->setTheme( QString() );
|
||||
mMapCanvas->refresh();
|
||||
} );
|
||||
mMenuPresetActions.append( actionFollowMain );
|
||||
|
||||
Q_FOREACH ( const QString &grpName, QgsProject::instance()->mapThemeCollection()->mapThemes() )
|
||||
{
|
||||
QAction *a = new QAction( grpName, mMenu );
|
||||
a->setCheckable( true );
|
||||
if ( grpName == currentTheme )
|
||||
{
|
||||
a->setChecked( true );
|
||||
}
|
||||
connect( a, &QAction::triggered, this, [a, this]
|
||||
{
|
||||
mMapCanvas->setTheme( a->text() );
|
||||
mMapCanvas->refresh();
|
||||
} );
|
||||
mMenuPresetActions.append( a );
|
||||
}
|
||||
mMenu->addActions( mMenuPresetActions );
|
||||
}
|
||||
|
||||
void QgsMapCanvasDockWidget::settingsMenuAboutToShow()
|
||||
{
|
||||
whileBlocking( mActionShowAnnotations )->setChecked( mMapCanvas->annotationsVisible() );
|
||||
}
|
||||
|
||||
void QgsMapCanvasDockWidget::syncMarker( const QgsPoint &p )
|
||||
{
|
||||
if ( !mXyMarker->isVisible() )
|
||||
return;
|
||||
|
||||
// reproject point
|
||||
QgsCoordinateTransform ct( mMainCanvas->mapSettings().destinationCrs(),
|
||||
mMapCanvas->mapSettings().destinationCrs() );
|
||||
QgsPoint t = p;
|
||||
try
|
||||
{
|
||||
t = ct.transform( p );
|
||||
}
|
||||
catch ( QgsCsException & )
|
||||
{}
|
||||
|
||||
mXyMarker->setCenter( t );
|
||||
}
|
||||
|
||||
void QgsMapCanvasDockWidget::mapScaleChanged()
|
||||
{
|
||||
if ( !mSyncScaleCheckBox->isChecked() )
|
||||
return;
|
||||
|
||||
double newScale = mMainCanvas->scale() / mScaleFactorWidget->value();
|
||||
bool prev = mBlockExtentSync;
|
||||
mBlockExtentSync = true;
|
||||
mMapCanvas->zoomScale( newScale );
|
||||
mBlockExtentSync = prev;
|
||||
}
|
||||
|
||||
QgsMapSettingsAction::QgsMapSettingsAction( QWidget *parent )
|
||||
: QWidgetAction( parent )
|
||||
{
|
||||
QGridLayout *gLayout = new QGridLayout();
|
||||
gLayout->setContentsMargins( 3, 2, 3, 2 );
|
||||
QLabel *label = new QLabel( tr( "Scale" ) );
|
||||
gLayout->addWidget( label, 0, 0 );
|
||||
|
||||
mScaleCombo = new QgsScaleComboBox();
|
||||
gLayout->addWidget( mScaleCombo, 0, 1 );
|
||||
|
||||
mRotationWidget = new QgsDoubleSpinBox();
|
||||
mRotationWidget->setClearValue( 0.0 );
|
||||
mRotationWidget->setKeyboardTracking( false );
|
||||
mRotationWidget->setMaximumWidth( 120 );
|
||||
mRotationWidget->setDecimals( 1 );
|
||||
mRotationWidget->setRange( -180.0, 180.0 );
|
||||
mRotationWidget->setWrapping( true );
|
||||
mRotationWidget->setSingleStep( 5.0 );
|
||||
mRotationWidget->setToolTip( tr( "Current clockwise map rotation in degrees" ) );
|
||||
|
||||
label = new QLabel( tr( "Rotation" ) );
|
||||
gLayout->addWidget( label, 1, 0 );
|
||||
gLayout->addWidget( mRotationWidget, 1, 1 );
|
||||
|
||||
QgsSettings settings;
|
||||
int minimumFactor = 100 * QgisGui::CANVAS_MAGNIFICATION_MIN;
|
||||
int maximumFactor = 100 * QgisGui::CANVAS_MAGNIFICATION_MAX;
|
||||
int defaultFactor = 100 * settings.value( QStringLiteral( "/qgis/magnifier_factor_default" ), 1.0 ).toDouble();
|
||||
|
||||
mMagnifierWidget = new QgsDoubleSpinBox();
|
||||
mMagnifierWidget->setSuffix( QStringLiteral( "%" ) );
|
||||
mMagnifierWidget->setKeyboardTracking( false );
|
||||
mMagnifierWidget->setDecimals( 0 );
|
||||
mMagnifierWidget->setRange( minimumFactor, maximumFactor );
|
||||
mMagnifierWidget->setWrapping( false );
|
||||
mMagnifierWidget->setSingleStep( 50 );
|
||||
mMagnifierWidget->setToolTip( tr( "Magnifier level" ) );
|
||||
mMagnifierWidget->setClearValueMode( QgsDoubleSpinBox::CustomValue );
|
||||
mMagnifierWidget->setClearValue( defaultFactor );
|
||||
mMagnifierWidget->setValue( defaultFactor );
|
||||
|
||||
label = new QLabel( tr( "Magnification" ) );
|
||||
gLayout->addWidget( label, 2, 0 );
|
||||
gLayout->addWidget( mMagnifierWidget, 2, 1 );
|
||||
|
||||
mSyncScaleCheckBox = new QCheckBox( tr( "Synchronize scale" ) );
|
||||
gLayout->addWidget( mSyncScaleCheckBox, 3, 0, 1, 2 );
|
||||
|
||||
mScaleFactorWidget = new QgsDoubleSpinBox();
|
||||
mScaleFactorWidget->setSuffix( QStringLiteral( "×" ) );
|
||||
mScaleFactorWidget->setDecimals( 2 );
|
||||
mScaleFactorWidget->setRange( 0.01, 100000 );
|
||||
mScaleFactorWidget->setWrapping( false );
|
||||
mScaleFactorWidget->setSingleStep( 0.1 );
|
||||
mScaleFactorWidget->setToolTip( tr( "Multiplication factor for main canvas scale to view scale" ) );
|
||||
mScaleFactorWidget->setClearValueMode( QgsDoubleSpinBox::CustomValue );
|
||||
mScaleFactorWidget->setClearValue( 1.0 );
|
||||
mScaleFactorWidget->setValue( 1.0 );
|
||||
mScaleFactorWidget->setEnabled( false );
|
||||
|
||||
connect( mSyncScaleCheckBox, &QCheckBox::toggled, mScaleFactorWidget, &QgsDoubleSpinBox::setEnabled );
|
||||
|
||||
label = new QLabel( tr( "Scale factor" ) );
|
||||
gLayout->addWidget( label, 4, 0 );
|
||||
gLayout->addWidget( mScaleFactorWidget, 4, 1 );
|
||||
|
||||
QWidget *w = new QWidget();
|
||||
w->setLayout( gLayout );
|
||||
setDefaultWidget( w );
|
||||
}
|
176
src/app/qgsmapcanvasdockwidget.h
Normal file
176
src/app/qgsmapcanvasdockwidget.h
Normal file
@ -0,0 +1,176 @@
|
||||
/***************************************************************************
|
||||
qgsmapcanvasdockwidget.h
|
||||
------------------------
|
||||
begin : February 2017
|
||||
copyright : (C) 2017 by Nyall Dawson
|
||||
email : nyall dot dawson at gmail dot com
|
||||
***************************************************************************
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
#ifndef QGSMAPCANVASDOCKWIDGET_H
|
||||
#define QGSMAPCANVASDOCKWIDGET_H
|
||||
|
||||
#include <ui_qgsmapcanvasdockwidgetbase.h>
|
||||
|
||||
#include "qgsdockwidget.h"
|
||||
#include "qgspoint.h"
|
||||
#include "qgis_app.h"
|
||||
#include <QWidgetAction>
|
||||
#include <QTimer>
|
||||
#include <memory>
|
||||
|
||||
class QgsMapCanvas;
|
||||
class QgsScaleComboBox;
|
||||
class QgsDoubleSpinBox;
|
||||
class QgsStatusBarMagnifierWidget;
|
||||
class QgsMapToolPan;
|
||||
class QgsVertexMarker;
|
||||
class QCheckBox;
|
||||
|
||||
/**
|
||||
* \class QgsMapCanvasDockWidget
|
||||
* A dock widget with an embedded map canvas, for additional map views.
|
||||
* \note added in QGIS 3.0
|
||||
*/
|
||||
class APP_EXPORT QgsMapCanvasDockWidget : public QgsDockWidget, private Ui::QgsMapCanvasDockWidgetBase
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit QgsMapCanvasDockWidget( const QString &name, QWidget *parent = nullptr );
|
||||
|
||||
/**
|
||||
* Sets the main app map canvas.
|
||||
*/
|
||||
void setMainCanvas( QgsMapCanvas *canvas );
|
||||
|
||||
/**
|
||||
* Returns the map canvas contained in the dock widget.
|
||||
*/
|
||||
QgsMapCanvas *mapCanvas();
|
||||
|
||||
/**
|
||||
* Sets whether the view center should be synchronized with the main canvas center.
|
||||
* @see isViewCenterSynchronized()
|
||||
*/
|
||||
void setViewCenterSynchronized( bool enabled );
|
||||
|
||||
/**
|
||||
* Returns true if the view extent is synchronized with the main canvas extent.
|
||||
* @see setViewCenterSynchronized()
|
||||
*/
|
||||
bool isViewCenterSynchronized() const;
|
||||
|
||||
/**
|
||||
* Sets whether the cursor position marker is visible.
|
||||
* @see isCursorMarkerVisible()
|
||||
*/
|
||||
void setCursorMarkerVisible( bool visible );
|
||||
|
||||
/**
|
||||
* Returns true if the cursor position marker is visible.
|
||||
* @see setCursorMarkerVisible()
|
||||
*/
|
||||
bool isCursorMarkerVisible() const;
|
||||
|
||||
/**
|
||||
* Returns the scaling factor for main canvas scale to view scale.
|
||||
* @see setScaleFactor()
|
||||
* @see isViewScaleSynchronized()
|
||||
*/
|
||||
double scaleFactor() const;
|
||||
|
||||
/**
|
||||
* Sets the scaling \a factor for main canvas scale to view scale.
|
||||
* @see scaleFactor()
|
||||
* @see setViewScaleSynchronized()
|
||||
*/
|
||||
void setScaleFactor( double factor );
|
||||
|
||||
/**
|
||||
* Sets whether the view scale should be synchronized with the main canvas center.
|
||||
* @see isViewScaleSynchronized()
|
||||
* @see setScaleFactor()
|
||||
*/
|
||||
void setViewScaleSynchronized( bool enabled );
|
||||
|
||||
/**
|
||||
* Returns true if the view scale is synchronized with the main canvas extent.
|
||||
* @see setViewScaleSynchronized()
|
||||
* @see scaleFactor()
|
||||
*/
|
||||
bool isViewScaleSynchronized() const;
|
||||
|
||||
signals:
|
||||
|
||||
void renameTriggered();
|
||||
|
||||
protected:
|
||||
|
||||
void resizeEvent( QResizeEvent *e ) override;
|
||||
|
||||
private slots:
|
||||
|
||||
void setMapCrs();
|
||||
void mapExtentChanged();
|
||||
void mapCrsChanged();
|
||||
void menuAboutToShow();
|
||||
void settingsMenuAboutToShow();
|
||||
void syncMarker( const QgsPoint &p );
|
||||
void mapScaleChanged();
|
||||
|
||||
private:
|
||||
|
||||
QgsMapCanvas *mMapCanvas = nullptr;
|
||||
QgsMapCanvas *mMainCanvas = nullptr;
|
||||
QMenu *mMenu = nullptr;
|
||||
QList<QAction *> mMenuPresetActions;
|
||||
QgsScaleComboBox *mScaleCombo = nullptr;
|
||||
QgsDoubleSpinBox *mRotationEdit = nullptr;
|
||||
QgsDoubleSpinBox *mMagnificationEdit = nullptr;
|
||||
QgsDoubleSpinBox *mScaleFactorWidget = nullptr;
|
||||
QCheckBox *mSyncScaleCheckBox = nullptr;
|
||||
bool mBlockScaleUpdate = false;
|
||||
bool mBlockRotationUpdate = false;
|
||||
bool mBlockMagnificationUpdate = false;
|
||||
bool mBlockExtentSync = false;
|
||||
QgsMapToolPan *mPanTool = nullptr;
|
||||
QTimer mResizeTimer;
|
||||
QgsVertexMarker *mXyMarker = nullptr;
|
||||
void syncViewCenter( QgsMapCanvas *sourceCanvas );
|
||||
};
|
||||
|
||||
/**
|
||||
* \class QgsMapSettingsAction
|
||||
* Allows embedding a scale, rotation and other map settings into a menu.
|
||||
* \note added in QGIS 3.0
|
||||
*/
|
||||
|
||||
class QgsMapSettingsAction: public QWidgetAction
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
QgsMapSettingsAction( QWidget *parent = nullptr );
|
||||
|
||||
QgsScaleComboBox *scaleCombo() { return mScaleCombo; }
|
||||
QgsDoubleSpinBox *rotationSpinBox() { return mRotationWidget; }
|
||||
QgsDoubleSpinBox *magnifierSpinBox() { return mMagnifierWidget; }
|
||||
QgsDoubleSpinBox *scaleFactorSpinBox() { return mScaleFactorWidget; }
|
||||
QCheckBox *syncScaleCheckBox() { return mSyncScaleCheckBox; }
|
||||
|
||||
private:
|
||||
QgsScaleComboBox *mScaleCombo = nullptr;
|
||||
QgsDoubleSpinBox *mRotationWidget = nullptr;
|
||||
QgsDoubleSpinBox *mMagnifierWidget = nullptr;
|
||||
QCheckBox *mSyncScaleCheckBox = nullptr;
|
||||
QgsDoubleSpinBox *mScaleFactorWidget = nullptr;
|
||||
};
|
||||
|
||||
|
||||
#endif // QGSMAPCANVASDOCKWIDGET_H
|
@ -336,24 +336,14 @@ QgsMapCanvasAnnotationItem *QgsMapToolAnnotation::selectedItem() const
|
||||
|
||||
QList<QgsMapCanvasAnnotationItem *> QgsMapToolAnnotation::annotationItems() const
|
||||
{
|
||||
QList<QgsMapCanvasAnnotationItem *> annotationItemList;
|
||||
if ( !mCanvas || !mCanvas->scene() )
|
||||
if ( !mCanvas )
|
||||
{
|
||||
return annotationItemList;
|
||||
return QList<QgsMapCanvasAnnotationItem *>();
|
||||
}
|
||||
|
||||
QList<QGraphicsItem *> itemList = mCanvas->scene()->items();
|
||||
QList<QGraphicsItem *>::iterator it = itemList.begin();
|
||||
for ( ; it != itemList.end(); ++it )
|
||||
else
|
||||
{
|
||||
QgsMapCanvasAnnotationItem *aItem = dynamic_cast<QgsMapCanvasAnnotationItem *>( *it );
|
||||
if ( aItem )
|
||||
{
|
||||
annotationItemList.push_back( aItem );
|
||||
}
|
||||
return mCanvas->annotationItems();
|
||||
}
|
||||
|
||||
return annotationItemList;
|
||||
}
|
||||
|
||||
void QgsMapToolAnnotation::toggleTextItemVisibilities()
|
||||
|
@ -811,21 +811,26 @@ void QgsProjectProperties::apply()
|
||||
}
|
||||
|
||||
//set the color for selections
|
||||
QColor myColor = pbnSelectionColor->color();
|
||||
QgsProject::instance()->writeEntry( QStringLiteral( "Gui" ), QStringLiteral( "/SelectionColorRedPart" ), myColor.red() );
|
||||
QgsProject::instance()->writeEntry( QStringLiteral( "Gui" ), QStringLiteral( "/SelectionColorGreenPart" ), myColor.green() );
|
||||
QgsProject::instance()->writeEntry( QStringLiteral( "Gui" ), QStringLiteral( "/SelectionColorBluePart" ), myColor.blue() );
|
||||
QgsProject::instance()->writeEntry( QStringLiteral( "Gui" ), QStringLiteral( "/SelectionColorAlphaPart" ), myColor.alpha() );
|
||||
mMapCanvas->setSelectionColor( myColor );
|
||||
QColor selectionColor = pbnSelectionColor->color();
|
||||
QgsProject::instance()->writeEntry( QStringLiteral( "Gui" ), QStringLiteral( "/SelectionColorRedPart" ), selectionColor.red() );
|
||||
QgsProject::instance()->writeEntry( QStringLiteral( "Gui" ), QStringLiteral( "/SelectionColorGreenPart" ), selectionColor.green() );
|
||||
QgsProject::instance()->writeEntry( QStringLiteral( "Gui" ), QStringLiteral( "/SelectionColorBluePart" ), selectionColor.blue() );
|
||||
QgsProject::instance()->writeEntry( QStringLiteral( "Gui" ), QStringLiteral( "/SelectionColorAlphaPart" ), selectionColor.alpha() );
|
||||
|
||||
|
||||
//set the color for canvas
|
||||
myColor = pbnCanvasColor->color();
|
||||
QgsProject::instance()->writeEntry( QStringLiteral( "Gui" ), QStringLiteral( "/CanvasColorRedPart" ), myColor.red() );
|
||||
QgsProject::instance()->writeEntry( QStringLiteral( "Gui" ), QStringLiteral( "/CanvasColorGreenPart" ), myColor.green() );
|
||||
QgsProject::instance()->writeEntry( QStringLiteral( "Gui" ), QStringLiteral( "/CanvasColorBluePart" ), myColor.blue() );
|
||||
mMapCanvas->setCanvasColor( myColor );
|
||||
QgisApp::instance()->mapOverviewCanvas()->setBackgroundColor( myColor );
|
||||
QgisApp::instance()->mapOverviewCanvas()->refresh();
|
||||
QColor canvasColor = pbnCanvasColor->color();
|
||||
QgsProject::instance()->writeEntry( QStringLiteral( "Gui" ), QStringLiteral( "/CanvasColorRedPart" ), canvasColor.red() );
|
||||
QgsProject::instance()->writeEntry( QStringLiteral( "Gui" ), QStringLiteral( "/CanvasColorGreenPart" ), canvasColor.green() );
|
||||
QgsProject::instance()->writeEntry( QStringLiteral( "Gui" ), QStringLiteral( "/CanvasColorBluePart" ), canvasColor.blue() );
|
||||
|
||||
Q_FOREACH ( QgsMapCanvas *canvas, QgisApp::instance()->mapCanvases() )
|
||||
{
|
||||
canvas->setCanvasColor( canvasColor );
|
||||
canvas->setSelectionColor( selectionColor );
|
||||
canvas->enableMapTileRendering( mMapTileRenderingCheckBox->isChecked() );
|
||||
}
|
||||
QgisApp::instance()->mapOverviewCanvas()->setBackgroundColor( canvasColor );
|
||||
|
||||
//save project scales
|
||||
QStringList myScales;
|
||||
@ -1139,7 +1144,12 @@ void QgsProjectProperties::apply()
|
||||
//save variables
|
||||
QgsProject::instance()->setCustomVariables( mVariableEditor->variablesInActiveScope() );
|
||||
|
||||
emit refresh();
|
||||
//refresh canvases to reflect new properties, eg background color and scale bar after changing display units.
|
||||
Q_FOREACH ( QgsMapCanvas *canvas, QgisApp::instance()->mapCanvases() )
|
||||
{
|
||||
canvas->refresh();
|
||||
}
|
||||
QgisApp::instance()->mapOverviewCanvas()->refresh();
|
||||
}
|
||||
|
||||
void QgsProjectProperties::showProjectionsTab()
|
||||
|
@ -162,9 +162,6 @@ class APP_EXPORT QgsProjectProperties : public QgsOptionsDialogBase, private Ui:
|
||||
//! Signal used to inform listeners that project scale list may have changed
|
||||
void scalesChanged( const QStringList &scales = QStringList() );
|
||||
|
||||
//! let listening canvases know to refresh
|
||||
void refresh();
|
||||
|
||||
private:
|
||||
|
||||
//! Formats for displaying coordinates
|
||||
|
@ -104,6 +104,26 @@ class GUI_EXPORT QgisInterface : public QObject
|
||||
*/
|
||||
virtual bool removeCustomActionForLayerType( QAction *action ) = 0;
|
||||
|
||||
/**
|
||||
* Returns a list of all map canvases open in the app.
|
||||
* @note added in QGIS 3.0
|
||||
*/
|
||||
virtual QList< QgsMapCanvas * > mapCanvases() = 0;
|
||||
|
||||
/**
|
||||
* Create a new map canvas with the specified unique \a name.
|
||||
* @note added in QGIS 3.0
|
||||
* @see closeMapCanvas()
|
||||
*/
|
||||
virtual QgsMapCanvas *createNewMapCanvas( const QString &name ) = 0;
|
||||
|
||||
/**
|
||||
* Closes the additional map canvas with matching \a name.
|
||||
* @note added in QGIS 3.0
|
||||
* @see createNewMapCanvas()
|
||||
*/
|
||||
virtual void closeMapCanvas( const QString &name ) = 0;
|
||||
|
||||
public slots: // TODO: do these functions really need to be slots?
|
||||
|
||||
/* Exposed functions */
|
||||
|
@ -1544,7 +1544,6 @@ void QgsMapCanvas::unsetMapTool( QgsMapTool *tool )
|
||||
}
|
||||
}
|
||||
|
||||
//! Write property of QColor bgColor.
|
||||
void QgsMapCanvas::setCanvasColor( const QColor &color )
|
||||
{
|
||||
// background of map's pixmap
|
||||
@ -1561,7 +1560,7 @@ void QgsMapCanvas::setCanvasColor( const QColor &color )
|
||||
|
||||
// background of QGraphicsScene
|
||||
mScene->setBackgroundBrush( bgBrush );
|
||||
} // setBackgroundColor
|
||||
}
|
||||
|
||||
QColor QgsMapCanvas::canvasColor() const
|
||||
{
|
||||
@ -1858,6 +1857,21 @@ void QgsMapCanvas::readProject( const QDomDocument &doc )
|
||||
{
|
||||
QDomNode node = nodes.item( 0 );
|
||||
|
||||
// Search the specific MapCanvas node using the name
|
||||
if ( nodes.count() > 1 )
|
||||
{
|
||||
for ( int i = 0; i < nodes.size(); ++i )
|
||||
{
|
||||
QDomElement elementNode = nodes.at( i ).toElement();
|
||||
|
||||
if ( elementNode.hasAttribute( QStringLiteral( "name" ) ) && elementNode.attribute( QStringLiteral( "name" ) ) == objectName() )
|
||||
{
|
||||
node = nodes.at( i );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QgsMapSettings tmpSettings;
|
||||
tmpSettings.readXml( node );
|
||||
setDestinationCrs( tmpSettings.destinationCrs() );
|
||||
@ -1867,6 +1881,16 @@ void QgsMapCanvas::readProject( const QDomDocument &doc )
|
||||
enableMapTileRendering( tmpSettings.testFlag( QgsMapSettings::RenderMapTile ) );
|
||||
|
||||
clearExtentHistory(); // clear the extent history on project load
|
||||
|
||||
QDomElement elem = node.toElement();
|
||||
if ( elem.hasAttribute( QStringLiteral( "theme" ) ) )
|
||||
{
|
||||
if ( QgsProject::instance()->mapThemeCollection()->hasMapTheme( elem.attribute( QStringLiteral( "theme" ) ) ) )
|
||||
{
|
||||
setTheme( elem.attribute( QStringLiteral( "theme" ) ) );
|
||||
}
|
||||
}
|
||||
setAnnotationsVisible( elem.attribute( QStringLiteral( "annotationsVisible" ), QStringLiteral( "1" ) ).toInt() );
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1887,6 +1911,10 @@ void QgsMapCanvas::writeProject( QDomDocument &doc )
|
||||
QDomNode qgisNode = nl.item( 0 ); // there should only be one, so zeroth element ok
|
||||
|
||||
QDomElement mapcanvasNode = doc.createElement( QStringLiteral( "mapcanvas" ) );
|
||||
mapcanvasNode.setAttribute( QStringLiteral( "name" ), objectName() );
|
||||
if ( !mTheme.isEmpty() )
|
||||
mapcanvasNode.setAttribute( QStringLiteral( "theme" ), mTheme );
|
||||
mapcanvasNode.setAttribute( QStringLiteral( "annotationsVisible" ), mAnnotationsVisible );
|
||||
qgisNode.appendChild( mapcanvasNode );
|
||||
|
||||
mSettings.writeXml( mapcanvasNode, doc );
|
||||
@ -2048,3 +2076,29 @@ void QgsMapCanvas::setSegmentationToleranceType( QgsAbstractGeometry::Segmentati
|
||||
{
|
||||
mSettings.setSegmentationToleranceType( type );
|
||||
}
|
||||
|
||||
QList<QgsMapCanvasAnnotationItem *> QgsMapCanvas::annotationItems() const
|
||||
{
|
||||
QList<QgsMapCanvasAnnotationItem *> annotationItemList;
|
||||
QList<QGraphicsItem *> itemList = mScene->items();
|
||||
QList<QGraphicsItem *>::iterator it = itemList.begin();
|
||||
for ( ; it != itemList.end(); ++it )
|
||||
{
|
||||
QgsMapCanvasAnnotationItem *aItem = dynamic_cast< QgsMapCanvasAnnotationItem *>( *it );
|
||||
if ( aItem )
|
||||
{
|
||||
annotationItemList.push_back( aItem );
|
||||
}
|
||||
}
|
||||
|
||||
return annotationItemList;
|
||||
}
|
||||
|
||||
void QgsMapCanvas::setAnnotationsVisible( bool show )
|
||||
{
|
||||
mAnnotationsVisible = show;
|
||||
Q_FOREACH ( QgsMapCanvasAnnotationItem *item, annotationItems() )
|
||||
{
|
||||
item->setVisible( show );
|
||||
}
|
||||
}
|
||||
|
@ -63,7 +63,7 @@ class QgsMapOverviewCanvas;
|
||||
class QgsMapTool;
|
||||
class QgsSnappingUtils;
|
||||
class QgsRubberBand;
|
||||
|
||||
class QgsMapCanvasAnnotationItem;
|
||||
|
||||
/** \ingroup gui
|
||||
* Map canvas is a class for displaying all GIS data types on a canvas.
|
||||
@ -468,6 +468,26 @@ class GUI_EXPORT QgsMapCanvas : public QGraphicsView
|
||||
@param type the segmentation tolerance typename*/
|
||||
void setSegmentationToleranceType( QgsAbstractGeometry::SegmentationToleranceType type );
|
||||
|
||||
/**
|
||||
* Returns a list of all annotation items in the canvas.
|
||||
* @note added in QGIS 3.0
|
||||
*/
|
||||
QList< QgsMapCanvasAnnotationItem *> annotationItems() const;
|
||||
|
||||
/**
|
||||
* Returns true if annotations are visible within the map canvas.
|
||||
* @note added in QGIS 3.0
|
||||
* @see setAnnotationsVisible()
|
||||
*/
|
||||
bool annotationsVisible() const { return mAnnotationsVisible; }
|
||||
|
||||
/**
|
||||
* Sets whether annotations are \a visible in the canvas.
|
||||
* @note added in QGIS 3.0
|
||||
* @see annotationsVisible()
|
||||
*/
|
||||
void setAnnotationsVisible( bool visible );
|
||||
|
||||
public slots:
|
||||
|
||||
//! Repaints the canvas map
|
||||
@ -784,6 +804,8 @@ class GUI_EXPORT QgsMapCanvas : public QGraphicsView
|
||||
|
||||
QString mTheme;
|
||||
|
||||
bool mAnnotationsVisible = true;
|
||||
|
||||
//! Force a resize of the map canvas item
|
||||
//! @note added in 2.16
|
||||
void updateMapSize();
|
||||
|
@ -33,6 +33,9 @@ QgsMapCanvasAnnotationItem::QgsMapCanvasAnnotationItem( QgsAnnotation *annotatio
|
||||
, mAnnotation( annotation )
|
||||
{
|
||||
setFlag( QGraphicsItem::ItemIsSelectable, true );
|
||||
if ( mapCanvas && !mapCanvas->annotationsVisible() )
|
||||
setVisible( false );
|
||||
|
||||
connect( mAnnotation, &QgsAnnotation::appearanceChanged, this, [this] { update(); } );
|
||||
connect( mAnnotation, &QgsAnnotation::moved, this, [this] { updatePosition(); } );
|
||||
connect( mAnnotation, &QgsAnnotation::moved, this, &QgsMapCanvasAnnotationItem::setFeatureForMapPosition );
|
||||
|
@ -54,6 +54,7 @@
|
||||
<addaction name="mActionDwgImport"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="mActionSnappingOptions"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="mActionNewPrintComposer"/>
|
||||
<addaction name="mActionShowComposerManager"/>
|
||||
<addaction name="mPrintComposersMenu"/>
|
||||
@ -91,6 +92,7 @@
|
||||
<addaction name="mActionPreviewProtanope"/>
|
||||
<addaction name="mActionPreviewDeuteranope"/>
|
||||
</widget>
|
||||
<addaction name="mActionNewMapCanvas"/>
|
||||
<addaction name="mActionPan"/>
|
||||
<addaction name="mActionPanToSelected"/>
|
||||
<addaction name="mActionZoomIn"/>
|
||||
@ -332,6 +334,7 @@
|
||||
<addaction name="mActionOpenProject"/>
|
||||
<addaction name="mActionSaveProject"/>
|
||||
<addaction name="mActionSaveProjectAs"/>
|
||||
<addaction name="mActionNewMapCanvas"/>
|
||||
<addaction name="mActionNewPrintComposer"/>
|
||||
<addaction name="mActionShowComposerManager"/>
|
||||
</widget>
|
||||
@ -640,6 +643,21 @@
|
||||
<string>Save as &Image...</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="mActionNewMapCanvas">
|
||||
<property name="icon">
|
||||
<iconset resource="../../images/images.qrc">
|
||||
<normaloff>:/images/themes/default/mActionNewMap.svg</normaloff>:/images/themes/default/mActionNewMap.svg</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>New &Map View</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>New Map View</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>Ctrl+M</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="mActionNewPrintComposer">
|
||||
<property name="icon">
|
||||
<iconset resource="../../images/images.qrc">
|
||||
|
167
src/ui/qgsmapcanvasdockwidgetbase.ui
Normal file
167
src/ui/qgsmapcanvasdockwidgetbase.ui
Normal file
@ -0,0 +1,167 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>QgsMapCanvasDockWidgetBase</class>
|
||||
<widget class="QgsDockWidget" name="QgsMapCanvasDockWidgetBase">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>216</width>
|
||||
<height>138</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Map Canvas</string>
|
||||
</property>
|
||||
<widget class="QWidget" name="mContents">
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QToolBar" name="mToolbar">
|
||||
<property name="iconSize">
|
||||
<size>
|
||||
<width>16</width>
|
||||
<height>16</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="floatable">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<addaction name="mActionSyncView"/>
|
||||
<addaction name="mActionZoomFullExtent"/>
|
||||
<addaction name="mActionZoomToSelected"/>
|
||||
<addaction name="mActionZoomToLayer"/>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QWidget" name="mMainWidget" native="true">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<action name="mActionSetCrs">
|
||||
<property name="icon">
|
||||
<iconset resource="../../images/images.qrc">
|
||||
<normaloff>:/images/themes/default/propertyicons/CRS.svg</normaloff>:/images/themes/default/propertyicons/CRS.svg</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Set Map CRS…</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Set Map CRS</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="mActionSyncView">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../../images/images.qrc">
|
||||
<normaloff>:/images/themes/default/mActionLockExtent.svg</normaloff>:/images/themes/default/mActionLockExtent.svg</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Synchronize View</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Synchronize View Center with Main Map</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="mActionRename">
|
||||
<property name="text">
|
||||
<string>Rename View…</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Rename View</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="mActionZoomToSelected">
|
||||
<property name="icon">
|
||||
<iconset resource="../../images/images.qrc">
|
||||
<normaloff>:/images/themes/default/mActionZoomToSelected.svg</normaloff>:/images/themes/default/mActionZoomToSelected.svg</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Zoom to &Selection</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="mActionZoomToLayer">
|
||||
<property name="icon">
|
||||
<iconset resource="../../images/images.qrc">
|
||||
<normaloff>:/images/themes/default/mActionZoomToLayer.svg</normaloff>:/images/themes/default/mActionZoomToLayer.svg</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Zoom to &Layer</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="mActionZoomFullExtent">
|
||||
<property name="icon">
|
||||
<iconset resource="../../images/images.qrc">
|
||||
<normaloff>:/images/themes/default/mActionZoomFullExtent.svg</normaloff>:/images/themes/default/mActionZoomFullExtent.svg</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Zoom &Full</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="mActionShowAnnotations">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Show Annotations</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Show Annotations</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="mActionShowCursor">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Show Cursor Position</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>QgsDockWidget</class>
|
||||
<extends>QDockWidget</extends>
|
||||
<header>qgsdockwidget.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources>
|
||||
<include location="../../images/images.qrc"/>
|
||||
</resources>
|
||||
<connections/>
|
||||
</ui>
|
@ -14,7 +14,8 @@ __revision__ = '$Format:%H$'
|
||||
|
||||
import qgis # NOQA
|
||||
|
||||
from qgis.core import (QgsCoordinateReferenceSystem,
|
||||
from qgis.core import (QgsMapSettings,
|
||||
QgsCoordinateReferenceSystem,
|
||||
QgsRectangle,
|
||||
QgsVectorLayer,
|
||||
QgsFeature,
|
||||
@ -23,10 +24,13 @@ from qgis.core import (QgsCoordinateReferenceSystem,
|
||||
QgsFillSymbol,
|
||||
QgsSingleSymbolRenderer,
|
||||
QgsMapThemeCollection,
|
||||
QgsProject)
|
||||
QgsProject,
|
||||
QgsApplication)
|
||||
from qgis.gui import (QgsMapCanvas)
|
||||
|
||||
from qgis.PyQt.QtCore import QDir
|
||||
from qgis.PyQt.QtCore import (Qt,
|
||||
QDir)
|
||||
from qgis.PyQt.QtXml import (QDomDocument, QDomElement)
|
||||
import time
|
||||
from qgis.testing import start_app, unittest
|
||||
|
||||
@ -337,6 +341,35 @@ class TestQgsMapCanvas(unittest.TestCase):
|
||||
print((self.report))
|
||||
return result
|
||||
|
||||
def testSaveMultipleCanvasesToProject(self):
|
||||
# test saving/restoring canvas state to project with multiple canvases
|
||||
c1 = QgsMapCanvas()
|
||||
c1.setObjectName('c1')
|
||||
c1.setDestinationCrs(QgsCoordinateReferenceSystem('EPSG:3111'))
|
||||
c1.setRotation(45)
|
||||
c2 = QgsMapCanvas()
|
||||
c2.setObjectName('c2')
|
||||
c2.setDestinationCrs(QgsCoordinateReferenceSystem('EPSG:4326'))
|
||||
c2.setRotation(65)
|
||||
|
||||
doc = QDomDocument("testdoc")
|
||||
elem = doc.createElement("qgis")
|
||||
doc.appendChild(elem)
|
||||
c1.writeProject(doc)
|
||||
c2.writeProject(doc)
|
||||
|
||||
c3 = QgsMapCanvas()
|
||||
c3.setObjectName('c1')
|
||||
c4 = QgsMapCanvas()
|
||||
c4.setObjectName('c2')
|
||||
c3.readProject(doc)
|
||||
c4.readProject(doc)
|
||||
|
||||
self.assertEqual(c3.mapSettings().destinationCrs().authid(), 'EPSG:3111')
|
||||
self.assertEqual(c3.rotation(), 45)
|
||||
self.assertEqual(c4.mapSettings().destinationCrs().authid(), 'EPSG:4326')
|
||||
self.assertEqual(c4.rotation(), 65)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
Loading…
x
Reference in New Issue
Block a user