Merge pull request #7313 from PeterPetrik/mesh_layer_styling_gui

[mesh] [feature] App widgets for styling mesh layers
This commit is contained in:
Martin Dobias 2018-06-28 15:17:14 +02:00 committed by GitHub
commit 97addfc2cc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
58 changed files with 5668 additions and 201 deletions

View File

@ -518,6 +518,9 @@
<file>themes/default/propertyicons/labeltext.svg</file>
<file>themes/default/propertyicons/locale.svg</file>
<file>themes/default/propertyicons/map_tools.svg</file>
<file>themes/default/propertyicons/meshcontours.svg</file>
<file>themes/default/propertyicons/meshframe.svg</file>
<file>themes/default/propertyicons/meshvectors.svg</file>
<file>themes/default/propertyicons/metadata.svg</file>
<file>themes/default/propertyicons/network_and_proxy.svg</file>
<file>themes/default/propertyicons/overlay.svg</file>

View File

@ -0,0 +1,170 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<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:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="16"
height="16"
id="svg2"
version="1.1"
inkscape:version="0.48.4 r9939"
sodipodi:docname="list_icons.svg">
<defs
id="defs4">
<marker
inkscape:stockid="TriangleOutM"
orient="auto"
refY="0.0"
refX="0.0"
id="TriangleOutM"
style="overflow:visible">
<path
id="path3940"
d="M 5.77,0.0 L -2.88,5.0 L -2.88,-5.0 L 5.77,0.0 z "
style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt"
transform="scale(0.4)" />
</marker>
<marker
inkscape:stockid="Arrow1Send"
orient="auto"
refY="0.0"
refX="0.0"
id="Arrow1Send"
style="overflow:visible;">
<path
id="path3810"
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;"
transform="scale(0.2) rotate(180) translate(6,0)" />
</marker>
<marker
inkscape:stockid="Arrow1Mend"
orient="auto"
refY="0.0"
refX="0.0"
id="Arrow1Mend"
style="overflow:visible;">
<path
id="path3804"
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;"
transform="scale(0.4) rotate(180) translate(10,0)" />
</marker>
<marker
inkscape:stockid="Arrow2Lend"
orient="auto"
refY="0.0"
refX="0.0"
id="Arrow2Lend"
style="overflow:visible;">
<path
id="path3816"
style="fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
transform="scale(1.1) rotate(180) translate(1,0)" />
</marker>
<marker
inkscape:stockid="TriangleOutL"
orient="auto"
refY="0.0"
refX="0.0"
id="TriangleOutL"
style="overflow:visible">
<path
id="path3937"
d="M 5.77,0.0 L -2.88,5.0 L -2.88,-5.0 L 5.77,0.0 z "
style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt"
transform="scale(0.8)" />
</marker>
<inkscape:perspective
sodipodi:type="inkscape:persp3d"
inkscape:vp_x="0 : 8 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_z="16 : 8 : 1"
inkscape:persp3d-origin="8 : 5.3333333 : 1"
id="perspective3771" />
<linearGradient
id="linearGradient3755">
<stop
id="stop3767"
offset="0"
style="stop-color:#0000ff;stop-opacity:0.50196081;" />
<stop
id="stop3765"
offset="0.34999999"
style="stop-color:#00ffff;stop-opacity:0.50196081;" />
<stop
id="stop3763"
offset="0.5"
style="stop-color:#00ff00;stop-opacity:0.50196081;" />
<stop
style="stop-color:#ffff00;stop-opacity:0.50196081;"
offset="0.64999998"
id="stop3769" />
<stop
style="stop-color:#ff0000;stop-opacity:0.50980395;"
offset="1"
id="stop3759" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3755"
id="linearGradient3761"
x1="-0.044642858"
y1="0.071428955"
x2="15.955357"
y2="16.053572"
gradientUnits="userSpaceOnUse" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="22.4"
inkscape:cx="10.67143"
inkscape:cy="2.9092772"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-width="1920"
inkscape:window-height="994"
inkscape:window-x="-4"
inkscape:window-y="-3"
inkscape:window-maximized="1" />
<metadata
id="metadata7">
<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>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-1036.3622)">
<rect
style="fill:url(#linearGradient3761);stroke:none;fill-opacity:1.0"
id="rect2985"
width="16"
height="16"
x="-0.044642858"
y="0.017857092"
transform="translate(0,1036.3622)" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 5.0 KiB

View File

@ -0,0 +1,207 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<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:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="16"
height="16"
id="svg2"
version="1.1"
inkscape:version="0.92.2 (5c3e80d, 2017-08-06)"
sodipodi:docname="meshframe.svg"
inkscape:export-filename="/home/martin/lutra/qgis-crayfish-plugin/plugin/list_icons_d.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90">
<defs
id="defs4">
<marker
inkscape:stockid="TriangleOutM"
orient="auto"
refY="0.0"
refX="0.0"
id="TriangleOutM"
style="overflow:visible">
<path
id="path3940"
d="M 5.77,0.0 L -2.88,5.0 L -2.88,-5.0 L 5.77,0.0 z "
style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt"
transform="scale(0.4)" />
</marker>
<marker
inkscape:stockid="Arrow1Send"
orient="auto"
refY="0.0"
refX="0.0"
id="Arrow1Send"
style="overflow:visible;">
<path
id="path3810"
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;"
transform="scale(0.2) rotate(180) translate(6,0)" />
</marker>
<marker
inkscape:stockid="Arrow1Mend"
orient="auto"
refY="0.0"
refX="0.0"
id="Arrow1Mend"
style="overflow:visible;">
<path
id="path3804"
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;"
transform="scale(0.4) rotate(180) translate(10,0)" />
</marker>
<marker
inkscape:stockid="Arrow2Lend"
orient="auto"
refY="0.0"
refX="0.0"
id="Arrow2Lend"
style="overflow:visible;">
<path
id="path3816"
style="fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
transform="scale(1.1) rotate(180) translate(1,0)" />
</marker>
<marker
inkscape:stockid="TriangleOutL"
orient="auto"
refY="0.0"
refX="0.0"
id="TriangleOutL"
style="overflow:visible">
<path
id="path3937"
d="M 5.77,0.0 L -2.88,5.0 L -2.88,-5.0 L 5.77,0.0 z "
style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt"
transform="scale(0.8)" />
</marker>
<inkscape:perspective
sodipodi:type="inkscape:persp3d"
inkscape:vp_x="0 : 8 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_z="16 : 8 : 1"
inkscape:persp3d-origin="8 : 5.3333333 : 1"
id="perspective3771" />
<linearGradient
id="linearGradient3755">
<stop
id="stop3767"
offset="0"
style="stop-color:#0000ff;stop-opacity:0.50196081;" />
<stop
id="stop3765"
offset="0.34999999"
style="stop-color:#00ffff;stop-opacity:0.50196081;" />
<stop
id="stop3763"
offset="0.5"
style="stop-color:#00ff00;stop-opacity:0.50196081;" />
<stop
style="stop-color:#ffff00;stop-opacity:0.50196081;"
offset="0.64999998"
id="stop3769" />
<stop
style="stop-color:#ff0000;stop-opacity:0.50980395;"
offset="1"
id="stop3759" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3755"
id="linearGradient3761"
x1="-0.044642858"
y1="0.071428955"
x2="15.955357"
y2="16.053572"
gradientUnits="userSpaceOnUse" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="31.678384"
inkscape:cx="6.3745751"
inkscape:cy="6.2123922"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-width="1920"
inkscape:window-height="1015"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
showguides="true"
inkscape:guide-bbox="true" />
<metadata
id="metadata7">
<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 />
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-1036.3622)">
<path
style="fill:#666666;fill-opacity:1;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 2.7463522,1038.4726 -0.063134,12.1219"
id="path111"
inkscape:connector-curvature="0" />
<path
style="fill:#666666;fill-opacity:1;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 6.2818858,1038.4725 -0.063134,12.1219"
id="path111-6"
inkscape:connector-curvature="0" />
<path
style="fill:#666666;fill-opacity:1;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 9.5964489,1038.5042 -0.063134,12.1219"
id="path111-2"
inkscape:connector-curvature="0" />
<path
style="fill:#666666;fill-opacity:1;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 12.942579,1038.5356 -0.06313,12.1219"
id="path111-9"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:1.04660463px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 2.1764118,1050.0579 11.2098392,0.063 v 0 0 0 0 0"
id="path1015"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:1.04660463px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 2.2012383,1046.121 11.2098387,0.063 v 0 0 0 0 0"
id="path1015-2"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:1.04660463px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 2.1921954,1039.0093 11.2098396,0.063 v 0 0 0 0 0"
id="path1015-7"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:1.04660463px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 2.2237627,1042.7026 11.2098393,0.063 v 0 0 0 0 0"
id="path1015-0"
inkscape:connector-curvature="0" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 7.1 KiB

View File

@ -0,0 +1,213 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<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:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="16"
height="16"
id="svg2"
version="1.1"
inkscape:version="0.48.4 r9939"
sodipodi:docname="list_icons.svg"
inkscape:export-filename="/home/martin/lutra/qgis-crayfish-plugin/plugin/list_icons_d.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90">
<defs
id="defs4">
<marker
inkscape:stockid="TriangleOutM"
orient="auto"
refY="0.0"
refX="0.0"
id="TriangleOutM"
style="overflow:visible">
<path
id="path3940"
d="M 5.77,0.0 L -2.88,5.0 L -2.88,-5.0 L 5.77,0.0 z "
style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt"
transform="scale(0.4)" />
</marker>
<marker
inkscape:stockid="Arrow1Send"
orient="auto"
refY="0.0"
refX="0.0"
id="Arrow1Send"
style="overflow:visible;">
<path
id="path3810"
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;"
transform="scale(0.2) rotate(180) translate(6,0)" />
</marker>
<marker
inkscape:stockid="Arrow1Mend"
orient="auto"
refY="0.0"
refX="0.0"
id="Arrow1Mend"
style="overflow:visible;">
<path
id="path3804"
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;"
transform="scale(0.4) rotate(180) translate(10,0)" />
</marker>
<marker
inkscape:stockid="Arrow2Lend"
orient="auto"
refY="0.0"
refX="0.0"
id="Arrow2Lend"
style="overflow:visible;">
<path
id="path3816"
style="fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
transform="scale(1.1) rotate(180) translate(1,0)" />
</marker>
<marker
inkscape:stockid="TriangleOutL"
orient="auto"
refY="0.0"
refX="0.0"
id="TriangleOutL"
style="overflow:visible">
<path
id="path3937"
d="M 5.77,0.0 L -2.88,5.0 L -2.88,-5.0 L 5.77,0.0 z "
style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt"
transform="scale(0.8)" />
</marker>
<inkscape:perspective
sodipodi:type="inkscape:persp3d"
inkscape:vp_x="0 : 8 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_z="16 : 8 : 1"
inkscape:persp3d-origin="8 : 5.3333333 : 1"
id="perspective3771" />
<linearGradient
id="linearGradient3755">
<stop
id="stop3767"
offset="0"
style="stop-color:#0000ff;stop-opacity:0.50196081;" />
<stop
id="stop3765"
offset="0.34999999"
style="stop-color:#00ffff;stop-opacity:0.50196081;" />
<stop
id="stop3763"
offset="0.5"
style="stop-color:#00ff00;stop-opacity:0.50196081;" />
<stop
style="stop-color:#ffff00;stop-opacity:0.50196081;"
offset="0.64999998"
id="stop3769" />
<stop
style="stop-color:#ff0000;stop-opacity:0.50980395;"
offset="1"
id="stop3759" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3755"
id="linearGradient3761"
x1="-0.044642858"
y1="0.071428955"
x2="15.955357"
y2="16.053572"
gradientUnits="userSpaceOnUse" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="31.678384"
inkscape:cx="2.8246129"
inkscape:cy="6.2123922"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-width="1920"
inkscape:window-height="994"
inkscape:window-x="-4"
inkscape:window-y="-3"
inkscape:window-maximized="1"
showguides="true"
inkscape:guide-bbox="true">
<sodipodi:guide
orientation="1,0"
position="14.017857,5.8035714"
id="guide4180" />
<sodipodi:guide
orientation="0,1"
position="-3.5714286,1.9642857"
id="guide4182" />
<sodipodi:guide
orientation="1,0"
position="12.053571,10.982143"
id="guide4186" />
<sodipodi:guide
orientation="0,1"
position="-9.1964286,3.9732143"
id="guide4188" />
<sodipodi:guide
orientation="0,1"
position="-5.0446429,5.9821429"
id="guide4190" />
<sodipodi:guide
orientation="1,0"
position="10,8.3482143"
id="guide4192" />
<sodipodi:guide
orientation="1,0"
position="12.991071,10.714286"
id="guide4194" />
<sodipodi:guide
orientation="0,1"
position="8.9651038,2.9673231"
id="guide4196" />
</sodipodi:namedview>
<metadata
id="metadata7">
<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>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-1036.3622)">
<path
style="fill:#b3b3b3;stroke:#b3b3b3;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-mid:none;marker-end:none"
d="m 2.5000001,1038.8622 10.9999999,11"
id="path3789"
inkscape:connector-curvature="0"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90" />
<path
style="fill:#b3b3b3;fill-opacity:1;stroke:#b3b3b3;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="M 14.017857,1050.3979 12.991071,1046.3801 10,1049.3949 z"
id="path4184"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccc" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 6.6 KiB

View File

@ -227,6 +227,8 @@ or read on demand
virtual bool addDataset( const QString &uri ) = 0;
%Docstring
Associate dataset with the mesh
emits dataChanged when successful
%End
virtual int datasetCount() const = 0;

View File

@ -10,6 +10,7 @@
class QgsMeshRendererMeshSettings
{
%Docstring
@ -73,54 +74,19 @@ Represents a mesh renderer settings for scalar datasets
#include "qgsmeshrenderersettings.h"
%End
public:
QColor maxColor() const;
QgsColorRampShader colorRampShader() const;
%Docstring
Returns color representing maximum scalar value in the dataset
Returns color ramp shader function
%End
void setMaxColor( const QColor &maxColor );
void setColorRampShader( const QgsColorRampShader &shader );
%Docstring
Sets color representing maximum scalar value in the dataset
Sets color ramp shader function
%End
QColor minColor() const;
bool isEnabled() const;
%Docstring
Returns color representing minimum scalar value in the dataset
Returns whether color ramp has any items assigned
%End
void setMinColor( const QColor &minColor );
%Docstring
Sets color representing maximum scalar value in the dataset
%End
double minValue() const;
%Docstring
Returns min scalar value that represents minColor()
if set to numerical_limits<double>.quiet_NaN(), value for minColor() is
taken from minimum value of active scalar dataset
%End
void setMinValue( double minValue );
%Docstring
Sets min scalar value that represents minColor()
.. seealso:: :py:func:`QgsMeshRendererScalarSettings.minValue`
%End
double maxValue() const;
%Docstring
Returns max scalar value that represents maxColor()
if set to numerical_limits<double>.quiet_NaN(), value for maxColor() is
taken from maximum value of active scalar dataset
%End
void setMaxValue( double maxValue );
%Docstring
Sets min scalar value that represents minColor()
.. seealso:: :py:func:`QgsMeshRendererScalarSettings.maxValue`
%End
};
class QgsMeshRendererVectorSettings

View File

@ -92,6 +92,13 @@ Returns the color ramp type as a string.
void setColorRampType( QgsColorRampShader::Type colorRampType );
%Docstring
Sets the color ramp type
%End
bool isEmpty() const;
%Docstring
Whether the color ramp contains any items
.. versionadded:: 3.4
%End
QgsColorRamp *sourceColorRamp() const /Factory/;

View File

@ -0,0 +1,107 @@
/************************************************************************
* This file has been generated automatically from *
* *
* src/gui/raster/qgscolorrampshaderwidget.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
************************************************************************/
class QgsColorRampShaderWidget: QWidget, protected Ui::QgsColorRampShaderWidgetBase
{
%Docstring
It has 2 ways how to use it. For raster layers, raster data provider and band is assigned and
the Quantile classification mode can be used and the LoadFromBandButton is visible.
The other mode is used to style mesh layer contours (scalar datasets)
.. versionadded:: 3.4
%End
%TypeHeaderCode
#include "qgscolorrampshaderwidget.h"
%End
public:
QgsColorRampShaderWidget( QWidget *parent = 0 );
%Docstring
Creates new color ramp shader widget
%End
void initForUseWithRasterLayer();
%Docstring
Allows quantile classification mode for raster layers
%End
void setRasterBand( QgsRasterDataProvider *dp, int band, const QgsRectangle &extent );
%Docstring
Associates raster with the widget
%End
void setMinMaxAndClassify( double min, double max );
%Docstring
Sets min max and classify color tree
%End
void setMinMax( double min, double max );
%Docstring
Sets min max
%End
QgsColorRampShader shader() const;
%Docstring
Returns shared function used in the renderer
%End
void setFromShader( const QgsColorRampShader &colorRampShader );
%Docstring
Sets widget state from the color ramp shader
%End
signals:
void minMaxChangedFromTree( double min, double max );
%Docstring
Color ramp tree has changed
%End
void widgetChanged();
%Docstring
Widget changed
%End
void classificationModeChanged( QgsColorRampShader::ClassificationMode mode );
%Docstring
Classification mode changed
%End
public slots:
void classify();
%Docstring
Executes the single band pseudo raster classification
%End
void loadMinMaxFromTree();
%Docstring
Loads min and max values from color ramp tree
%End
protected:
void populateColormapTreeWidget( const QList<QgsColorRampShader::ColorRampItem> &colorRampItems );
%Docstring
Populates color ramp tree from ramp items
%End
};
/************************************************************************
* This file has been generated automatically from *
* *
* src/gui/raster/qgscolorrampshaderwidget.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
************************************************************************/

View File

@ -23,12 +23,22 @@ class QgsSingleBandPseudoColorRendererWidget: QgsRasterRendererWidget
static QgsRasterRendererWidget *create( QgsRasterLayer *layer, const QgsRectangle &extent ) /Factory/;
virtual QgsRasterRenderer *renderer();
QgsColorRampShader *shaderFunction() const /Factory/;
%Docstring
Returns shader function used in the renderer. Caller takes ownership and deletes it.
%End
virtual void setMapCanvas( QgsMapCanvas *canvas );
virtual void doComputations();
virtual QgsRasterMinMaxWidget *minMaxWidget();
int currentBand() const;
%Docstring
Returns the current raster band number
%End
void setFromRenderer( const QgsRasterRenderer *r );
public slots:

View File

@ -206,6 +206,7 @@
%Include auto_generated/qgsvariableeditorwidget.sip
%Include auto_generated/qgsvscrollarea.sip
%Include auto_generated/qgsfiledownloaderdialog.sip
%Include auto_generated/raster/qgscolorrampshaderwidget.sip
%Include auto_generated/raster/qgsmultibandcolorrendererwidget.sip
%Include auto_generated/raster/qgspalettedrendererwidget.sip
%Include auto_generated/raster/qgsrasterbandcombobox.sip

View File

@ -210,6 +210,14 @@ SET(QGIS_APP_SRCS
qgssettingstree.cpp
qgsvariantdelegate.cpp
qgscrashhandler.cpp
mesh/qgsmeshlayerproperties.cpp
mesh/qgsrenderermeshpropertieswidget.cpp
mesh/qgsmeshrenderermeshsettingswidget.cpp
mesh/qgsmeshrendererscalarsettingswidget.cpp
mesh/qgsmeshrenderervectorsettingswidget.cpp
mesh/qgsmeshrendereractivedatasetwidget.cpp
mesh/qgsmeshdatasetgrouptreeview.cpp
)
SET (QGIS_APP_MOC_HDRS
@ -410,6 +418,14 @@ SET (QGIS_APP_MOC_HDRS
qgssettingstree.h
qgsvariantdelegate.h
mesh/qgsmeshlayerproperties.h
mesh/qgsrenderermeshpropertieswidget.h
mesh/qgsmeshrenderermeshsettingswidget.h
mesh/qgsmeshrendererscalarsettingswidget.h
mesh/qgsmeshrenderervectorsettingswidget.h
mesh/qgsmeshrendereractivedatasetwidget.h
mesh/qgsmeshdatasetgrouptreeview.h
)
@ -584,6 +600,7 @@ INCLUDE_DIRECTORIES(
${CMAKE_SOURCE_DIR}/src/app/pluginmanager
${CMAKE_SOURCE_DIR}/src/app/gps
${CMAKE_SOURCE_DIR}/src/app/dwg
${CMAKE_SOURCE_DIR}/src/app/mesh
${CMAKE_SOURCE_DIR}/src/app/locator
${CMAKE_SOURCE_DIR}/src/analysis/raster
${CMAKE_SOURCE_DIR}/src/core
@ -660,6 +677,7 @@ INCLUDE_DIRECTORIES(
../core/processing
../core/providers/memory
../core/raster
../core/mesh
../core/scalebar
../core/symbology
../gui

View File

@ -0,0 +1,324 @@
/***************************************************************************
qgsmeshdatasetgrouptreeview.cpp
-------------------------------
begin : June 2018
copyright : (C) 2018 by Peter Petrik
email : zilolv 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 "qgsmeshdatasetgrouptreeview.h"
#include "qgis.h"
#include "qgsmeshlayer.h"
#include <QList>
#include <QItemSelectionModel>
QgsMeshDatasetGroupTreeItem::QgsMeshDatasetGroupTreeItem( QgsMeshDatasetGroupTreeItem *parent )
: mParent( parent )
{
}
QgsMeshDatasetGroupTreeItem::QgsMeshDatasetGroupTreeItem( const QString &name, QgsMeshDatasetGroupTreeItem *parent )
: mParent( parent )
, mName( name )
{
}
QgsMeshDatasetGroupTreeItem::~QgsMeshDatasetGroupTreeItem()
{
qDeleteAll( mChildren );
}
void QgsMeshDatasetGroupTreeItem::appendChild( QgsMeshDatasetGroupTreeItem *node )
{
mChildren.append( node );
}
QgsMeshDatasetGroupTreeItem *QgsMeshDatasetGroupTreeItem::child( int row ) const
{
if ( row < mChildren.count() )
return mChildren.at( row );
else
return nullptr;
}
int QgsMeshDatasetGroupTreeItem::columnCount() const
{
return 1;
}
int QgsMeshDatasetGroupTreeItem::childCount() const
{
return mChildren.count();
}
QgsMeshDatasetGroupTreeItem *QgsMeshDatasetGroupTreeItem::parentItem() const
{
return mParent;
}
int QgsMeshDatasetGroupTreeItem::row() const
{
if ( mParent )
return mParent->mChildren.indexOf( const_cast<QgsMeshDatasetGroupTreeItem *>( this ) );
return 0;
}
QVariant QgsMeshDatasetGroupTreeItem::data( int column ) const
{
Q_UNUSED( column );
return mName;
}
/////////////////////////////////////////////////////////////////////////////////////////
QgsMeshDatasetGroupTreeModel::QgsMeshDatasetGroupTreeModel( QObject *parent )
: QAbstractItemModel( parent )
, mRootItem( new QgsMeshDatasetGroupTreeItem() )
{
}
QgsMeshDatasetGroupTreeModel::~QgsMeshDatasetGroupTreeModel() = default;
int QgsMeshDatasetGroupTreeModel::columnCount( const QModelIndex &parent ) const
{
if ( parent.isValid() )
return static_cast<QgsMeshDatasetGroupTreeItem *>( parent.internalPointer() )->columnCount();
else
return mRootItem->columnCount();
}
QVariant QgsMeshDatasetGroupTreeModel::data( const QModelIndex &index, int role ) const
{
if ( !index.isValid() )
return QVariant();
if ( role != Qt::DisplayRole )
return QVariant();
QgsMeshDatasetGroupTreeItem *item = static_cast<QgsMeshDatasetGroupTreeItem *>( index.internalPointer() );
return item->data( index.column() );
}
Qt::ItemFlags QgsMeshDatasetGroupTreeModel::flags( const QModelIndex &index ) const
{
if ( !index.isValid() )
return Qt::NoItemFlags;
return QAbstractItemModel::flags( index );
}
QVariant QgsMeshDatasetGroupTreeModel::headerData( int section,
Qt::Orientation orientation,
int role ) const
{
Q_UNUSED( section );
if ( orientation == Qt::Horizontal && role == Qt::DisplayRole )
return tr( "Groups" );
return QVariant();
}
QModelIndex QgsMeshDatasetGroupTreeModel::index( int row, int column, const QModelIndex &parent )
const
{
if ( !hasIndex( row, column, parent ) )
return QModelIndex();
QgsMeshDatasetGroupTreeItem *parentItem;
if ( !parent.isValid() )
parentItem = mRootItem.get();
else
parentItem = static_cast<QgsMeshDatasetGroupTreeItem *>( parent.internalPointer() );
QgsMeshDatasetGroupTreeItem *childItem = parentItem->child( row );
if ( childItem )
return createIndex( row, column, childItem );
else
return QModelIndex();
}
QModelIndex QgsMeshDatasetGroupTreeModel::parent( const QModelIndex &index ) const
{
if ( !index.isValid() )
return QModelIndex();
QgsMeshDatasetGroupTreeItem *childItem = static_cast<QgsMeshDatasetGroupTreeItem *>( index.internalPointer() );
QgsMeshDatasetGroupTreeItem *parentItem = childItem->parentItem();
if ( parentItem == mRootItem.get() )
return QModelIndex();
return createIndex( parentItem->row(), 0, parentItem );
}
int QgsMeshDatasetGroupTreeModel::rowCount( const QModelIndex &parent ) const
{
QgsMeshDatasetGroupTreeItem *parentItem;
if ( parent.column() > 0 )
return 0;
if ( !parent.isValid() )
parentItem = mRootItem.get();
else
parentItem = static_cast<QgsMeshDatasetGroupTreeItem *>( parent.internalPointer() );
return parentItem->childCount();
}
void QgsMeshDatasetGroupTreeModel::setupModelData( const QStringList &groups )
{
beginResetModel();
mRootItem.reset( new QgsMeshDatasetGroupTreeItem() );
for ( const QString &groupName : groups )
{
QgsMeshDatasetGroupTreeItem *item = new QgsMeshDatasetGroupTreeItem( groupName, mRootItem.get() );
mRootItem->appendChild( item );
}
endResetModel();
}
/////////////////////////////////////////////////////////////////////////////////////////
QgsMeshDatasetGroupTreeView::QgsMeshDatasetGroupTreeView( QWidget *parent )
: QTreeView( parent )
{
setModel( &mModel );
setSelectionMode( QAbstractItemView::SingleSelection ) ;
connect( selectionModel(),
&QItemSelectionModel::selectionChanged,
this,
&QgsMeshDatasetGroupTreeView::onSelectionChanged
);
}
void QgsMeshDatasetGroupTreeView::setLayer( QgsMeshLayer *layer )
{
if ( layer != mMeshLayer )
{
mMeshLayer = layer;
syncToLayer();
}
}
QVector<int> QgsMeshDatasetGroupTreeView::datasetsInActiveGroup() const
{
if ( mGroups.constFind( mActiveGroup ) == mGroups.constEnd() )
return QVector<int>();
else
return mGroups[mActiveGroup];
}
void QgsMeshDatasetGroupTreeView::onSelectionChanged( const QItemSelection &selected, const QItemSelection &deselected )
{
Q_UNUSED( deselected );
if ( selected.isEmpty() )
{
mActiveGroup = QString();
return;
}
if ( selected.first().indexes().isEmpty() )
{
mActiveGroup = QString();
return;
}
QModelIndex index = selected.first().indexes().first(); //single selection only
QVariant name = mModel.data( index, 0 );
mActiveGroup = name.toString();
emit activeGroupChanged();
}
void QgsMeshDatasetGroupTreeView::extractGroups()
{
// TODO replace with MDAL groups when introduced
mGroups.clear();
if ( !mMeshLayer || !mMeshLayer->dataProvider() )
return;
for ( int i = 0; i < mMeshLayer->dataProvider()->datasetCount(); ++i )
{
const QgsMeshDatasetMetadata meta = mMeshLayer->dataProvider()->datasetMetadata( i );
QString name = meta.extraOptions()["name"];
if ( mGroups.constFind( name ) == mGroups.constEnd() )
{
QVector<int> datasets;
datasets.append( i );
mGroups[name] = datasets;
}
else
{
mGroups[name].append( i );
}
}
}
void QgsMeshDatasetGroupTreeView::syncToLayer()
{
mActiveGroup.clear();
extractGroups();
mModel.setupModelData( mGroups.keys() );
int index = setActiveGroupFromActiveDataset();
if ( mGroups.size() > index )
setCurrentIndex( mModel.index( index, 0 ) );
}
int QgsMeshDatasetGroupTreeView::setActiveGroupFromActiveDataset()
{
// find active dataset
int activeDataset = -1;
if ( mMeshLayer )
{
activeDataset = mMeshLayer->activeScalarDataset();
if ( activeDataset == -1 )
activeDataset = mMeshLayer->activeVectorDataset();
}
// find group that contains active dataset
int index = 0;
if ( activeDataset > -1 )
{
for ( auto it = mGroups.constBegin(); it != mGroups.constEnd(); ++it )
{
int datasetIndex = it.value().indexOf( activeDataset );
if ( datasetIndex > -1 )
{
mActiveGroup = it.key();
return index;
}
else
{
++index;
}
}
}
// not found return first item in the list
mActiveGroup = QString();
return 0;
}

View File

@ -0,0 +1,137 @@
/***************************************************************************
qgsmeshdatasetgrouptreeview.h
-----------------------------
begin : June 2018
copyright : (C) 2018 by Peter Petrik
email : zilolv 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 QGSMESHDATASETGROUPTREE_H
#define QGSMESHDATASETGROUPTREE_H
#include "qgis_app.h"
#include <QObject>
#include <QTreeView>
#include <QMap>
#include <QVector>
#include <QItemSelection>
#include <QStandardItemModel>
#include <QList>
#include <memory>
class QgsMeshLayer;
/**
* Tree item for display of the mesh dataset groups.
* Dataset group is set of datasets with the same name,
* but different control variable (e.g. time)
*
* Support for multiple levels, because groups can have
* subgroups, for example
*
* Groups:
* Depth
* - Maximum/Depth
* Velocity
* Wind speed
* - Maximum/Wind Speed
*/
class APP_NO_EXPORT QgsMeshDatasetGroupTreeItem
{
public:
QgsMeshDatasetGroupTreeItem( QgsMeshDatasetGroupTreeItem *parent = nullptr );
QgsMeshDatasetGroupTreeItem( const QString &name, QgsMeshDatasetGroupTreeItem *parent = nullptr );
~QgsMeshDatasetGroupTreeItem();
void appendChild( QgsMeshDatasetGroupTreeItem *node );
QgsMeshDatasetGroupTreeItem *child( int row ) const;
int columnCount() const;
int childCount() const;
QgsMeshDatasetGroupTreeItem *parentItem() const;
int row() const;
QVariant data( int column ) const;
private:
QgsMeshDatasetGroupTreeItem *mParent = nullptr;
QList< QgsMeshDatasetGroupTreeItem * > mChildren;
// Data
QString mName;
};
/**
* Item Model for QgsMeshDatasetGroupTreeItem
*/
class APP_NO_EXPORT QgsMeshDatasetGroupTreeModel : public QAbstractItemModel
{
Q_OBJECT
public:
explicit QgsMeshDatasetGroupTreeModel( QObject *parent = nullptr );
~QgsMeshDatasetGroupTreeModel();
QVariant data( const QModelIndex &index, int role ) const override;
Qt::ItemFlags flags( const QModelIndex &index ) const override;
QVariant headerData( int section, Qt::Orientation orientation,
int role = Qt::DisplayRole ) const override;
QModelIndex index( int row, int column,
const QModelIndex &parent = QModelIndex() ) const override;
QModelIndex parent( const QModelIndex &index ) const override;
int rowCount( const QModelIndex &parent = QModelIndex() ) const override;
int columnCount( const QModelIndex &parent = QModelIndex() ) const override;
//! Add groups to the model
void setupModelData( const QStringList &groups );
private:
std::unique_ptr<QgsMeshDatasetGroupTreeItem> mRootItem;
};
/**
* Tree widget for display of the mesh dataset groups.
*
* One dataset group is selected (active)
*/
class APP_EXPORT QgsMeshDatasetGroupTreeView : public QTreeView
{
Q_OBJECT
public:
QgsMeshDatasetGroupTreeView( QWidget *parent = nullptr );
~QgsMeshDatasetGroupTreeView() = default;
//! Associates mesh layer with the widget
void setLayer( QgsMeshLayer *layer );
//! Returns all the dataset indexes in the active group
QVector<int> datasetsInActiveGroup() const;
//! Synchronize widgets state with associated mesh layer
void syncToLayer();
signals:
//! Selected dataset group changed
void activeGroupChanged();
private slots:
void onSelectionChanged( const QItemSelection &selected, const QItemSelection &deselected );
private:
void extractGroups();
int setActiveGroupFromActiveDataset();
QgsMeshDatasetGroupTreeModel mModel;
QgsMeshLayer *mMeshLayer = nullptr; // not owned
QMap<QString, QVector<int>> mGroups; // group name -> dataset indices
QString mActiveGroup;
};
#endif // QGSMESHDATASETGROUPTREE_H

View File

@ -0,0 +1,197 @@
/***************************************************************************
qgsmeshlayerproperties.cpp
--------------------------
begin : Jun 2018
copyright : (C) 2018 by Peter Petrik
email : zilolv 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 <limits>
#include <typeinfo>
#include "qgisapp.h"
#include "qgsapplication.h"
#include "qgscoordinatetransform.h"
#include "qgshelp.h"
#include "qgslogger.h"
#include "qgsmapcanvas.h"
#include "qgsmaplayerstylemanager.h"
#include "qgsmeshlayer.h"
#include "qgsmeshlayerproperties.h"
#include "qgsproject.h"
#include "qgsprojectionselectiondialog.h"
#include "qgsrenderermeshpropertieswidget.h"
#include "qgssettings.h"
#include <QFileDialog>
#include <QMessageBox>
QgsMeshLayerProperties::QgsMeshLayerProperties( QgsMapLayer *lyr, QgsMapCanvas *canvas, QWidget *parent, Qt::WindowFlags fl )
: QgsOptionsDialogBase( QStringLiteral( "MeshLayerProperties" ), parent, fl )
, mMeshLayer( qobject_cast<QgsMeshLayer *>( lyr ) )
{
Q_ASSERT( mMeshLayer );
setupUi( this );
mRendererMeshPropertiesWidget = new QgsRendererMeshPropertiesWidget( mMeshLayer, canvas, this );
mOptsPage_StyleContent->layout()->addWidget( mRendererMeshPropertiesWidget );
connect( mLayerOrigNameLineEd, &QLineEdit::textEdited, this, &QgsMeshLayerProperties::updateLayerName );
connect( mCrsSelector, &QgsProjectionSelectionWidget::crsChanged, this, &QgsMeshLayerProperties::changeCrs );
connect( mAddDatasetButton, &QPushButton::clicked, this, &QgsMeshLayerProperties::addDataset );
// QgsOptionsDialogBase handles saving/restoring of geometry, splitter and current tab states,
// switching vertical tabs between icon/text to icon-only modes (splitter collapsed to left),
// and connecting QDialogButtonBox's accepted/rejected signals to dialog's accept/reject slots
initOptionsBase( false );
connect( lyr->styleManager(), &QgsMapLayerStyleManager::currentStyleChanged, this, &QgsMeshLayerProperties::syncAndRepaint );
connect( this, &QDialog::accepted, this, &QgsMeshLayerProperties::apply );
connect( buttonBox->button( QDialogButtonBox::Apply ), &QAbstractButton::clicked, this, &QgsMeshLayerProperties::apply );
connect( mMeshLayer, &QgsMeshLayer::dataChanged, this, &QgsMeshLayerProperties::syncAndRepaint );
// update based on lyr's current state
syncToLayer();
QgsSettings settings;
// if dialog hasn't been opened/closed yet, default to Styles tab, which is used most often
// this will be read by restoreOptionsBaseUi()
if ( !settings.contains( QStringLiteral( "/Windows/MeshLayerProperties/tab" ) ) )
{
settings.setValue( QStringLiteral( "Windows/MeshLayerProperties/tab" ),
mOptStackedWidget->indexOf( mOptsPage_Style ) );
}
QString title = QString( tr( "Layer Properties - %1" ) ).arg( lyr->name() );
if ( !mMeshLayer->styleManager()->isDefault( mMeshLayer->styleManager()->currentStyle() ) )
title += QStringLiteral( " (%1)" ).arg( mMeshLayer->styleManager()->currentStyle() );
restoreOptionsBaseUi( title );
}
void QgsMeshLayerProperties::syncToLayer()
{
Q_ASSERT( mRendererMeshPropertiesWidget );
QgsDebugMsg( "populate general information tab" );
/*
* Information Tab
*/
QString info;
if ( mMeshLayer->dataProvider() )
{
info += QStringLiteral( "<table>" );
info += QStringLiteral( "<tr><td>%1: </td><td>%2</td><tr>" ).arg( tr( "Uri" ) ).arg( mMeshLayer->dataProvider()->dataSourceUri() );
info += QStringLiteral( "<tr><td>%1: </td><td>%2</td><tr>" ).arg( tr( "Vertex count" ) ).arg( mMeshLayer->dataProvider()->vertexCount() );
info += QStringLiteral( "<tr><td>%1: </td><td>%2</td><tr>" ).arg( tr( "Face count" ) ).arg( mMeshLayer->dataProvider()->faceCount() );
info += QStringLiteral( "<tr><td>%1: </td><td>%2</td><tr>" ).arg( tr( "Dataset count" ) ).arg( mMeshLayer->dataProvider()->datasetCount() );
info += QStringLiteral( "</table>" );
}
else
{
info += tr( "Invalid data provider" );
}
mInformationTextBrowser->setText( info );
QgsDebugMsg( "populate source tab" );
/*
* Source Tab
*/
mLayerOrigNameLineEd->setText( mMeshLayer->name() );
leDisplayName->setText( mMeshLayer->name() );
if ( mMeshLayer && mMeshLayer->dataProvider() )
{
mUriLabel->setText( mMeshLayer->dataProvider()->dataSourceUri() );
}
else
{
mUriLabel->setText( tr( "Not assigned" ) );
}
QgsDebugMsg( "populate styling tab" );
/*
* Styling Tab
*/
mRendererMeshPropertiesWidget->syncToLayer();
}
void QgsMeshLayerProperties::addDataset()
{
if ( !mMeshLayer->dataProvider() )
return;
QgsSettings settings;
QString openFileDir = settings.value( QStringLiteral( "lastMeshDatasetDir" ), QDir::homePath(), QgsSettings::App ).toString();
QString openFileString = QFileDialog::getOpenFileName( nullptr, tr( "Load mesh datasets" ), openFileDir, tr( "Layout mesh datasets" ) + " (*.*)" );
if ( openFileString.isEmpty() )
{
return; //canceled by the user
}
QFileInfo openFileInfo( openFileString );
settings.setValue( QStringLiteral( "lastMeshDatasetDir" ), openFileInfo.absolutePath(), QgsSettings::App );
QFile datasetFile( openFileString );
bool ok = mMeshLayer->dataProvider()->addDataset( openFileString );
if ( ok )
{
syncToLayer();
QMessageBox::information( this, tr( "Load mesh datasets" ), tr( "Datasets successfully added to the mesh layer" ) );
}
else
{
QMessageBox::warning( this, tr( "Load mesh datasets" ), tr( "Could not read mesh dataset." ) );
}
}
void QgsMeshLayerProperties::apply()
{
Q_ASSERT( mRendererMeshPropertiesWidget );
QgsDebugMsg( "processing general tab" );
/*
* General Tab
*/
mMeshLayer->setName( mLayerOrigNameLineEd->text() );
QgsDebugMsg( "processing style tab" );
/*
* Style Tab
*/
mRendererMeshPropertiesWidget->apply();
//make sure the layer is redrawn
mMeshLayer->triggerRepaint();
// notify the project we've made a change
QgsProject::instance()->setDirty( true );
}
void QgsMeshLayerProperties::changeCrs( const QgsCoordinateReferenceSystem &crs )
{
mMeshLayer->setCrs( crs );
}
void QgsMeshLayerProperties::updateLayerName( const QString &text )
{
leDisplayName->setText( mMeshLayer->formatLayerName( text ) );
}
void QgsMeshLayerProperties::syncAndRepaint()
{
syncToLayer();
mMeshLayer->triggerRepaint();
}

View File

@ -0,0 +1,72 @@
/***************************************************************************
qgsmeshlayerproperties.h
------------------------
begin : Jun 2018
copyright : (C) 2018 by Peter Petrik
email : zilolv 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 QGSMESHLAYERPROPERTIES_H
#define QGSMESHLAYERPROPERTIES_H
#include "ui_qgsmeshlayerpropertiesbase.h"
#include "qgsoptionsdialogbase.h"
#include "qgsguiutils.h"
#include "qgis_app.h"
class QgsMapLayer;
class QgsMapCanvas;
class QgsMeshLayer;
class QgsRendererMeshPropertiesWidget;
/**
* Property sheet for a mesh map layer.
* Contains information, source and style tabs
*/
class APP_EXPORT QgsMeshLayerProperties : public QgsOptionsDialogBase, private Ui::QgsMeshLayerPropertiesBase
{
Q_OBJECT
public:
/**
* \brief Constructor
* \param lyr Mesh map layer for which properties will be displayed
*/
QgsMeshLayerProperties( QgsMapLayer *lyr, QgsMapCanvas *canvas, QWidget *parent = nullptr, Qt::WindowFlags = QgsGuiUtils::ModalDialogFlags );
~QgsMeshLayerProperties() = default;
private slots:
//! Synchronize widgets state with associated mesh layer
void syncToLayer();
//!Applies the settings made in the dialog without closing the box
void apply();
//! \brief Slot to update layer display name as original is edited.
void updateLayerName( const QString &text );
//! Synchronize GUI state with associated mesh layer and trigger repaint
void syncAndRepaint();
//! Change layer coordinate reference system
void changeCrs( const QgsCoordinateReferenceSystem &crs );
//! Associate dataset to the mesh layer
void addDataset();
private:
//! Pointer to the mesh styling widget
QgsRendererMeshPropertiesWidget *mRendererMeshPropertiesWidget = nullptr;
//! \brief Pointer to the mesh layer that this property dilog changes the behavior of.
QgsMeshLayer *mMeshLayer = nullptr;
};
#endif // QGSMESHLAYERPROPERTIES_H

View File

@ -0,0 +1,146 @@
/***************************************************************************
qgsmeshrendereractivedatasetwidget.cpp
---------------------------------------
begin : June 2018
copyright : (C) 2018 by Peter Petrik
email : zilolv 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 "qgsmeshrendereractivedatasetwidget.h"
#include "qgis.h"
#include "qgsmeshlayer.h"
#include "qgsmessagelog.h"
#include "qgsmeshrenderersettings.h"
QgsMeshRendererActiveDatasetWidget::QgsMeshRendererActiveDatasetWidget( QWidget *parent )
: QWidget( parent )
{
setupUi( this );
connect( mDatasetGroupTreeView, &QgsMeshDatasetGroupTreeView::activeGroupChanged, this, &QgsMeshRendererActiveDatasetWidget::onActiveGroupChanged );
connect( mDatasetSlider, &QSlider::valueChanged, this, &QgsMeshRendererActiveDatasetWidget::onActiveDatasetChanged );
}
void QgsMeshRendererActiveDatasetWidget::setLayer( QgsMeshLayer *layer )
{
if ( layer != mMeshLayer )
{
mMeshLayer = layer;
}
mDatasetGroupTreeView->setLayer( layer );
setEnabled( mMeshLayer );
syncToLayer();
}
int QgsMeshRendererActiveDatasetWidget::activeScalarDataset() const
{
return mActiveScalarDataset;
}
int QgsMeshRendererActiveDatasetWidget::activeVectorDataset() const
{
return mActiveVectorDataset;
}
void QgsMeshRendererActiveDatasetWidget::onActiveGroupChanged()
{
const QVector<int> datasets = mDatasetGroupTreeView->datasetsInActiveGroup();
mDatasetSlider->setMinimum( 0 );
mDatasetSlider->setMaximum( datasets.size() - 1 );
mDatasetSlider->setValue( 0 );
}
void QgsMeshRendererActiveDatasetWidget::onActiveDatasetChanged( int value )
{
int datasetIndex = -1;
const QVector<int> datasets = mDatasetGroupTreeView->datasetsInActiveGroup();
mActiveScalarDataset = -1;
mActiveVectorDataset = -1;
if ( datasets.size() > value && mMeshLayer && mMeshLayer->dataProvider() )
{
datasetIndex = datasets[value];
const QgsMeshDatasetMetadata meta = mMeshLayer->dataProvider()->datasetMetadata( datasetIndex );
mActiveScalarDataset = datasetIndex;
if ( meta.isVector() )
mActiveVectorDataset = datasetIndex;
}
updateMetadata( datasetIndex );
emit activeScalarDatasetChanged( activeScalarDataset() );
emit activeVectorDatasetChanged( activeVectorDataset() );
emit widgetChanged();
}
void QgsMeshRendererActiveDatasetWidget::updateMetadata( int datasetIndex )
{
if ( datasetIndex == -1 )
{
mActiveDatasetMetadata->setText( tr( "No dataset selected" ) );
}
else
{
const QgsMeshDatasetMetadata meta = mMeshLayer->dataProvider()->datasetMetadata( datasetIndex );
QString msg;
msg += QStringLiteral( "<table>" );
msg += QStringLiteral( "<tr><td>%1</td><td>%2</td></tr>" )
.arg( tr( "Is on vertices" ) )
.arg( meta.isOnVertices() ? tr( "Yes" ) : tr( "No" ) );
msg += QStringLiteral( "<tr><td>%1</td><td>%2</td></tr>" )
.arg( tr( "Is vector" ) )
.arg( meta.isVector() ? tr( "Yes" ) : tr( "No" ) );
for ( auto it = meta.extraOptions().constBegin(); it != meta.extraOptions().constEnd(); ++it )
{
msg += QStringLiteral( "<tr><td>%1</td><td>%2</td></tr>" ).arg( it.key() ).arg( it.value() );
}
msg += QStringLiteral( "</table>" );
mActiveDatasetMetadata->setText( msg );
}
}
int QgsMeshRendererActiveDatasetWidget::datasetIndex() const
{
const QVector<int> datasets = mDatasetGroupTreeView->datasetsInActiveGroup();
int value = mDatasetSlider->value();
int datasetIndex = -1;
if ( value < datasets.size() )
{
datasetIndex = datasets[value];
}
return datasetIndex;
}
void QgsMeshRendererActiveDatasetWidget::syncToLayer()
{
mDatasetGroupTreeView->syncToLayer();
if ( mMeshLayer )
{
mActiveScalarDataset = mMeshLayer->activeScalarDataset();
mActiveVectorDataset = mMeshLayer->activeVectorDataset();
}
else
{
mActiveScalarDataset = -1;
mActiveVectorDataset = -1;
}
if ( mActiveScalarDataset != -1 )
whileBlocking( mDatasetSlider )->setValue( mActiveScalarDataset );
}

View File

@ -0,0 +1,82 @@
/***************************************************************************
qgsmeshrendereractivedatasetwidget.h
-------------------------------------
begin : June 2018
copyright : (C) 2018 by Peter Petrik
email : zilolv 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 QGSMESHRENDERERACTIVEDATASETWIDGET_H
#define QGSMESHRENDERERACTIVEDATASETWIDGET_H
#include "ui_qgsmeshrendereractivedatasetwidgetbase.h"
#include "qgis_app.h"
#include <QWidget>
class QgsMeshLayer;
/**
* Widget for selection of active dataset group from tree view.
* Also selects the active scalar and vector dataset by slider
*
* At the moment, it is not possible to select different vector and
* scalar dataset
*/
class APP_EXPORT QgsMeshRendererActiveDatasetWidget : public QWidget, private Ui::QgsMeshRendererActiveDatasetWidgetBase
{
Q_OBJECT
public:
/**
* A widget to hold the renderer scalar settings for a mesh layer.
* \param parent Parent object
*/
QgsMeshRendererActiveDatasetWidget( QWidget *parent = nullptr );
~QgsMeshRendererActiveDatasetWidget() = default;
//! Associates mesh layer with the widget
void setLayer( QgsMeshLayer *layer );
//! Gets index of the selected/active scalar dataset
int activeScalarDataset() const;
//! Gets index of the selected/active vector dataset
int activeVectorDataset() const;
//! Synchronizes widgets state with associated mesh layer
void syncToLayer();
signals:
//! Emitted when active scalar dataset changed
void activeScalarDatasetChanged( int index );
//! Emitted when active vector dataset changed
void activeVectorDatasetChanged( int index );
//! Emitted when any settings related to rendering changed
void widgetChanged();
private slots:
void onActiveGroupChanged();
void onActiveDatasetChanged( int value );
void updateMetadata( int datasetIndex );
private:
int datasetIndex() const;
QgsMeshLayer *mMeshLayer = nullptr; // not owned
int mActiveScalarDataset = -1;
int mActiveVectorDataset = -1;
};
#endif // QGSMESHRENDERERSCALARSETTINGSWIDGET_H

View File

@ -0,0 +1,73 @@
/***************************************************************************
qgsmeshrenderermeshsettingswidget.cpp
---------------------------------------
begin : June 2018
copyright : (C) 2018 by Peter Petrik
email : zilolv 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 "qgsmeshrenderermeshsettingswidget.h"
#include <QtGlobal>
#include "qgis.h"
#include "qgsmapcanvas.h"
#include "qgsmeshlayer.h"
#include "qgsrasterlayer.h"
#include "raster/qgscolorrampshaderwidget.h"
#include "raster/qgsrasterminmaxwidget.h"
#include "qgsrasterminmaxorigin.h"
#include "qgsmessagelog.h"
#include "qgscolorbutton.h"
#include "qgsdoublespinbox.h"
QgsMeshRendererMeshSettingsWidget::QgsMeshRendererMeshSettingsWidget( QWidget *parent )
: QWidget( parent )
{
setupUi( this );
connect( mColorWidget, &QgsColorButton::colorChanged, this, &QgsMeshRendererMeshSettingsWidget::widgetChanged );
connect( mLineWidthSpinBox, QOverload<double>::of( &QgsDoubleSpinBox::valueChanged ),
this, &QgsMeshRendererMeshSettingsWidget::widgetChanged );
}
void QgsMeshRendererMeshSettingsWidget::setLayer( QgsMeshLayer *layer, bool isTriangularMesh )
{
mIsTriangularMesh = isTriangularMesh;
if ( layer != mMeshLayer )
{
mMeshLayer = layer;
syncToLayer();
}
}
QgsMeshRendererMeshSettings QgsMeshRendererMeshSettingsWidget::settings() const
{
QgsMeshRendererMeshSettings settings;
settings.setColor( mColorWidget->color() );
settings.setLineWidth( mLineWidthSpinBox->value() );
return settings;
}
void QgsMeshRendererMeshSettingsWidget::syncToLayer( )
{
if ( !mMeshLayer )
return;
QgsMeshRendererMeshSettings settings;
if ( mIsTriangularMesh )
settings = mMeshLayer->rendererTriangularMeshSettings();
else
settings = mMeshLayer->rendererNativeMeshSettings();
mColorWidget->setColor( settings.color() );
mLineWidthSpinBox->setValue( settings.lineWidth() );
}

View File

@ -0,0 +1,72 @@
/***************************************************************************
qgsmeshrenderermeshsettingswidget.h
-------------------------------------
begin : June 2018
copyright : (C) 2018 by Peter Petrik
email : zilolv 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 QGSMESHRENDERERMESHSETTINGSWIDGET_H
#define QGSMESHRENDERERMESHSETTINGSWIDGET_H
#include "ui_qgsmeshrenderermeshsettingswidgetbase.h"
#include "qgsmeshrenderersettings.h"
#include "qgis_app.h"
#include <QWidget>
class QgsMeshLayer;
/**
* A widget for setup of the mesh frame settings of
* the mesh layer. Can be used for both native and
* triangular mesh renderer settings.
*/
class APP_EXPORT QgsMeshRendererMeshSettingsWidget : public QWidget, private Ui::QgsMeshRendererMeshSettingsWidgetBase
{
Q_OBJECT
public:
/**
* A widget to hold the renderer mesh settings for a mesh layer.
* \param parent Parent object
*/
QgsMeshRendererMeshSettingsWidget( QWidget *parent = nullptr );
~QgsMeshRendererMeshSettingsWidget() = default;
/**
* Associates mesh layer with the widget
* \param layer mesh layer that contains mesh frame
* \param isTriangularMesh whether use settings for triangular mesh or native mesh
*/
void setLayer( QgsMeshLayer *layer, bool isTriangularMesh );
//! Returns the mesh rendering settings (native or triangular)
QgsMeshRendererMeshSettings settings() const;
//! Synchronizes widgets state with associated mesh layer
void syncToLayer();
signals:
//! Mesh rendering settings changed
void widgetChanged();
private:
QgsMeshLayer *mMeshLayer = nullptr; // not owned
/**
* If true, the widget works for triangular (derived) mesh
* If false, the widget works for native mesh
*/
bool mIsTriangularMesh = true;
};
#endif // QGSMESHRENDERERMESHSETTINGSWIDGET_H

View File

@ -0,0 +1,145 @@
/***************************************************************************
qgsmeshrendererscalarsettingswidget.cpp
---------------------------------------
begin : June 2018
copyright : (C) 2018 by Peter Petrik
email : zilolv 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 "qgsmeshrendererscalarsettingswidget.h"
#include "qgis.h"
#include "qgsmeshlayer.h"
#include "qgsmessagelog.h"
QgsMeshRendererScalarSettingsWidget::QgsMeshRendererScalarSettingsWidget( QWidget *parent )
: QWidget( parent )
{
setupUi( this );
connect( mScalarRecalculateMinMaxButton, &QPushButton::clicked, this, &QgsMeshRendererScalarSettingsWidget::recalculateMinMaxButtonClicked );
connect( mScalarMinLineEdit, &QLineEdit::textChanged, this, &QgsMeshRendererScalarSettingsWidget::minMaxChanged );
connect( mScalarMaxLineEdit, &QLineEdit::textChanged, this, &QgsMeshRendererScalarSettingsWidget::minMaxChanged );
connect( mScalarMinLineEdit, &QLineEdit::textEdited, this, &QgsMeshRendererScalarSettingsWidget::minMaxEdited );
connect( mScalarMaxLineEdit, &QLineEdit::textEdited, this, &QgsMeshRendererScalarSettingsWidget::minMaxEdited );
connect( mScalarColorRampShaderWidget, &QgsColorRampShaderWidget::widgetChanged, this, &QgsMeshRendererScalarSettingsWidget::widgetChanged );
}
void QgsMeshRendererScalarSettingsWidget::setLayer( QgsMeshLayer *layer )
{
if ( layer != mMeshLayer )
{
mMeshLayer = layer;
syncToLayer();
}
}
QgsMeshRendererScalarSettings QgsMeshRendererScalarSettingsWidget::settings() const
{
QgsMeshRendererScalarSettings settings;
settings.setColorRampShader( mScalarColorRampShaderWidget->shader() );
return settings;
}
void QgsMeshRendererScalarSettingsWidget::syncToLayer( )
{
if ( !mMeshLayer )
return;
if ( mMeshLayer->rendererScalarSettings().isEnabled() )
{
const QgsColorRampShader shader = mMeshLayer->rendererScalarSettings().colorRampShader();
whileBlocking( mScalarMinLineEdit )->setText( QString::number( shader.minimumValue() ) );
whileBlocking( mScalarMaxLineEdit )->setText( QString::number( shader.maximumValue() ) );
whileBlocking( mScalarColorRampShaderWidget )->setFromShader( shader );
}
}
double QgsMeshRendererScalarSettingsWidget::lineEditValue( const QLineEdit *lineEdit ) const
{
if ( lineEdit->text().isEmpty() )
{
return std::numeric_limits<double>::quiet_NaN();
}
return lineEdit->text().toDouble();
}
void QgsMeshRendererScalarSettingsWidget::minMaxChanged()
{
double min = lineEditValue( mScalarMinLineEdit );
double max = lineEditValue( mScalarMaxLineEdit );
mScalarColorRampShaderWidget->setMinMax( min, max );
}
void QgsMeshRendererScalarSettingsWidget::minMaxEdited()
{
double min = lineEditValue( mScalarMinLineEdit );
double max = lineEditValue( mScalarMaxLineEdit );
mScalarColorRampShaderWidget->setMinMaxAndClassify( min, max );
}
void QgsMeshRendererScalarSettingsWidget::recalculateMinMaxButtonClicked()
{
double min, max;
calcMinMax( mActiveDataset, min, max );
whileBlocking( mScalarMinLineEdit )->setText( QString::number( min ) );
whileBlocking( mScalarMaxLineEdit )->setText( QString::number( max ) );
mScalarColorRampShaderWidget->setMinMaxAndClassify( min, max );
}
void QgsMeshRendererScalarSettingsWidget::setActiveDataset( int activeDataset )
{
mActiveDataset = activeDataset;
}
void QgsMeshRendererScalarSettingsWidget::calcMinMax( int datasetIndex, double &min, double &max ) const
{
if ( !mMeshLayer )
return;
if ( !mMeshLayer->dataProvider() )
return;
const QgsMeshDatasetMetadata metadata = mMeshLayer->dataProvider()->datasetMetadata( datasetIndex );
bool scalarDataOnVertices = metadata.isOnVertices();
int count;
if ( scalarDataOnVertices )
count = mMeshLayer->dataProvider()->vertexCount();
else
count = mMeshLayer->dataProvider()->faceCount();
bool myFirstIterationFlag = true;
for ( int i = 0; i < count; ++i )
{
double myValue = mMeshLayer->dataProvider()->datasetValue( datasetIndex, i ).scalar();
if ( std::isnan( myValue ) ) continue; // NULL
if ( myFirstIterationFlag )
{
myFirstIterationFlag = false;
min = myValue;
max = myValue;
}
else
{
if ( myValue < min )
{
min = myValue;
}
if ( myValue > max )
{
max = myValue;
}
}
}
}

View File

@ -0,0 +1,75 @@
/***************************************************************************
qgsmeshrendererscalarsettingswidget.h
-------------------------------------
begin : June 2018
copyright : (C) 2018 by Peter Petrik
email : zilolv 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 QGSMESHRENDERERSCALARSETTINGSWIDGET_H
#define QGSMESHRENDERERSCALARSETTINGSWIDGET_H
#include "ui_qgsmeshrendererscalarsettingswidgetbase.h"
#include "qgis_app.h"
#include "qgsmeshrenderersettings.h"
#include <QWidget>
class QgsMeshLayer;
/*!
* A widget for setup of the scalar dataset renderer settings of
* a mesh layer. The layer must be connected and an active dataset
* must be selected.
*/
class APP_EXPORT QgsMeshRendererScalarSettingsWidget : public QWidget, private Ui::QgsMeshRendererScalarSettingsWidgetBase
{
Q_OBJECT
public:
/**
* A widget to hold the renderer scalar settings for a mesh layer.
* \param parent Parent object
*/
QgsMeshRendererScalarSettingsWidget( QWidget *parent = nullptr );
~QgsMeshRendererScalarSettingsWidget() = default;
//! Associates mesh layer with the widget
void setLayer( QgsMeshLayer *layer );
//! Returns scalar settings
QgsMeshRendererScalarSettings settings() const;
//! Synchronizes widgets state with associated mesh layer
void syncToLayer();
signals:
//! Mesh rendering settings changed
void widgetChanged();
public slots:
//! Set active scalar dataset to be used
void setActiveDataset( int activeDatase );
private slots:
void minMaxChanged();
void minMaxEdited();
void recalculateMinMaxButtonClicked();
private:
double lineEditValue( const QLineEdit *lineEdit ) const;
void calcMinMax( int datasetIndex, double &min, double &max ) const;
QgsMeshLayer *mMeshLayer = nullptr; // not owned
int mActiveDataset = -1;
};
#endif // QGSMESHRENDERERSCALARSETTINGSWIDGET_H

View File

@ -0,0 +1,155 @@
/***************************************************************************
qgsmeshrenderervectorsettingswidget.cpp
---------------------------------------
begin : June 2018
copyright : (C) 2018 by Peter Petrik
email : zilolv 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 "qgsmeshrenderervectorsettingswidget.h"
#include "qgis.h"
#include "qgsmeshlayer.h"
#include "qgsmessagelog.h"
QgsMeshRendererVectorSettingsWidget::QgsMeshRendererVectorSettingsWidget( QWidget *parent )
: QWidget( parent )
{
setupUi( this );
connect( mColorWidget, &QgsColorButton::colorChanged, this, &QgsMeshRendererVectorSettingsWidget::widgetChanged );
connect( mLineWidthSpinBox, QOverload<double>::of( &QgsDoubleSpinBox::valueChanged ),
this, &QgsMeshRendererVectorSettingsWidget::widgetChanged );
connect( mShaftLengthComboBox, QOverload<int>::of( &QComboBox::currentIndexChanged ),
this, &QgsMeshRendererVectorSettingsWidget::widgetChanged );
connect( mShaftLengthComboBox, QOverload<int>::of( &QComboBox::currentIndexChanged ),
mShaftOptionsStackedWidget, &QStackedWidget::setCurrentIndex );
QVector<QLineEdit *> widgets;
widgets << mMinMagLineEdit << mMaxMagLineEdit
<< mHeadWidthLineEdit << mHeadLengthLineEdit
<< mMinimumShaftLineEdit << mMaximumShaftLineEdit
<< mScaleShaftByFactorOfLineEdit << mShaftLengthLineEdit;
for ( auto widget : widgets )
{
connect( widget, &QLineEdit::textChanged, this, &QgsMeshRendererVectorSettingsWidget::widgetChanged );
}
}
void QgsMeshRendererVectorSettingsWidget::setLayer( QgsMeshLayer *layer )
{
if ( layer != mMeshLayer )
{
mMeshLayer = layer;
syncToLayer();
}
}
QgsMeshRendererVectorSettings QgsMeshRendererVectorSettingsWidget::settings() const
{
QgsMeshRendererVectorSettings settings;
// basic
settings.setColor( mColorWidget->color() );
settings.setLineWidth( mLineWidthSpinBox->value() );
// filter by magnitude
double val = filterValue( mMinMagLineEdit->text(), -1 );
settings.setFilterMin( val );
val = filterValue( mMaxMagLineEdit->text(), -1 );
settings.setFilterMax( val );
// arrow head
val = filterValue( mHeadWidthLineEdit->text(), settings.arrowHeadWidthRatio() * 100.0 );
settings.setArrowHeadWidthRatio( val / 100.0 );
val = filterValue( mHeadLengthLineEdit->text(), settings.arrowHeadLengthRatio() * 100.0 );
settings.setArrowHeadLengthRatio( val / 100.0 );
// shaft length
auto method = static_cast<QgsMeshRendererVectorSettings::ArrowScalingMethod>( mShaftLengthComboBox->currentIndex() );
settings.setShaftLengthMethod( method );
val = filterValue( mMinimumShaftLineEdit->text(), settings.minShaftLength() );
settings.setMinShaftLength( val );
val = filterValue( mMaximumShaftLineEdit->text(), settings.maxShaftLength() );
settings.setMaxShaftLength( val );
val = filterValue( mScaleShaftByFactorOfLineEdit->text(), settings.scaleFactor() );
settings.setScaleFactor( val );
val = filterValue( mShaftLengthLineEdit->text(), settings.fixedShaftLength() );
settings.setFixedShaftLength( val );
return settings;
}
void QgsMeshRendererVectorSettingsWidget::setActiveDataset( int activeDataset )
{
mActiveDataset = activeDataset;
}
void QgsMeshRendererVectorSettingsWidget::syncToLayer( )
{
if ( !mMeshLayer )
return;
QgsMeshRendererVectorSettings settings = mMeshLayer->rendererVectorSettings();
// basic
mColorWidget->setColor( settings.color() );
mLineWidthSpinBox->setValue( settings.lineWidth() );
// filter by magnitude
if ( settings.filterMin() > 0 )
{
mMinMagLineEdit->setText( QString::number( settings.filterMin() ) );
}
if ( settings.filterMax() > 0 )
{
mMaxMagLineEdit->setText( QString::number( settings.filterMax() ) );
}
// arrow head
mHeadWidthLineEdit->setText( QString::number( settings.arrowHeadWidthRatio() * 100.0 ) );
mHeadLengthLineEdit->setText( QString::number( settings.arrowHeadLengthRatio() * 100.0 ) );
// shaft length
mShaftLengthComboBox->setCurrentIndex( settings.shaftLengthMethod() );
mMinimumShaftLineEdit->setText( QString::number( settings.minShaftLength() ) );
mMaximumShaftLineEdit->setText( QString::number( settings.maxShaftLength() ) );
mScaleShaftByFactorOfLineEdit->setText( QString::number( settings.scaleFactor() ) );
mShaftLengthLineEdit->setText( QString::number( settings.fixedShaftLength() ) );
}
double QgsMeshRendererVectorSettingsWidget::filterValue( const QString &text, double errVal ) const
{
if ( text.isEmpty() )
return errVal;
bool ok;
double val = text.toDouble( &ok );
if ( !ok )
return errVal;
if ( val < 0 )
return errVal;
return val;
}

View File

@ -0,0 +1,75 @@
/***************************************************************************
qgsmeshrenderervectorsettingswidget.h
-------------------------------------
begin : June 2018
copyright : (C) 2018 by Peter Petrik
email : zilolv 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 QGSMESHRENDERERVECTORSETTINGSWIDGET_H
#define QGSMESHRENDERERVECTORSETTINGSWIDGET_H
#include "ui_qgsmeshrenderervectorsettingswidgetbase.h"
#include "qgis_app.h"
#include "qgsmeshrenderersettings.h"
#include <memory>
#include <QWidget>
class QgsMeshLayer;
/**
* A widget for setup of the vector dataset renderer settings of
* a mesh layer. The layer must be connected and an active dataset
* must be selected.
*/
class APP_EXPORT QgsMeshRendererVectorSettingsWidget : public QWidget, private Ui::QgsMeshRendererVectorSettingsWidgetBase
{
Q_OBJECT
public:
/**
* A widget to hold the renderer Vector settings for a mesh layer.
* \param parent Parent object
*/
QgsMeshRendererVectorSettingsWidget( QWidget *parent = nullptr );
~QgsMeshRendererVectorSettingsWidget() = default;
//! Associates mesh layer with the widget
void setLayer( QgsMeshLayer *layer );
//! Returns vector settings
QgsMeshRendererVectorSettings settings() const;
//! Synchronizes widgets state with associated mesh layer
void syncToLayer();
signals:
//! Mesh rendering settings changed
void widgetChanged();
public slots:
//! Set active vector dataset to be used
void setActiveDataset( int activeDataset );
private:
/**
* convert text to double, return err_val if
* text is not possible to convert or the value is negative
*/
double filterValue( const QString &text, double errVal ) const;
QgsMeshLayer *mMeshLayer = nullptr; //not owned
int mActiveDataset = -1;
};
#endif // QGSMESHRENDERERVECTORSETTINGSWIDGET_H

View File

@ -0,0 +1,137 @@
/***************************************************************************
qgsrenderermeshpropertieswidget.cpp
-----------------------------------
begin : June 2018
copyright : (C) 2018 by Peter Petrik
email : zilolv 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 "qgsrenderermeshpropertieswidget.h"
#include "qgis.h"
#include "qgsmapcanvas.h"
#include "qgsmeshlayer.h"
#include "qgsmessagelog.h"
#include "qgsmeshrendererscalarsettingswidget.h"
#include "qgsmeshdatasetgrouptreeview.h"
#include "qgsmeshrendereractivedatasetwidget.h"
QgsRendererMeshPropertiesWidget::QgsRendererMeshPropertiesWidget( QgsMeshLayer *layer, QgsMapCanvas *canvas, QWidget *parent )
: QgsMapLayerConfigWidget( layer, canvas, parent )
, mMeshLayer( layer )
{
if ( !mMeshLayer )
return;
setupUi( this );
connect( mMeshLayer,
&QgsMeshLayer::dataChanged,
this,
&QgsRendererMeshPropertiesWidget::syncToLayer );
mMeshRendererActiveDatasetWidget->setLayer( mMeshLayer );
mMeshRendererScalarSettingsWidget->setLayer( mMeshLayer );
mNativeMeshSettingsWidget->setLayer( mMeshLayer, false );
mTriangularMeshSettingsWidget->setLayer( mMeshLayer, true );
mMeshRendererVectorSettingsWidget->setLayer( mMeshLayer );
connect( mMeshRendererActiveDatasetWidget, &QgsMeshRendererActiveDatasetWidget::activeScalarDatasetChanged,
mMeshRendererScalarSettingsWidget, &QgsMeshRendererScalarSettingsWidget::setActiveDataset );
connect( mMeshRendererActiveDatasetWidget, &QgsMeshRendererActiveDatasetWidget::activeVectorDatasetChanged,
mMeshRendererVectorSettingsWidget, &QgsMeshRendererVectorSettingsWidget::setActiveDataset );
connect( mMeshRendererActiveDatasetWidget, &QgsMeshRendererActiveDatasetWidget::activeVectorDatasetChanged,
this, &QgsRendererMeshPropertiesWidget::enableVectorRenderingTab );
connect( mNativeMeshGroup, &QGroupBox::toggled, this, &QgsPanelWidget::widgetChanged );
connect( mTriangularMeshGroup, &QGroupBox::toggled, this, &QgsPanelWidget::widgetChanged );
connect( mContoursGroupBox, &QGroupBox::toggled, this, &QgsPanelWidget::widgetChanged );
connect( mVectorsGroupBox, &QGroupBox::toggled, this, &QgsPanelWidget::widgetChanged );
connect( mMeshRendererActiveDatasetWidget, &QgsMeshRendererActiveDatasetWidget::widgetChanged, this, &QgsPanelWidget::widgetChanged );
connect( mMeshRendererScalarSettingsWidget, &QgsMeshRendererScalarSettingsWidget::widgetChanged, this, &QgsPanelWidget::widgetChanged );
connect( mMeshRendererVectorSettingsWidget, &QgsMeshRendererVectorSettingsWidget::widgetChanged, this, &QgsPanelWidget::widgetChanged );
connect( mNativeMeshSettingsWidget, &QgsMeshRendererMeshSettingsWidget::widgetChanged,
this, &QgsPanelWidget::widgetChanged );
connect( mTriangularMeshSettingsWidget, &QgsMeshRendererMeshSettingsWidget::widgetChanged,
this, &QgsPanelWidget::widgetChanged );
}
void QgsRendererMeshPropertiesWidget::apply()
{
if ( !mMeshLayer )
return;
// MESH
bool meshRenderingIsEnabled = mNativeMeshGroup->isChecked();
QgsMeshRendererMeshSettings meshSettings = mNativeMeshSettingsWidget->settings();
meshSettings.setEnabled( meshRenderingIsEnabled );
whileBlocking( mMeshLayer )->setRendererNativeMeshSettings( meshSettings );
// TRIANGULAR MESH
bool triangularMeshRenderingIsEnabled = mTriangularMeshGroup->isChecked();
QgsMeshRendererMeshSettings triangularMeshSettings = mTriangularMeshSettingsWidget->settings();
triangularMeshSettings.setEnabled( triangularMeshRenderingIsEnabled );
whileBlocking( mMeshLayer )->setRendererTriangularMeshSettings( triangularMeshSettings );
// SCALAR
int activeScalarDatasetIndex = activeScalarDataset();
whileBlocking( mMeshLayer )->setActiveScalarDataset( activeScalarDatasetIndex );
if ( activeScalarDatasetIndex != -1 )
{
const QgsMeshRendererScalarSettings settings = mMeshRendererScalarSettingsWidget->settings();
whileBlocking( mMeshLayer )->setRendererScalarSettings( settings );
}
// VECTOR
int activeVectorDatasetIndex = activeVectorDataset();
whileBlocking( mMeshLayer )->setActiveVectorDataset( activeVectorDatasetIndex );
if ( activeVectorDatasetIndex != -1 )
{
const QgsMeshRendererVectorSettings settings = mMeshRendererVectorSettingsWidget->settings();
whileBlocking( mMeshLayer )->setRendererVectorSettings( settings );
}
mMeshLayer->triggerRepaint();
}
void QgsRendererMeshPropertiesWidget::syncToLayer()
{
mMeshRendererActiveDatasetWidget->syncToLayer();
mMeshRendererScalarSettingsWidget->syncToLayer();
mNativeMeshSettingsWidget->syncToLayer();
mTriangularMeshSettingsWidget->syncToLayer();
mMeshRendererVectorSettingsWidget->syncToLayer();
enableVectorRenderingTab( activeVectorDataset() );
}
void QgsRendererMeshPropertiesWidget::enableVectorRenderingTab( int vectorDatasetIndex )
{
mVectorsGroupBox->setEnabled( vectorDatasetIndex != -1 );
}
int QgsRendererMeshPropertiesWidget::activeScalarDataset() const
{
int activeScalarDatasetIndex = mMeshRendererActiveDatasetWidget->activeScalarDataset();
if ( activeScalarDatasetIndex != -1 && mContoursGroupBox->isChecked() )
return activeScalarDatasetIndex;
else
return -1;
}
int QgsRendererMeshPropertiesWidget::activeVectorDataset() const
{
int activeScalarDatasetIndex = mMeshRendererActiveDatasetWidget->activeVectorDataset();
if ( activeScalarDatasetIndex != -1 && mVectorsGroupBox->isChecked() )
return activeScalarDatasetIndex;
else
return -1;
}

View File

@ -0,0 +1,69 @@
/***************************************************************************
qgsrenderermeshpropertieswidget.h
---------------------
begin : June 2018
copyright : (C) 2018 by Peter Petrik
email : zilolv 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 QGSRENDERERMESHPROPERTIESWIDGET_H
#define QGSRENDERERMESHPROPERTIESWIDGET_H
#include <QObject>
#include <QDialog>
#include "ui_qgsrenderermeshpropswidgetbase.h"
#include "qgsmaplayerconfigwidget.h"
#include "qgis_app.h"
#include <memory>
class QgsMeshLayer;
class QgsMapCanvas;
/**
* Widget for renderer properties of the mesh, contours (scalars)
* and vectors data associated with the mesh layer
*/
class APP_EXPORT QgsRendererMeshPropertiesWidget : public QgsMapLayerConfigWidget, private Ui::QgsRendererMeshPropsWidgetBase
{
Q_OBJECT
public:
/**
* A widget to hold the renderer properties for a mesh layer.
* \param layer The mesh layer to style
* \param canvas The canvas object used
* \param parent Parent object
*/
QgsRendererMeshPropertiesWidget( QgsMeshLayer *layer, QgsMapCanvas *canvas, QWidget *parent = nullptr );
~QgsRendererMeshPropertiesWidget() = default;
public slots:
//! Applies the settings made in the dialog
void apply() override;
//! Synchronize widgets state with associated mesh layer
void syncToLayer();
private slots:
void enableVectorRenderingTab( int vectorDatasetIndex );
private:
//! Gets index of the selected/active scalar dataset
int activeScalarDataset() const;
//! Gets index of the selected/active vector dataset
int activeVectorDataset() const;
QgsMeshLayer *mMeshLayer = nullptr; //not owned
};
#endif // QGSRENDERERMESHPROPERTIESWIDGET_H

View File

@ -231,6 +231,7 @@ Q_GUI_EXPORT extern int qt_defaultDpiX();
#include "qgsmessagebar.h"
#include "qgsmessagebaritem.h"
#include "qgsmeshlayer.h"
#include "qgsmeshlayerproperties.h"
#include "qgsmemoryproviderutils.h"
#include "qgsmimedatautils.h"
#include "qgsmessagelog.h"
@ -13086,6 +13087,17 @@ void QgisApp::showLayerProperties( QgsMapLayer *mapLayer )
rasterLayerPropertiesDialog->deleteLater();
} );
}
else if ( mapLayer->type() == QgsMapLayer::MeshLayer )
{
QgsMeshLayerProperties meshLayerPropertiesDialog( mapLayer, mMapCanvas, this );
mMapStyleWidget->blockUpdates( true );
if ( meshLayerPropertiesDialog.exec() )
{
activateDeactivateLayerRelatedActions( mapLayer );
mMapStyleWidget->updateCurrentWidgetLayer();
}
mMapStyleWidget->blockUpdates( false ); // delete since dialog cannot be reused without updating code
}
else if ( mapLayer->type() == QgsMapLayer::VectorLayer ) // VECTOR
{
QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( mapLayer );

View File

@ -26,6 +26,7 @@
#include "qgsrastertransparencywidget.h"
#include "qgsrendererpropertiesdialog.h"
#include "qgsrendererrasterpropertieswidget.h"
#include "qgsrenderermeshpropertieswidget.h"
#include "qgsrasterhistogramwidget.h"
#include "qgsrasterrenderer.h"
#include "qgsrasterrendererwidget.h"
@ -33,6 +34,7 @@
#include "qgsmaplayer.h"
#include "qgsstyle.h"
#include "qgsvectorlayer.h"
#include "qgsmeshlayer.h"
#include "qgsproject.h"
#include "qgsundowidget.h"
#include "qgsreadwritecontext.h"
@ -189,6 +191,13 @@ void QgsLayerStylingWidget::setLayer( QgsMapLayer *layer )
histogramItem->setToolTip( tr( "Histogram" ) );
}
}
else if ( layer->type() == QgsMapLayer::MeshLayer )
{
QListWidgetItem *symbolItem = new QListWidgetItem( QgsApplication::getThemeIcon( QStringLiteral( "propertyicons/symbology.svg" ) ), QString() );
symbolItem->setData( Qt::UserRole, Symbology );
symbolItem->setToolTip( tr( "Symbology" ) );
mOptionsListWidget->addItem( symbolItem );
}
Q_FOREACH ( QgsMapLayerConfigWidgetFactory *factory, mPageFactories )
{
@ -335,7 +344,10 @@ void QgsLayerStylingWidget::updateCurrentWidgetLayer()
mVector3DWidget = widget;
}
#endif
else if ( QgsRendererMeshPropertiesWidget *widget = qobject_cast<QgsRendererMeshPropertiesWidget *>( current ) )
{
mMeshStyleWidget = widget;
}
}
mWidgetStack->clear();
@ -481,6 +493,24 @@ void QgsLayerStylingWidget::updateCurrentWidgetLayer()
break;
}
}
else if ( mCurrentLayer->type() == QgsMapLayer::MeshLayer )
{
QgsMeshLayer *meshLayer = qobject_cast<QgsMeshLayer *>( mCurrentLayer );
switch ( row )
{
case 0: // Style
{
mMeshStyleWidget = new QgsRendererMeshPropertiesWidget( meshLayer, mMapCanvas, mWidgetStack );
mMeshStyleWidget->setDockMode( true );
connect( mMeshStyleWidget, &QgsPanelWidget::widgetChanged, this, &QgsLayerStylingWidget::autoApply );
mWidgetStack->setMainPanel( mMeshStyleWidget );
break;
}
default:
break;
}
}
else
{
mStackedWidget->setCurrentIndex( mNotSupportedPage );
@ -591,5 +621,5 @@ QgsMapLayerConfigWidget *QgsLayerStyleManagerWidgetFactory::createWidget( QgsMap
bool QgsLayerStyleManagerWidgetFactory::supportsLayer( QgsMapLayer *layer ) const
{
return ( layer->type() == QgsMapLayer::VectorLayer || layer->type() == QgsMapLayer::RasterLayer );
return ( layer->type() == QgsMapLayer::VectorLayer || layer->type() == QgsMapLayer::RasterLayer || layer->type() == QgsMapLayer::MeshLayer );
}

View File

@ -36,6 +36,7 @@ class QgsMapLayer;
class QgsMapCanvas;
class QgsRendererPropertiesDialog;
class QgsRendererRasterPropertiesWidget;
class QgsRendererMeshPropertiesWidget;
class QgsUndoWidget;
class QgsRasterHistogramWidget;
class QgsMapLayerStyleManagerWidget;
@ -140,6 +141,7 @@ class APP_EXPORT QgsLayerStylingWidget : public QWidget, private Ui::QgsLayerSty
QgsVectorLayer3DRendererWidget *mVector3DWidget = nullptr;
#endif
QgsRendererRasterPropertiesWidget *mRasterStyleWidget = nullptr;
QgsRendererMeshPropertiesWidget *mMeshStyleWidget = nullptr;
QList<QgsMapLayerConfigWidgetFactory *> mPageFactories;
QMap<int, QgsMapLayerConfigWidgetFactory *> mUserPages;
QgsLayerStyleManagerWidgetFactory *mStyleManagerFactory = nullptr;

View File

@ -215,6 +215,8 @@ class CORE_EXPORT QgsMeshDatasetSourceInterface SIP_ABSTRACT
/**
* \brief Associate dataset with the mesh
*
* emits dataChanged when successful
*/
virtual bool addDataset( const QString &uri ) = 0;

View File

@ -338,5 +338,7 @@ bool QgsMeshLayer::setDataProvider( QString const &provider, const QgsDataProvid
mDataSource = mDataSource + QStringLiteral( "&uid=%1" ).arg( QUuid::createUuid().toString() );
}
connect( mDataProvider, &QgsMeshDataProvider::dataChanged, this, &QgsMeshLayer::dataChanged );
return true;
} // QgsMeshLayer:: setDataProvider

View File

@ -31,8 +31,8 @@
#include "qgsmeshlayerinterpolator.h"
#include "qgsmeshvectorrenderer.h"
#include "qgsfillsymbollayer.h"
#include "qgssettings.h"
#include "qgsstyle.h"
QgsMeshLayerRenderer::QgsMeshLayerRenderer( QgsMeshLayer *layer, QgsRenderContext &context )
: QgsMapLayerRenderer( layer->id() )
@ -55,9 +55,29 @@ QgsMeshLayerRenderer::QgsMeshLayerRenderer( QgsMeshLayer *layer, QgsRenderContex
copyScalarDatasetValues( layer );
copyVectorDatasetValues( layer );
assignDefaultScalarShader();
calculateOutputSize();
}
void QgsMeshLayerRenderer::assignDefaultScalarShader( )
{
if ( mScalarDatasetValues.isEmpty() || mRendererScalarSettings.isEnabled() )
return; // no need for default shader, either rendering is off or we already have some shader
auto bounds = std::minmax_element( mScalarDatasetValues.constBegin(), mScalarDatasetValues.constEnd() );
double vMin = *bounds.first;
double vMax = *bounds.second;
QgsSettings settings;
QString defaultPalette = settings.value( QStringLiteral( "/Raster/defaultPalette" ), "Spectral" ).toString();
std::unique_ptr<QgsColorRamp> colorRamp( QgsStyle::defaultStyle()->colorRamp( defaultPalette ) );
QgsColorRampShader fcn( vMin, vMax, colorRamp.release() );
fcn.classifyColorRamp( 5, -1, QgsRectangle(), nullptr );
mRendererScalarSettings.setColorRampShader( fcn );
}
QgsFeedback *QgsMeshLayerRenderer::feedback() const
{
return mFeedback.get();
@ -203,29 +223,20 @@ void QgsMeshLayerRenderer::renderMesh( const std::unique_ptr<QgsSymbol> &symbol,
void QgsMeshLayerRenderer::renderScalarDataset()
{
if ( mScalarDatasetValues.isEmpty() )
return;
return; // activeScalarDataset == NO_ACTIVE_MESH_DATASET
// do not render if magnitude is outside of the filtered range (if filtering is enabled)
double vMin = mRendererScalarSettings.minValue();
if ( std::isnan( vMin ) )
vMin = *std::min_element( mScalarDatasetValues.constBegin(), mScalarDatasetValues.constEnd() );
if ( !mRendererScalarSettings.isEnabled() )
return; // no shader
double vMax = mRendererScalarSettings.maxValue();
if ( std::isnan( vMax ) )
vMax = *std::max_element( mScalarDatasetValues.constBegin(), mScalarDatasetValues.constEnd() );
QList<QgsColorRampShader::ColorRampItem> lst;
lst << QgsColorRampShader::ColorRampItem( vMin, mRendererScalarSettings.minColor(), QString::number( vMin ) );
lst << QgsColorRampShader::ColorRampItem( vMax, mRendererScalarSettings.maxColor(), QString::number( vMax ) );
QgsColorRampShader *fcn = new QgsColorRampShader( vMin, vMax );
fcn->setColorRampItemList( lst );
QgsRasterShader *sh = new QgsRasterShader( vMin, vMax );
QgsColorRampShader *fcn = new QgsColorRampShader( mRendererScalarSettings.colorRampShader() );
QgsRasterShader *sh = new QgsRasterShader();
sh->setRasterShaderFunction( fcn ); // takes ownership of fcn
QgsMeshLayerInterpolator interpolator( mTriangularMesh, mScalarDatasetValues, mScalarDataOnVertices, mContext, mOutputSize );
QgsSingleBandPseudoColorRenderer r( &interpolator, 0, sh ); // takes ownership of sh
std::unique_ptr<QgsRasterBlock> bl( r.block( 0, mContext.extent(), mOutputSize.width(), mOutputSize.height(), mFeedback.get() ) );
QgsSingleBandPseudoColorRenderer renderer( &interpolator, 0, sh ); // takes ownership of sh
renderer.setClassificationMin( fcn->minimumValue() );
renderer.setClassificationMax( fcn->maximumValue() );
std::unique_ptr<QgsRasterBlock> bl( renderer.block( 0, mContext.extent(), mOutputSize.width(), mOutputSize.height(), mFeedback.get() ) );
QImage img = bl->image();
mContext.painter()->drawImage( 0, 0, img );

View File

@ -46,7 +46,6 @@ class QgsMeshLayerRendererFeedback : public QgsRasterBlockFeedback
///@endcond
/**
* \ingroup core
* Implementation of threaded rendering for mesh layers.
@ -69,6 +68,8 @@ class QgsMeshLayerRenderer : public QgsMapLayerRenderer
void renderVectorDataset();
void copyScalarDatasetValues( QgsMeshLayer *layer );
void copyVectorDatasetValues( QgsMeshLayer *layer );
void assignDefaultScalarShader( );
void createMeshSymbol( std::unique_ptr<QgsSymbol> &symbol, const QgsMeshRendererMeshSettings &settings );
void calculateOutputSize();

View File

@ -307,6 +307,9 @@ bool QgsMeshMemoryDataProvider::addDataset( const QString &uri )
mDatasets.push_back( ds );
if ( ds.valid )
emit dataChanged();
return ds.valid;
}

View File

@ -47,45 +47,23 @@ void QgsMeshRendererMeshSettings::setColor( const QColor &color )
mColor = color;
}
QColor QgsMeshRendererScalarSettings::maxColor() const
QgsColorRampShader QgsMeshRendererScalarSettings::colorRampShader() const
{
return mMaxColor;
return mColorRampShader;
}
void QgsMeshRendererScalarSettings::setMaxColor( const QColor &maxColor )
void QgsMeshRendererScalarSettings::setColorRampShader( const QgsColorRampShader &shader )
{
mMaxColor = maxColor;
mColorRampShader = shader;
}
QColor QgsMeshRendererScalarSettings::minColor() const
bool QgsMeshRendererScalarSettings::isEnabled() const
{
return mMinColor;
return !mColorRampShader.isEmpty();
}
void QgsMeshRendererScalarSettings::setMinColor( const QColor &minColor )
{
mMinColor = minColor;
}
double QgsMeshRendererScalarSettings::minValue() const
{
return mMinValue;
}
void QgsMeshRendererScalarSettings::setMinValue( double minValue )
{
mMinValue = minValue;
}
double QgsMeshRendererScalarSettings::maxValue() const
{
return mMaxValue;
}
void QgsMeshRendererScalarSettings::setMaxValue( double maxValue )
{
mMaxValue = maxValue;
}
double QgsMeshRendererVectorSettings::lineWidth() const
{

View File

@ -23,6 +23,8 @@
#include "qgis_core.h"
#include "qgis.h"
#include "qgscolorrampshader.h"
/**
* \ingroup core
@ -69,49 +71,15 @@ class CORE_EXPORT QgsMeshRendererMeshSettings
class CORE_EXPORT QgsMeshRendererScalarSettings
{
public:
//! Returns color representing maximum scalar value in the dataset
QColor maxColor() const;
//! Sets color representing maximum scalar value in the dataset
void setMaxColor( const QColor &maxColor );
//! Returns color representing minimum scalar value in the dataset
QColor minColor() const;
//! Sets color representing maximum scalar value in the dataset
void setMinColor( const QColor &minColor );
/**
* Returns min scalar value that represents minColor()
*
* if set to numerical_limits<double>::quiet_NaN(), value for minColor() is
* taken from minimum value of active scalar dataset
*/
double minValue() const;
/**
* Sets min scalar value that represents minColor()
* \see QgsMeshRendererScalarSettings::minValue()
*/
void setMinValue( double minValue );
/**
* Returns max scalar value that represents maxColor()
*
* if set to numerical_limits<double>::quiet_NaN(), value for maxColor() is
* taken from maximum value of active scalar dataset
*/
double maxValue() const;
/**
* Sets min scalar value that represents minColor()
* \see QgsMeshRendererScalarSettings::maxValue()
*/
void setMaxValue( double maxValue );
//! Returns color ramp shader function
QgsColorRampShader colorRampShader() const;
//! Sets color ramp shader function
void setColorRampShader( const QgsColorRampShader &shader );
//! Returns whether color ramp has any items assigned
bool isEnabled() const;
private:
QColor mMaxColor = QColor::fromRgb( 255, 0, 0 );
QColor mMinColor = QColor::fromRgb( 0, 0, 255 );
double mMaxValue = std::numeric_limits<double>::quiet_NaN(); //disabled
double mMinValue = std::numeric_limits<double>::quiet_NaN(); //disabled
QgsColorRampShader mColorRampShader;
};
/**

View File

@ -55,15 +55,7 @@ QgsMeshVectorRenderer::QgsMeshVectorRenderer( const QgsTriangularMesh &m,
, mDataOnVertices( dataIsOnVertices )
, mOutputSize( size )
{
auto bounds = std::minmax_element( mDatasetValuesX.constBegin(), mDatasetValuesX.constEnd() );
mMinX = *bounds.first;
mMaxX = *bounds.second;
bounds = std::minmax_element( mDatasetValuesY.constBegin(), mDatasetValuesY.constEnd() );
mMinY = *bounds.first;
mMaxY = *bounds.second;
bounds = std::minmax_element( mDatasetValuesMag.constBegin(), mDatasetValuesMag.constEnd() );
auto bounds = std::minmax_element( mDatasetValuesMag.constBegin(), mDatasetValuesMag.constEnd() );
mMinMag = *bounds.first;
mMaxMag = *bounds.second;
}

View File

@ -84,10 +84,6 @@ class QgsMeshVectorRenderer
const QVector<double> &mDatasetValuesX;
const QVector<double> &mDatasetValuesY;
const QVector<double> &mDatasetValuesMag; //magnitudes
double mMinX = 0.0;
double mMaxX = 0.0;
double mMinY = 0.0;
double mMaxY = 0.0;
double mMinMag = 0.0;
double mMaxMag = 0.0;
QgsRenderContext &mContext;

View File

@ -50,12 +50,18 @@ QgsColorRampShader::QgsColorRampShader( const QgsColorRampShader &other )
, mLUTInitialized( other.mLUTInitialized )
, mClip( other.mClip )
{
mSourceColorRamp.reset( other.sourceColorRamp()->clone() );
if ( other.sourceColorRamp() )
mSourceColorRamp.reset( other.sourceColorRamp()->clone() );
mColorRampItemList = other.mColorRampItemList;
}
QgsColorRampShader &QgsColorRampShader::operator=( const QgsColorRampShader &other )
{
mSourceColorRamp.reset( other.sourceColorRamp()->clone() );
if ( other.sourceColorRamp() )
mSourceColorRamp.reset( other.sourceColorRamp()->clone() );
else
mSourceColorRamp.reset();
mColorRampType = other.mColorRampType;
mClassificationMode = other.mClassificationMode;
mLUT = other.mLUT;
@ -63,6 +69,7 @@ QgsColorRampShader &QgsColorRampShader::operator=( const QgsColorRampShader &oth
mLUTFactor = other.mLUTFactor;
mLUTInitialized = other.mLUTInitialized;
mClip = other.mClip;
mColorRampItemList = other.mColorRampItemList;
return *this;
}
@ -93,6 +100,11 @@ void QgsColorRampShader::setColorRampType( QgsColorRampShader::Type colorRampTyp
mColorRampType = colorRampType;
}
bool QgsColorRampShader::isEmpty() const
{
return mColorRampItemList.isEmpty();
}
void QgsColorRampShader::setColorRampType( const QString &type )
{
if ( type == QLatin1String( "INTERPOLATED" ) )

View File

@ -116,6 +116,12 @@ class CORE_EXPORT QgsColorRampShader : public QgsRasterShaderFunction
//! Sets the color ramp type
void setColorRampType( QgsColorRampShader::Type colorRampType );
/**
* Whether the color ramp contains any items
* \since QGIS 3.4
*/
bool isEmpty() const;
/**
* Gets the source color ramp
* \see setSourceColorRamp()

View File

@ -1,4 +1,5 @@
SET(QGIS_GUI_SRCS
raster/qgscolorrampshaderwidget.cpp
raster/qgsmultibandcolorrendererwidget.cpp
raster/qgspalettedrendererwidget.cpp
raster/qgsrasterbandcombobox.cpp
@ -541,6 +542,7 @@ SET(QGIS_GUI_MOC_HDRS
ogr/qgsnewogrconnection.h
ogr/qgsvectorlayersaveasdialog.h
raster/qgscolorrampshaderwidget.h
raster/qgsmultibandcolorrendererwidget.h
raster/qgspalettedrendererwidget.h
raster/qgsrasterbandcombobox.h

View File

@ -0,0 +1,778 @@
/***************************************************************************
qgscolorrampshaderwidget.cpp
----------------------------
begin : Jun 2018
copyright : (C) 2018 by Peter Petrik
email : zilolv 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 "qgsrasterdataprovider.h"
#include "qgscolorrampshaderwidget.h"
#include "qgssinglebandpseudocolorrenderer.h"
#include "qgsrasterlayer.h"
#include "qgsrasterdataprovider.h"
#include "qgsrastershader.h"
#include "qgsrasterminmaxwidget.h"
#include "qgstreewidgetitem.h"
#include "qgssettings.h"
#include "qgsstyle.h"
#include "qgscolorramp.h"
#include "qgscolorrampbutton.h"
#include "qgscolordialog.h"
#include <QCursor>
#include <QPushButton>
#include <QInputDialog>
#include <QFileDialog>
#include <QMenu>
#include <QMessageBox>
#include <QTextStream>
#include <QTreeView>
QgsColorRampShaderWidget::QgsColorRampShaderWidget( QWidget *parent )
: QWidget( parent )
{
QgsSettings settings;
setupUi( this );
mLoadFromBandButton->setVisible( false ); // only for raster version
connect( mAddEntryButton, &QPushButton::clicked, this, &QgsColorRampShaderWidget::mAddEntryButton_clicked );
connect( mDeleteEntryButton, &QPushButton::clicked, this, &QgsColorRampShaderWidget::mDeleteEntryButton_clicked );
connect( mLoadFromBandButton, &QPushButton::clicked, this, &QgsColorRampShaderWidget::mLoadFromBandButton_clicked );
connect( mLoadFromFileButton, &QPushButton::clicked, this, &QgsColorRampShaderWidget::mLoadFromFileButton_clicked );
connect( mExportToFileButton, &QPushButton::clicked, this, &QgsColorRampShaderWidget::mExportToFileButton_clicked );
connect( mUnitLineEdit, &QLineEdit::textEdited, this, &QgsColorRampShaderWidget::mUnitLineEdit_textEdited );
connect( mColormapTreeWidget, &QTreeWidget::itemDoubleClicked, this, &QgsColorRampShaderWidget::mColormapTreeWidget_itemDoubleClicked );
connect( mColorInterpolationComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsColorRampShaderWidget::mColorInterpolationComboBox_currentIndexChanged );
connect( mClassificationModeComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsColorRampShaderWidget::mClassificationModeComboBox_currentIndexChanged );
contextMenu = new QMenu( tr( "Options" ), this );
contextMenu->addAction( tr( "Change Color…" ), this, SLOT( changeColor() ) );
contextMenu->addAction( tr( "Change Opacity…" ), this, SLOT( changeOpacity() ) );
mColormapTreeWidget->setColumnWidth( ColorColumn, 50 );
mColormapTreeWidget->setContextMenuPolicy( Qt::CustomContextMenu );
mColormapTreeWidget->setSelectionMode( QAbstractItemView::ExtendedSelection );
connect( mColormapTreeWidget, &QTreeView::customContextMenuRequested, this, [ = ]( QPoint ) { contextMenu->exec( QCursor::pos() ); }
);
QString defaultPalette = settings.value( QStringLiteral( "Raster/defaultPalette" ), "" ).toString();
btnColorRamp->setColorRampFromName( defaultPalette );
mColorInterpolationComboBox->addItem( tr( "Discrete" ), QgsColorRampShader::Discrete );
mColorInterpolationComboBox->addItem( tr( "Linear" ), QgsColorRampShader::Interpolated );
mColorInterpolationComboBox->addItem( tr( "Exact" ), QgsColorRampShader::Exact );
mColorInterpolationComboBox->setCurrentIndex( mColorInterpolationComboBox->findData( QgsColorRampShader::Interpolated ) );
mClassificationModeComboBox->addItem( tr( "Continuous" ), QgsColorRampShader::Continuous );
mClassificationModeComboBox->addItem( tr( "Equal Interval" ), QgsColorRampShader::EqualInterval );
// Quantile added only on demand
mClassificationModeComboBox->setCurrentIndex( mClassificationModeComboBox->findData( QgsColorRampShader::Continuous ) );
mNumberOfEntriesSpinBox->setValue( 5 ); // some default
mClassificationModeComboBox_currentIndexChanged( 0 );
resetClassifyButton();
connect( mClassificationModeComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsColorRampShaderWidget::classify );
connect( mClassifyButton, &QPushButton::clicked, this, &QgsColorRampShaderWidget::applyColorRamp );
connect( btnColorRamp, &QgsColorRampButton::colorRampChanged, this, &QgsColorRampShaderWidget::applyColorRamp );
connect( mNumberOfEntriesSpinBox, static_cast < void ( QSpinBox::* )( int ) > ( &QSpinBox::valueChanged ), this, &QgsColorRampShaderWidget::classify );
}
void QgsColorRampShaderWidget::initForUseWithRasterLayer()
{
Q_ASSERT( mClassificationModeComboBox->findData( QgsColorRampShader::Quantile < 0 ) );
mClassificationModeComboBox->addItem( tr( "Quantile" ), QgsColorRampShader::Quantile );
mLoadFromBandButton->setVisible( bool( mRasterDataProvider ) ); // only for raster version
}
void QgsColorRampShaderWidget::setRasterBand( QgsRasterDataProvider *dp,
int band,
const QgsRectangle &extent )
{
mRasterDataProvider = dp;
mBand = band;
mExtent = extent;
}
QgsColorRampShader QgsColorRampShaderWidget::shader() const
{
QgsColorRampShader colorRampShader( mMin, mMax );
colorRampShader.setColorRampType( static_cast< QgsColorRampShader::Type >( mColorInterpolationComboBox->currentData().toInt() ) );
colorRampShader.setClassificationMode( static_cast< QgsColorRampShader::ClassificationMode >( mClassificationModeComboBox->currentData().toInt() ) );
colorRampShader.setClip( mClipCheckBox->isChecked() );
//iterate through mColormapTreeWidget and set colormap info of layer
QList<QgsColorRampShader::ColorRampItem> colorRampItems;
int topLevelItemCount = mColormapTreeWidget->topLevelItemCount();
QTreeWidgetItem *currentItem = nullptr;
for ( int i = 0; i < topLevelItemCount; ++i )
{
currentItem = mColormapTreeWidget->topLevelItem( i );
if ( !currentItem )
{
continue;
}
QgsColorRampShader::ColorRampItem newColorRampItem;
newColorRampItem.value = currentItem->text( ValueColumn ).toDouble();
newColorRampItem.color = currentItem->background( ColorColumn ).color();
newColorRampItem.label = currentItem->text( LabelColumn );
colorRampItems.append( newColorRampItem );
}
// sort the shader items
std::sort( colorRampItems.begin(), colorRampItems.end() );
colorRampShader.setColorRampItemList( colorRampItems );
if ( !btnColorRamp->isNull() )
{
colorRampShader.setSourceColorRamp( btnColorRamp->colorRamp() );
}
return colorRampShader;
}
void QgsColorRampShaderWidget::autoLabel()
{
QgsColorRampShader::Type interpolation = static_cast< QgsColorRampShader::Type >( mColorInterpolationComboBox->currentData().toInt() );
bool discrete = interpolation == QgsColorRampShader::Discrete;
QString unit = mUnitLineEdit->text();
QString label;
int topLevelItemCount = mColormapTreeWidget->topLevelItemCount();
QTreeWidgetItem *currentItem = nullptr;
for ( int i = 0; i < topLevelItemCount; ++i )
{
currentItem = mColormapTreeWidget->topLevelItem( i );
//If the item is null or does not have a pixel values set, skip
if ( !currentItem || currentItem->text( ValueColumn ).isEmpty() )
{
continue;
}
if ( discrete )
{
if ( i == 0 )
{
label = "<= " + currentItem->text( ValueColumn ) + unit;
}
else if ( currentItem->text( ValueColumn ).toDouble() == std::numeric_limits<double>::infinity() )
{
label = "> " + mColormapTreeWidget->topLevelItem( i - 1 )->text( ValueColumn ) + unit;
}
else
{
label = mColormapTreeWidget->topLevelItem( i - 1 )->text( ValueColumn ) + " - " + currentItem->text( ValueColumn ) + unit;
}
}
else
{
label = currentItem->text( ValueColumn ) + unit;
}
if ( currentItem->text( LabelColumn ).isEmpty() || currentItem->text( LabelColumn ) == label || currentItem->foreground( LabelColumn ).color() == QColor( Qt::gray ) )
{
currentItem->setText( LabelColumn, label );
currentItem->setForeground( LabelColumn, QBrush( QColor( Qt::gray ) ) );
}
}
}
void QgsColorRampShaderWidget::setUnitFromLabels()
{
QgsColorRampShader::Type interpolation = static_cast< QgsColorRampShader::Type >( mColorInterpolationComboBox->currentData().toInt() );
bool discrete = interpolation == QgsColorRampShader::Discrete;
QStringList allSuffixes;
QString label;
int topLevelItemCount = mColormapTreeWidget->topLevelItemCount();
QTreeWidgetItem *currentItem = nullptr;
for ( int i = 0; i < topLevelItemCount; ++i )
{
currentItem = mColormapTreeWidget->topLevelItem( i );
//If the item is null or does not have a pixel values set, skip
if ( !currentItem || currentItem->text( ValueColumn ).isEmpty() )
{
continue;
}
if ( discrete )
{
if ( i == 0 )
{
label = "<= " + currentItem->text( ValueColumn );
}
else if ( currentItem->text( ValueColumn ).toDouble() == std::numeric_limits<double>::infinity() )
{
label = "> " + mColormapTreeWidget->topLevelItem( i - 1 )->text( ValueColumn );
}
else
{
label = mColormapTreeWidget->topLevelItem( i - 1 )->text( ValueColumn ) + " - " + currentItem->text( ValueColumn );
}
}
else
{
label = currentItem->text( ValueColumn );
}
if ( currentItem->text( LabelColumn ).startsWith( label ) )
{
allSuffixes.append( currentItem->text( LabelColumn ).mid( label.length() ) );
}
}
// find most common suffix
QStringList suffixes = QStringList( allSuffixes );
suffixes.removeDuplicates();
int max = 0;
QString unit;
for ( int i = 0; i < suffixes.count(); ++i )
{
int n = allSuffixes.count( suffixes[i] );
if ( n > max )
{
max = n;
unit = suffixes[i];
}
}
// Set this suffix as unit if at least used twice
if ( max >= 2 )
{
mUnitLineEdit->setText( unit );
}
autoLabel();
}
void QgsColorRampShaderWidget::mAddEntryButton_clicked()
{
QgsTreeWidgetItemObject *newItem = new QgsTreeWidgetItemObject( mColormapTreeWidget );
newItem->setText( ValueColumn, QStringLiteral( "0" ) );
newItem->setBackground( ColorColumn, QBrush( QColor( Qt::magenta ) ) );
newItem->setText( LabelColumn, QString() );
newItem->setFlags( Qt::ItemIsEnabled | Qt::ItemIsEditable | Qt::ItemIsSelectable );
connect( newItem, &QgsTreeWidgetItemObject::itemEdited,
this, &QgsColorRampShaderWidget::mColormapTreeWidget_itemEdited );
mColormapTreeWidget->sortItems( ValueColumn, Qt::AscendingOrder );
autoLabel();
loadMinMaxFromTree();
emit widgetChanged();
}
void QgsColorRampShaderWidget::mDeleteEntryButton_clicked()
{
QList<QTreeWidgetItem *> itemList;
itemList = mColormapTreeWidget->selectedItems();
if ( itemList.isEmpty() )
{
return;
}
Q_FOREACH ( QTreeWidgetItem *item, itemList )
{
delete item;
}
loadMinMaxFromTree();
emit widgetChanged();
}
void QgsColorRampShaderWidget::classify()
{
std::unique_ptr< QgsColorRamp > ramp( btnColorRamp->colorRamp() );
if ( !ramp || std::isnan( mMin ) || std::isnan( mMax ) )
{
return;
}
std::unique_ptr< QgsColorRampShader > colorRampShader( new QgsColorRampShader(
mMin, mMax,
ramp.release(),
static_cast< QgsColorRampShader::Type >( mColorInterpolationComboBox->currentData().toInt() ),
static_cast< QgsColorRampShader::ClassificationMode >( mClassificationModeComboBox->currentData().toInt() ) )
);
// only for Quantile we need band and provider and extent
colorRampShader->classifyColorRamp( mNumberOfEntriesSpinBox->value(),
mBand,
mExtent,
mRasterDataProvider );
colorRampShader->setClip( mClipCheckBox->isChecked() );
mColormapTreeWidget->clear();
const QList<QgsColorRampShader::ColorRampItem> colorRampItemList = colorRampShader->colorRampItemList();
QList<QgsColorRampShader::ColorRampItem>::const_iterator it = colorRampItemList.constBegin();
for ( ; it != colorRampItemList.end(); ++it )
{
QgsTreeWidgetItemObject *newItem = new QgsTreeWidgetItemObject( mColormapTreeWidget );
newItem->setText( ValueColumn, QString::number( it->value, 'g', 15 ) );
newItem->setBackground( ColorColumn, QBrush( it->color ) );
newItem->setText( LabelColumn, it->label );
newItem->setFlags( Qt::ItemIsEnabled | Qt::ItemIsEditable | Qt::ItemIsSelectable );
connect( newItem, &QgsTreeWidgetItemObject::itemEdited,
this, &QgsColorRampShaderWidget::mColormapTreeWidget_itemEdited );
}
mClipCheckBox->setChecked( colorRampShader->clip() );
autoLabel();
emit widgetChanged();
}
void QgsColorRampShaderWidget::mClassificationModeComboBox_currentIndexChanged( int index )
{
QgsColorRampShader::ClassificationMode mode = static_cast< QgsColorRampShader::ClassificationMode >( mClassificationModeComboBox->itemData( index ).toInt() );
mNumberOfEntriesSpinBox->setEnabled( mode != QgsColorRampShader::Continuous );
emit classificationModeChanged( mode );
}
void QgsColorRampShaderWidget::applyColorRamp()
{
std::unique_ptr< QgsColorRamp > ramp( btnColorRamp->colorRamp() );
if ( !ramp )
{
return;
}
if ( !btnColorRamp->colorRampName().isEmpty() )
{
// Remember last used color ramp
QgsSettings settings;
settings.setValue( QStringLiteral( "Raster/defaultPalette" ), btnColorRamp->colorRampName() );
}
bool enableContinuous = ( ramp->count() > 0 );
mClassificationModeComboBox->setEnabled( enableContinuous );
if ( !enableContinuous )
{
mClassificationModeComboBox->setCurrentIndex( mClassificationModeComboBox->findData( QgsColorRampShader::EqualInterval ) );
}
classify();
}
void QgsColorRampShaderWidget::populateColormapTreeWidget( const QList<QgsColorRampShader::ColorRampItem> &colorRampItems )
{
mColormapTreeWidget->clear();
QList<QgsColorRampShader::ColorRampItem>::const_iterator it = colorRampItems.constBegin();
for ( ; it != colorRampItems.constEnd(); ++it )
{
QgsTreeWidgetItemObject *newItem = new QgsTreeWidgetItemObject( mColormapTreeWidget );
newItem->setText( ValueColumn, QString::number( it->value, 'g', 15 ) );
newItem->setBackground( ColorColumn, QBrush( it->color ) );
newItem->setText( LabelColumn, it->label );
newItem->setFlags( Qt::ItemIsEnabled | Qt::ItemIsEditable | Qt::ItemIsSelectable );
connect( newItem, &QgsTreeWidgetItemObject::itemEdited,
this, &QgsColorRampShaderWidget::mColormapTreeWidget_itemEdited );
}
setUnitFromLabels();
autoLabel();
emit widgetChanged();
}
void QgsColorRampShaderWidget::mLoadFromBandButton_clicked()
{
if ( !mRasterDataProvider )
return;
QList<QgsColorRampShader::ColorRampItem> colorRampList = mRasterDataProvider->colorTable( mBand );
if ( !colorRampList.isEmpty() )
{
populateColormapTreeWidget( colorRampList );
mColorInterpolationComboBox->setCurrentIndex( mColorInterpolationComboBox->findData( QgsColorRampShader::Interpolated ) );
}
else
{
QMessageBox::warning( this, tr( "Load Color Map" ), tr( "The color map for band %1 has no entries." ).arg( mBand ) );
}
loadMinMaxFromTree();
emit widgetChanged();
}
void QgsColorRampShaderWidget::mLoadFromFileButton_clicked()
{
int lineCounter = 0;
bool importError = false;
QString badLines;
QgsSettings settings;
QString lastDir = settings.value( QStringLiteral( "lastColorMapDir" ), QDir::homePath() ).toString();
QString fileName = QFileDialog::getOpenFileName( this, tr( "Load Color Map from File" ), lastDir, tr( "Textfile (*.txt)" ) );
QFile inputFile( fileName );
if ( inputFile.open( QFile::ReadOnly ) )
{
//clear the current tree
mColormapTreeWidget->clear();
QTextStream inputStream( &inputFile );
QString inputLine;
QStringList inputStringComponents;
QList<QgsColorRampShader::ColorRampItem> colorRampItems;
//read through the input looking for valid data
while ( !inputStream.atEnd() )
{
lineCounter++;
inputLine = inputStream.readLine();
if ( !inputLine.isEmpty() )
{
if ( !inputLine.simplified().startsWith( '#' ) )
{
if ( inputLine.contains( QLatin1String( "INTERPOLATION" ), Qt::CaseInsensitive ) )
{
inputStringComponents = inputLine.split( ':' );
if ( inputStringComponents.size() == 2 )
{
if ( inputStringComponents[1].trimmed().toUpper().compare( QLatin1String( "INTERPOLATED" ), Qt::CaseInsensitive ) == 0 )
{
mColorInterpolationComboBox->setCurrentIndex( mColorInterpolationComboBox->findData( QgsColorRampShader::Interpolated ) );
}
else if ( inputStringComponents[1].trimmed().toUpper().compare( QLatin1String( "DISCRETE" ), Qt::CaseInsensitive ) == 0 )
{
mColorInterpolationComboBox->setCurrentIndex( mColorInterpolationComboBox->findData( QgsColorRampShader::Discrete ) );
}
else
{
mColorInterpolationComboBox->setCurrentIndex( mColorInterpolationComboBox->findData( QgsColorRampShader::Exact ) );
}
}
else
{
importError = true;
badLines = badLines + QString::number( lineCounter ) + ":\t[" + inputLine + "]\n";
}
}
else
{
inputStringComponents = inputLine.split( ',' );
if ( inputStringComponents.size() == 6 )
{
QgsColorRampShader::ColorRampItem currentItem( inputStringComponents[0].toDouble(),
QColor::fromRgb( inputStringComponents[1].toInt(), inputStringComponents[2].toInt(),
inputStringComponents[3].toInt(), inputStringComponents[4].toInt() ),
inputStringComponents[5] );
colorRampItems.push_back( currentItem );
}
else
{
importError = true;
badLines = badLines + QString::number( lineCounter ) + ":\t[" + inputLine + "]\n";
}
}
}
}
lineCounter++;
}
populateColormapTreeWidget( colorRampItems );
QFileInfo fileInfo( fileName );
settings.setValue( QStringLiteral( "lastColorMapDir" ), fileInfo.absoluteDir().absolutePath() );
if ( importError )
{
QMessageBox::warning( this, tr( "Load Color Map from File" ), tr( "The following lines contained errors\n\n" ) + badLines );
}
}
else if ( !fileName.isEmpty() )
{
QMessageBox::warning( this, tr( "Load Color Map from File" ), tr( "Read access denied. Adjust the file permissions and try again.\n\n" ) );
}
loadMinMaxFromTree();
emit widgetChanged();
}
void QgsColorRampShaderWidget::mExportToFileButton_clicked()
{
QgsSettings settings;
QString lastDir = settings.value( QStringLiteral( "lastColorMapDir" ), QDir::homePath() ).toString();
QString fileName = QFileDialog::getSaveFileName( this, tr( "Save Color Map as File" ), lastDir, tr( "Textfile (*.txt)" ) );
if ( !fileName.isEmpty() )
{
if ( !fileName.endsWith( QLatin1String( ".txt" ), Qt::CaseInsensitive ) )
{
fileName = fileName + ".txt";
}
QFile outputFile( fileName );
if ( outputFile.open( QFile::WriteOnly | QIODevice::Truncate ) )
{
QTextStream outputStream( &outputFile );
outputStream << "# " << tr( "QGIS Generated Color Map Export File" ) << '\n';
outputStream << "INTERPOLATION:";
QgsColorRampShader::Type interpolation = static_cast< QgsColorRampShader::Type >( mColorInterpolationComboBox->currentData().toInt() );
switch ( interpolation )
{
case QgsColorRampShader::Interpolated:
outputStream << "INTERPOLATED\n";
break;
case QgsColorRampShader::Discrete:
outputStream << "DISCRETE\n";
break;
case QgsColorRampShader::Exact:
outputStream << "EXACT\n";
break;
}
int topLevelItemCount = mColormapTreeWidget->topLevelItemCount();
QTreeWidgetItem *currentItem = nullptr;
QColor color;
for ( int i = 0; i < topLevelItemCount; ++i )
{
currentItem = mColormapTreeWidget->topLevelItem( i );
if ( !currentItem )
{
continue;
}
color = currentItem->background( ColorColumn ).color();
outputStream << currentItem->text( ValueColumn ).toDouble() << ',';
outputStream << color.red() << ',' << color.green() << ',' << color.blue() << ',' << color.alpha() << ',';
if ( currentItem->text( LabelColumn ).isEmpty() )
{
outputStream << "Color entry " << i + 1 << '\n';
}
else
{
outputStream << currentItem->text( LabelColumn ) << '\n';
}
}
outputStream.flush();
outputFile.close();
QFileInfo fileInfo( fileName );
settings.setValue( QStringLiteral( "lastColorMapDir" ), fileInfo.absoluteDir().absolutePath() );
}
else
{
QMessageBox::warning( this, tr( "Save Color Map as File" ), tr( "Write access denied. Adjust the file permissions and try again.\n\n" ) );
}
}
}
void QgsColorRampShaderWidget::mColormapTreeWidget_itemDoubleClicked( QTreeWidgetItem *item, int column )
{
if ( !item )
{
return;
}
if ( column == ColorColumn )
{
item->setFlags( Qt::ItemIsEnabled | Qt::ItemIsSelectable );
QColor newColor = QgsColorDialog::getColor( item->background( column ).color(), this, QStringLiteral( "Change Color" ), true );
if ( newColor.isValid() )
{
item->setBackground( ColorColumn, QBrush( newColor ) );
loadMinMaxFromTree();
emit widgetChanged();
}
}
else
{
if ( column == LabelColumn )
{
// Set text color to default black, which signifies a manually edited label
item->setForeground( LabelColumn, QBrush() );
}
item->setFlags( Qt::ItemIsEnabled | Qt::ItemIsEditable | Qt::ItemIsSelectable );
}
}
void QgsColorRampShaderWidget::mColormapTreeWidget_itemEdited( QTreeWidgetItem *item, int column )
{
Q_UNUSED( item );
if ( column == ValueColumn )
{
mColormapTreeWidget->sortItems( ValueColumn, Qt::AscendingOrder );
autoLabel();
loadMinMaxFromTree();
emit widgetChanged();
}
else if ( column == LabelColumn )
{
// call autoLabel to fill when empty or gray out when same as autoLabel
autoLabel();
emit widgetChanged();
}
}
void QgsColorRampShaderWidget::setFromShader( const QgsColorRampShader &colorRampShader )
{
if ( colorRampShader.sourceColorRamp() )
{
btnColorRamp->setColorRamp( colorRampShader.sourceColorRamp() );
}
else
{
QgsSettings settings;
QString defaultPalette = settings.value( QStringLiteral( "/Raster/defaultPalette" ), "Spectral" ).toString();
btnColorRamp->setColorRampFromName( defaultPalette );
}
mColorInterpolationComboBox->setCurrentIndex( mColorInterpolationComboBox->findData( colorRampShader.colorRampType() ) );
const QList<QgsColorRampShader::ColorRampItem> colorRampItemList = colorRampShader.colorRampItemList();
QList<QgsColorRampShader::ColorRampItem>::const_iterator it = colorRampItemList.constBegin();
for ( ; it != colorRampItemList.end(); ++it )
{
QgsTreeWidgetItemObject *newItem = new QgsTreeWidgetItemObject( mColormapTreeWidget );
newItem->setText( ValueColumn, QString::number( it->value, 'g', 15 ) );
newItem->setBackground( ColorColumn, QBrush( it->color ) );
newItem->setText( LabelColumn, it->label );
newItem->setFlags( Qt::ItemIsEnabled | Qt::ItemIsEditable | Qt::ItemIsSelectable );
connect( newItem, &QgsTreeWidgetItemObject::itemEdited,
this, &QgsColorRampShaderWidget::mColormapTreeWidget_itemEdited );
}
setUnitFromLabels();
mClipCheckBox->setChecked( colorRampShader.clip() );
mClassificationModeComboBox->setCurrentIndex( mClassificationModeComboBox->findData( colorRampShader.classificationMode() ) );
mNumberOfEntriesSpinBox->setValue( colorRampShader.colorRampItemList().count() ); // some default
}
void QgsColorRampShaderWidget::mColorInterpolationComboBox_currentIndexChanged( int index )
{
QgsColorRampShader::Type interpolation = static_cast< QgsColorRampShader::Type >( mColorInterpolationComboBox->itemData( index ).toInt() );
mClipCheckBox->setEnabled( interpolation == QgsColorRampShader::Interpolated );
QString valueLabel;
QString valueToolTip;
switch ( interpolation )
{
case QgsColorRampShader::Interpolated:
valueLabel = tr( "Value" );
valueToolTip = tr( "Value for color stop" );
break;
case QgsColorRampShader::Discrete:
valueLabel = tr( "Value <=" );
valueToolTip = tr( "Maximum value for class" );
break;
case QgsColorRampShader::Exact:
valueLabel = tr( "Value =" );
valueToolTip = tr( "Value for color" );
break;
}
QTreeWidgetItem *header = mColormapTreeWidget->headerItem();
header->setText( ValueColumn, valueLabel );
header->setToolTip( ValueColumn, valueToolTip );
autoLabel();
emit widgetChanged();
}
void QgsColorRampShaderWidget::setMinMaxAndClassify( double min, double max )
{
if ( !qgsDoubleNear( mMin, min ) || !qgsDoubleNear( mMax, max ) )
{
mMin = min;
mMax = max;
classify();
}
}
void QgsColorRampShaderWidget::setMinMax( double min, double max )
{
mMin = min;
mMax = max;
resetClassifyButton();
}
void QgsColorRampShaderWidget::loadMinMaxFromTree()
{
QTreeWidgetItem *item = mColormapTreeWidget->topLevelItem( 0 );
if ( !item )
{
return;
}
double min = item->text( ValueColumn ).toDouble();
item = mColormapTreeWidget->topLevelItem( mColormapTreeWidget->topLevelItemCount() - 1 );
double max = item->text( ValueColumn ).toDouble();
if ( !qgsDoubleNear( mMin, min ) || !qgsDoubleNear( mMax, max ) )
{
mMin = min;
mMax = max;
emit minMaxChangedFromTree( min, max );
}
}
void QgsColorRampShaderWidget::resetClassifyButton()
{
mClassifyButton->setEnabled( true );
if ( std::isnan( mMin ) || std::isnan( mMax ) || mMin >= mMax )
{
mClassifyButton->setEnabled( false );
}
}
void QgsColorRampShaderWidget::changeColor()
{
QList<QTreeWidgetItem *> itemList;
itemList = mColormapTreeWidget->selectedItems();
if ( itemList.isEmpty() )
{
return;
}
QTreeWidgetItem *firstItem = itemList.first();
QColor newColor = QgsColorDialog::getColor( firstItem->background( ColorColumn ).color(), this, QStringLiteral( "Change Color" ), true );
if ( newColor.isValid() )
{
Q_FOREACH ( QTreeWidgetItem *item, itemList )
{
item->setFlags( Qt::ItemIsEnabled | Qt::ItemIsSelectable );
item->setBackground( ColorColumn, QBrush( newColor ) );
}
loadMinMaxFromTree();
emit widgetChanged();
}
}
void QgsColorRampShaderWidget::changeOpacity()
{
QList<QTreeWidgetItem *> itemList;
itemList = mColormapTreeWidget->selectedItems();
if ( itemList.isEmpty() )
{
return;
}
QTreeWidgetItem *firstItem = itemList.first();
bool ok;
double oldOpacity = firstItem->background( ColorColumn ).color().alpha() / 255 * 100;
double opacity = QInputDialog::getDouble( this, tr( "Opacity" ), tr( "Change color opacity [%]" ), oldOpacity, 0.0, 100.0, 0, &ok );
if ( ok )
{
int newOpacity = static_cast<int>( opacity / 100 * 255 );
Q_FOREACH ( QTreeWidgetItem *item, itemList )
{
QColor newColor = item->background( ColorColumn ).color();
newColor.setAlpha( newOpacity );
item->setBackground( ColorColumn, QBrush( newColor ) );
}
loadMinMaxFromTree();
emit widgetChanged();
}
}

View File

@ -0,0 +1,145 @@
/***************************************************************************
qgscolorrampshaderwidget.h
--------------------------
begin : Jun 2018
copyright : (C) 2018 by Peter Petrik
email : zilolv 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 QGSCOLORRAMPSHADERWIDGET_H
#define QGSCOLORRAMPSHADERWIDGET_H
#include "qgis_sip.h"
#include "qgscolorrampshader.h"
#include "qgsrasterrenderer.h"
#include "ui_qgscolorrampshaderwidgetbase.h"
#include "qgis_gui.h"
#include "qgsrasterrendererwidget.h"
class QgsRasterDataProvider;
/**
* \ingroup gui
* \class QgsColorRampShaderWidget
*
* It has 2 ways how to use it. For raster layers, raster data provider and band is assigned and
* the Quantile classification mode can be used and the LoadFromBandButton is visible.
*
* The other mode is used to style mesh layer contours (scalar datasets)
*
* \since QGIS 3.4
*/
class GUI_EXPORT QgsColorRampShaderWidget: public QWidget, protected Ui::QgsColorRampShaderWidgetBase
{
Q_OBJECT
public:
//! Creates new color ramp shader widget
QgsColorRampShaderWidget( QWidget *parent = nullptr );
//! Allows quantile classification mode for raster layers
void initForUseWithRasterLayer();
//! Associates raster with the widget
void setRasterBand( QgsRasterDataProvider *dp, int band, const QgsRectangle &extent );
//! Sets min max and classify color tree
void setMinMaxAndClassify( double min, double max );
//! Sets min max
void setMinMax( double min, double max );
//! Returns shared function used in the renderer
QgsColorRampShader shader() const;
//! Sets widget state from the color ramp shader
void setFromShader( const QgsColorRampShader &colorRampShader );
signals:
//! Color ramp tree has changed
void minMaxChangedFromTree( double min, double max );
//! Widget changed
void widgetChanged();
//! Classification mode changed
void classificationModeChanged( QgsColorRampShader::ClassificationMode mode );
public slots:
/**
* Executes the single band pseudo raster classification
*/
void classify();
//! Loads min and max values from color ramp tree
void loadMinMaxFromTree();
protected:
//! Populates color ramp tree from ramp items
void populateColormapTreeWidget( const QList<QgsColorRampShader::ColorRampItem> &colorRampItems );
private:
enum Column
{
ValueColumn = 0,
ColorColumn = 1,
LabelColumn = 2,
};
/**
* Generate labels from the values in the color map.
* Skip labels which were manually edited (black text).
* Text of generated labels is made gray
*/
void autoLabel();
//! Extract the unit out of the current labels and set the unit field.
void setUnitFromLabels();
QMenu *contextMenu = nullptr;
private slots:
void applyColorRamp();
void mAddEntryButton_clicked();
void mDeleteEntryButton_clicked();
void mLoadFromBandButton_clicked();
void mLoadFromFileButton_clicked();
void mExportToFileButton_clicked();
void mUnitLineEdit_textEdited( const QString &text ) { Q_UNUSED( text ); autoLabel(); }
void mColormapTreeWidget_itemDoubleClicked( QTreeWidgetItem *item, int column );
void mColormapTreeWidget_itemEdited( QTreeWidgetItem *item, int column );
void mColorInterpolationComboBox_currentIndexChanged( int index );
void mClassificationModeComboBox_currentIndexChanged( int index );
void changeColor();
void changeOpacity();
private:
void setLineEditValue( QLineEdit *lineEdit, double value );
double lineEditValue( const QLineEdit *lineEdit ) const;
void resetClassifyButton();
double mMin = std::numeric_limits<double>::quiet_NaN();
double mMax = std::numeric_limits<double>::quiet_NaN();
// For mode with raster layer
QgsRasterDataProvider *mRasterDataProvider = nullptr;
int mBand = -1;
QgsRectangle mExtent;
};
#endif // QGSCOLORRAMPSHADERWIDGET_H

View File

@ -142,9 +142,8 @@ QgsSingleBandPseudoColorRendererWidget::QgsSingleBandPseudoColorRendererWidget(
connect( mClipCheckBox, &QAbstractButton::toggled, this, &QgsRasterRendererWidget::widgetChanged );
}
QgsRasterRenderer *QgsSingleBandPseudoColorRendererWidget::renderer()
QgsColorRampShader *QgsSingleBandPseudoColorRendererWidget::shaderFunction() const
{
QgsRasterShader *rasterShader = new QgsRasterShader();
QgsColorRampShader *colorRampShader = new QgsColorRampShader( lineEditValue( mMinLineEdit ), lineEditValue( mMaxLineEdit ) );
colorRampShader->setColorRampType( static_cast< QgsColorRampShader::Type >( mColorInterpolationComboBox->currentData().toInt() ) );
colorRampShader->setClassificationMode( static_cast< QgsColorRampShader::ClassificationMode >( mClassificationModeComboBox->currentData().toInt() ) );
@ -175,8 +174,13 @@ QgsRasterRenderer *QgsSingleBandPseudoColorRendererWidget::renderer()
{
colorRampShader->setSourceColorRamp( btnColorRamp->colorRamp() );
}
return colorRampShader;
}
rasterShader->setRasterShaderFunction( colorRampShader );
QgsRasterRenderer *QgsSingleBandPseudoColorRendererWidget::renderer()
{
QgsRasterShader *rasterShader = new QgsRasterShader();
rasterShader->setRasterShaderFunction( shaderFunction() );
int bandNumber = mBandComboBox->currentBand();
QgsSingleBandPseudoColorRenderer *renderer = new QgsSingleBandPseudoColorRenderer( mRasterLayer->dataProvider(), bandNumber, rasterShader );
@ -191,6 +195,11 @@ void QgsSingleBandPseudoColorRendererWidget::doComputations()
mMinMaxWidget->doComputations();
}
int QgsSingleBandPseudoColorRendererWidget::currentBand() const
{
return mBandComboBox->currentBand();
}
void QgsSingleBandPseudoColorRendererWidget::setMapCanvas( QgsMapCanvas *canvas )
{
QgsRasterRendererWidget::setMapCanvas( canvas );

View File

@ -42,10 +42,16 @@ class GUI_EXPORT QgsSingleBandPseudoColorRendererWidget: public QgsRasterRendere
static QgsRasterRendererWidget *create( QgsRasterLayer *layer, const QgsRectangle &extent ) SIP_FACTORY { return new QgsSingleBandPseudoColorRendererWidget( layer, extent ); }
QgsRasterRenderer *renderer() override;
//! Returns shader function used in the renderer. Caller takes ownership and deletes it.
QgsColorRampShader *shaderFunction() const SIP_FACTORY;
void setMapCanvas( QgsMapCanvas *canvas ) override;
void doComputations() override;
QgsRasterMinMaxWidget *minMaxWidget() override { return mMinMaxWidget; }
//! Returns the current raster band number
int currentBand() const;
void setFromRenderer( const QgsRasterRenderer *r );
public slots:

View File

@ -98,10 +98,21 @@ QgsMeshFace QgsMdalProvider::face( int index ) const
bool QgsMdalProvider::addDataset( const QString &uri )
{
int datasetCount = mDatasets.count();
std::string str = uri.toStdString();
MDAL_M_LoadDatasets( mMeshH, str.c_str() );
refreshDatasets();
return true;
if ( datasetCount == mDatasets.count() )
{
return false;
}
else
{
emit dataChanged();
return true; // Ok
}
}
int QgsMdalProvider::datasetCount() const

View File

@ -8,6 +8,7 @@ FILE(GLOB PROCESSING_UIS "${CMAKE_CURRENT_SOURCE_DIR}/processing/*.ui")
FILE(GLOB AUTH_UIS "${CMAKE_CURRENT_SOURCE_DIR}/auth/*.ui")
FILE(GLOB RASTER_UIS "${CMAKE_CURRENT_SOURCE_DIR}/raster/*.ui")
FILE(GLOB STYLEDOCK_UIS "${CMAKE_CURRENT_SOURCE_DIR}/styledock/*.ui")
FILE(GLOB MESH_UIS "${CMAKE_CURRENT_SOURCE_DIR}/mesh/*.ui")
FILE(GLOB _3D_UIS "${CMAKE_CURRENT_SOURCE_DIR}/3d/*.ui")
QT5_WRAP_UI(QGIS_UIS_H
@ -20,6 +21,7 @@ QT5_WRAP_UI(QGIS_UIS_H
${RASTER_UIS}
${STYLEDOCK_UIS}
${LAYOUT_UIS}
${MESH_UIS}
${_3D_UIS}
)

View File

@ -0,0 +1,467 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>QgsMeshLayerPropertiesBase</class>
<widget class="QDialog" name="QgsMeshLayerPropertiesBase">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>815</width>
<height>777</height>
</rect>
</property>
<property name="minimumSize">
<size>
<width>700</width>
<height>0</height>
</size>
</property>
<property name="windowTitle">
<string>Raster Layer Properties</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QSplitter" name="mOptionsSplitter">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="childrenCollapsible">
<bool>false</bool>
</property>
<widget class="QFrame" name="mOptionsListFrame">
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<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="QgsFilterLineEdit" name="mSearchLineEdit"/>
</item>
<item>
<widget class="QListWidget" name="mOptionsListWidget">
<property name="minimumSize">
<size>
<width>58</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>150</width>
<height>16777215</height>
</size>
</property>
<property name="horizontalScrollBarPolicy">
<enum>Qt::ScrollBarAlwaysOff</enum>
</property>
<property name="editTriggers">
<set>QAbstractItemView::NoEditTriggers</set>
</property>
<property name="iconSize">
<size>
<width>32</width>
<height>32</height>
</size>
</property>
<property name="textElideMode">
<enum>Qt::ElideNone</enum>
</property>
<property name="resizeMode">
<enum>QListView::Adjust</enum>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
<item>
<property name="text">
<string>Information</string>
</property>
<property name="icon">
<iconset resource="../../../images/images.qrc">
<normaloff>:/images/themes/default/propertyicons/metadata.svg</normaloff>:/images/themes/default/propertyicons/metadata.svg</iconset>
</property>
</item>
<item>
<property name="text">
<string>Source</string>
</property>
<property name="icon">
<iconset resource="../../../images/images.qrc">
<normaloff>:/images/themes/default/propertyicons/system.svg</normaloff>:/images/themes/default/propertyicons/system.svg</iconset>
</property>
</item>
<item>
<property name="text">
<string>Style</string>
</property>
<property name="toolTip">
<string>Style</string>
</property>
<property name="icon">
<iconset resource="../../../images/images.qrc">
<normaloff>:/images/themes/default/propertyicons/symbology.svg</normaloff>:/images/themes/default/propertyicons/symbology.svg</iconset>
</property>
</item>
</widget>
</item>
</layout>
</widget>
<widget class="QFrame" name="mOptionsFrame">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>1</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3">
<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="QStackedWidget" name="mOptionsStackedWidget">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="currentIndex">
<number>0</number>
</property>
<widget class="QWidget" name="mOptsPage_Information">
<layout class="QVBoxLayout" name="verticalLayout_20">
<item>
<widget class="QTextBrowser" name="mInformationTextBrowser"/>
</item>
</layout>
</widget>
<widget class="QWidget" name="mOptsPage_Source">
<layout class="QVBoxLayout" name="verticalLayout_6">
<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="QgsScrollArea" name="scrollArea_3">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="widgetResizable">
<bool>true</bool>
</property>
<widget class="QWidget" name="scrollAreaWidgetContents_3">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>261</width>
<height>144</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_4">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_14">
<item>
<widget class="QLabel" name="label_8">
<property name="text">
<string>Layer name</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="mLayerOrigNameLineEd"/>
</item>
<item>
<widget class="QLabel" name="label_9">
<property name="text">
<string>displayed as</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="leDisplayName">
<property name="styleSheet">
<string notr="true">color: #505050;
background-color: #F0F0F0;
border: 1px solid #B0B0B0;
border-radius: 2px;</string>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_9" stretch="0">
<property name="topMargin">
<number>5</number>
</property>
<item>
<widget class="QLabel" name="label_7">
<property name="text">
<string>Set source coordinate reference system</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QgsProjectionSelectionWidget" name="mCrsSelector" native="true">
<property name="focusPolicy">
<enum>Qt::StrongFocus</enum>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>Uri</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="mUriLabel">
<property name="text">
<string/>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QPushButton" name="mAddDatasetButton">
<property name="text">
<string>Assign extra dataset to mesh</string>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer_3">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>415</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="mOptsPage_Style">
<layout class="QVBoxLayout" name="verticalLayout_14">
<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="QgsScrollArea" name="scrollArea">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="widgetResizable">
<bool>true</bool>
</property>
<widget class="QWidget" name="mOptsPage_StyleContent">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>100</width>
<height>30</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_10"/>
</widget>
</widget>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
</widget>
</widget>
</item>
<item>
<widget class="QFrame" name="mButtonBoxFrame">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<layout class="QGridLayout" name="gridLayout">
<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 row="0" column="0" colspan="2">
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Apply|QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>QgsFilterLineEdit</class>
<extends>QLineEdit</extends>
<header>qgsfilterlineedit.h</header>
</customwidget>
<customwidget>
<class>QgsProjectionSelectionWidget</class>
<extends>QWidget</extends>
<header>qgsprojectionselectionwidget.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>QgsScrollArea</class>
<extends>QScrollArea</extends>
<header>qgsscrollarea.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<tabstops>
<tabstop>mSearchLineEdit</tabstop>
<tabstop>mOptionsListWidget</tabstop>
<tabstop>mInformationTextBrowser</tabstop>
<tabstop>scrollArea_3</tabstop>
<tabstop>mLayerOrigNameLineEd</tabstop>
<tabstop>leDisplayName</tabstop>
<tabstop>mCrsSelector</tabstop>
<tabstop>scrollArea</tabstop>
</tabstops>
<resources>
<include location="../../../images/images.qrc"/>
<include location="../../../images/images.qrc"/>
<include location="../../../images/images.qrc"/>
<include location="../../../images/images.qrc"/>
<include location="../../../images/images.qrc"/>
<include location="../../../images/images.qrc"/>
<include location="../../../images/images.qrc"/>
<include location="../../../images/images.qrc"/>
<include location="../../../images/images.qrc"/>
<include location="../../../images/images.qrc"/>
<include location="../../../images/images.qrc"/>
<include location="../../../images/images.qrc"/>
<include location="../../../images/images.qrc"/>
<include location="../../../images/images.qrc"/>
<include location="../../../images/images.qrc"/>
<include location="../../../images/images.qrc"/>
<include location="../../../images/images.qrc"/>
<include location="../../../images/images.qrc"/>
<include location="../../../images/images.qrc"/>
<include location="../../../images/images.qrc"/>
<include location="../../../images/images.qrc"/>
<include location="../../../images/images.qrc"/>
<include location="../../../images/images.qrc"/>
<include location="../../../images/images.qrc"/>
<include location="../../../images/images.qrc"/>
<include location="../../../images/images.qrc"/>
<include location="../../../images/images.qrc"/>
<include location="../../../images/images.qrc"/>
<include location="../../../images/images.qrc"/>
</resources>
<connections>
<connection>
<sender>mOptionsListWidget</sender>
<signal>currentRowChanged(int)</signal>
<receiver>mOptionsStackedWidget</receiver>
<slot>setCurrentIndex(int)</slot>
<hints>
<hint type="sourcelabel">
<x>86</x>
<y>325</y>
</hint>
<hint type="destinationlabel">
<x>794</x>
<y>14</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@ -0,0 +1,86 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>QgsMeshRendererActiveDatasetWidgetBase</class>
<widget class="QWidget" name="QgsMeshRendererActiveDatasetWidgetBase">
<property name="enabled">
<bool>false</bool>
</property>
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>319</width>
<height>317</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QgsMeshDatasetGroupTreeView" name="mDatasetGroupTreeView">
<property name="minimumSize">
<size>
<width>0</width>
<height>100</height>
</size>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_2">
<property name="text">
<string>Dataset in Selected Group(s)</string>
</property>
</widget>
</item>
<item>
<widget class="QSlider" name="mDatasetSlider">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="tickPosition">
<enum>QSlider::TicksBelow</enum>
</property>
<property name="tickInterval">
<number>1</number>
</property>
</widget>
</item>
<item>
<widget class="QgsCollapsibleGroupBox" name="mActiveDatasetMetadataGroup">
<property name="title">
<string>Metadata</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QLabel" name="mActiveDatasetMetadata">
<property name="text">
<string/>
</property>
<property name="textFormat">
<enum>Qt::RichText</enum>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>QgsMeshDatasetGroupTreeView</class>
<extends>QTreeView</extends>
<header>mesh/qgsmeshdatasetgrouptreeview.h</header>
</customwidget>
<customwidget>
<class>QgsCollapsibleGroupBox</class>
<extends>QGroupBox</extends>
<header>qgscollapsiblegroupbox.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>

View File

@ -0,0 +1,75 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>QgsMeshRendererMeshSettingsWidgetBase</class>
<widget class="QWidget" name="QgsMeshRendererMeshSettingsWidgetBase">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>279</width>
<height>84</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QGroupBox" name="groupBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="title">
<string>Line Width and Color</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QgsDoubleSpinBox" name="mLineWidthSpinBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item>
<widget class="QgsColorButton" name="mColorWidget">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>QgsDoubleSpinBox</class>
<extends>QDoubleSpinBox</extends>
<header>qgsdoublespinbox.h</header>
</customwidget>
<customwidget>
<class>QgsColorButton</class>
<extends>QFrame</extends>
<header>qgscolorbutton.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>

View File

@ -0,0 +1,78 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>QgsMeshRendererScalarSettingsWidgetBase</class>
<widget class="QWidget" name="QgsMeshRendererScalarSettingsWidgetBase">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>344</width>
<height>267</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QLabel" name="mScalarMinLabel">
<property name="text">
<string>Min</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="mScalarMinLineEdit">
<property name="text">
<string>0</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="mScalarMaxLabel">
<property name="text">
<string>Max</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="mScalarMaxLineEdit">
<property name="text">
<string>1</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="mScalarRecalculateMinMaxButton">
<property name="text">
<string>Recalculate</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QgsColorRampShaderWidget" name="mScalarColorRampShaderWidget" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>QgsColorRampShaderWidget</class>
<extends>QWidget</extends>
<header>raster/qgscolorrampshaderwidget.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>

View File

@ -0,0 +1,233 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>QgsMeshRendererVectorSettingsWidgetBase</class>
<widget class="QWidget" name="QgsMeshRendererVectorSettingsWidgetBase">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>310</width>
<height>419</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>Line Width and Color</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QgsDoubleSpinBox" name="mLineWidthSpinBox"/>
</item>
<item>
<widget class="QgsColorButton" name="mColorWidget"/>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="filterByMagGroupBox">
<property name="title">
<string>Filter by Magnitude</string>
</property>
<property name="checked">
<bool>false</bool>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QLabel" name="minimumMagLabel">
<property name="text">
<string>Min</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="mMinMagLineEdit"/>
</item>
<item>
<widget class="QLabel" name="maximumMagLabel">
<property name="text">
<string> Max</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="mMaxMagLineEdit"/>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="headOptionsGroupBox">
<property name="title">
<string>Head Options</string>
</property>
<layout class="QGridLayout" name="gridLayout_4">
<item row="0" column="0">
<widget class="QLabel" name="headWidthLabel">
<property name="text">
<string>Width</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="mHeadWidthLineEdit"/>
</item>
<item row="0" column="2">
<widget class="QLabel" name="percShaftLenLabel">
<property name="text">
<string>% of Shaft Length</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="headLengthLabel">
<property name="text">
<string>Length</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLineEdit" name="mHeadLengthLineEdit"/>
</item>
<item row="1" column="2">
<widget class="QLabel" name="percShaftLenLabel_2">
<property name="text">
<string>% of Shaft Length</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="generalOptionsGroupBox">
<property name="title">
<string>Arrow Length</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QComboBox" name="mShaftLengthComboBox">
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="sizeAdjustPolicy">
<enum>QComboBox::AdjustToContents</enum>
</property>
<item>
<property name="text">
<string>Defined by Min and Max</string>
</property>
</item>
<item>
<property name="text">
<string>Scaled to Magnitude</string>
</property>
</item>
<item>
<property name="text">
<string>Fixed</string>
</property>
</item>
</widget>
</item>
<item>
<widget class="QStackedWidget" name="mShaftOptionsStackedWidget">
<property name="currentIndex">
<number>2</number>
</property>
<widget class="QWidget" name="page">
<layout class="QFormLayout" name="formLayout">
<item row="0" column="0">
<widget class="QLabel" name="minimumShaftLabel">
<property name="text">
<string>Minimum</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="mMinimumShaftLineEdit"/>
</item>
<item row="1" column="0">
<widget class="QLabel" name="maximumShaftLabel">
<property name="text">
<string>Maximum</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLineEdit" name="mMaximumShaftLineEdit"/>
</item>
</layout>
</widget>
<widget class="QWidget" name="page_2">
<layout class="QFormLayout" name="formLayout_2">
<item row="0" column="0">
<widget class="QLabel" name="scaleByFactorOfLabel">
<property name="text">
<string>Scale by a Factor of:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="mScaleShaftByFactorOfLineEdit"/>
</item>
</layout>
</widget>
<widget class="QWidget" name="page_3">
<layout class="QFormLayout" name="formLayout_3">
<item row="0" column="0">
<widget class="QLabel" name="LengthLabel">
<property name="text">
<string>Length</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="mShaftLengthLineEdit"/>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>QgsDoubleSpinBox</class>
<extends>QDoubleSpinBox</extends>
<header>qgsdoublespinbox.h</header>
</customwidget>
<customwidget>
<class>QgsColorButton</class>
<extends>QFrame</extends>
<header>qgscolorbutton.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>

View File

@ -0,0 +1,335 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>QgsRendererMeshPropsWidgetBase</class>
<widget class="QWidget" name="QgsRendererMeshPropsWidgetBase">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>774</width>
<height>593</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QTabWidget" name="mStyleOptionsTab">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="tabPosition">
<enum>QTabWidget::North</enum>
</property>
<property name="tabShape">
<enum>QTabWidget::Rounded</enum>
</property>
<property name="currentIndex">
<number>0</number>
</property>
<property name="iconSize">
<size>
<width>20</width>
<height>20</height>
</size>
</property>
<property name="elideMode">
<enum>Qt::ElideNone</enum>
</property>
<property name="documentMode">
<bool>true</bool>
</property>
<property name="tabsClosable">
<bool>false</bool>
</property>
<widget class="QWidget" name="mActiveDatasetTab">
<attribute name="icon">
<iconset resource="../../../images/images.qrc">
<normaloff>:/images/themes/default/propertyicons/general.svg</normaloff>:/images/themes/default/propertyicons/general.svg</iconset>
</attribute>
<attribute name="title">
<string/>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_11">
<item>
<widget class="QgsMeshRendererActiveDatasetWidget" name="mMeshRendererActiveDatasetWidget" native="true">
<property name="enabled">
<bool>true</bool>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer_3">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<widget class="QWidget" name="mContoursTab">
<attribute name="icon">
<iconset resource="../../../images/images.qrc">
<normaloff>:/images/themes/default/propertyicons/meshcontours.svg</normaloff>:/images/themes/default/propertyicons/meshcontours.svg</iconset>
</attribute>
<attribute name="title">
<string/>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_10">
<item>
<widget class="QGroupBox" name="mContoursGroupBox">
<property name="title">
<string>Show contours</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>false</bool>
</property>
<layout class="QVBoxLayout" name="verticalLayout_6">
<item>
<widget class="QgsMeshRendererScalarSettingsWidget" name="mMeshRendererScalarSettingsWidget" native="true"/>
</item>
<item>
<spacer name="verticalSpacer_4">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="mVectorsTab">
<attribute name="icon">
<iconset resource="../../../images/images.qrc">
<normaloff>:/images/themes/default/propertyicons/meshvectors.svg</normaloff>:/images/themes/default/propertyicons/meshvectors.svg</iconset>
</attribute>
<attribute name="title">
<string/>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QGroupBox" name="mVectorsGroupBox">
<property name="title">
<string>Show Vectors</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>false</bool>
</property>
<layout class="QVBoxLayout" name="verticalLayout_5">
<item>
<widget class="QgsMeshRendererVectorSettingsWidget" name="mMeshRendererVectorSettingsWidget" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer_5">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="mMeshTab">
<attribute name="icon">
<iconset resource="../../../images/images.qrc">
<normaloff>:/images/themes/default/propertyicons/meshframe.svg</normaloff>:/images/themes/default/propertyicons/meshframe.svg</iconset>
</attribute>
<attribute name="title">
<string/>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_12">
<item>
<widget class="QGroupBox" name="mNativeMeshGroup">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="title">
<string>Native Mesh rendering</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<layout class="QVBoxLayout" name="verticalLayout_4">
<item>
<widget class="QgsMeshRendererMeshSettingsWidget" name="mNativeMeshSettingsWidget" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="mTriangularMeshGroup">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="title">
<string>Triangular Mesh Rendering</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>false</bool>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<widget class="QgsMeshRendererMeshSettingsWidget" name="mTriangularMeshSettingsWidget" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>QgsMeshRendererScalarSettingsWidget</class>
<extends>QWidget</extends>
<header>mesh/qgsmeshrendererscalarsettingswidget.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>QgsMeshRendererActiveDatasetWidget</class>
<extends>QWidget</extends>
<header>mesh/qgsmeshrendereractivedatasetwidget.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>QgsMeshRendererMeshSettingsWidget</class>
<extends>QWidget</extends>
<header>mesh/qgsmeshrenderermeshsettingswidget.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>QgsMeshRendererVectorSettingsWidget</class>
<extends>QWidget</extends>
<header>mesh/qgsmeshrenderervectorsettingswidget.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources>
<include location="../../../images/images.qrc"/>
<include location="../../../images/images.qrc"/>
<include location="../../../images/images.qrc"/>
<include location="../../../images/images.qrc"/>
<include location="../../../images/images.qrc"/>
<include location="../../../images/images.qrc"/>
<include location="../../../images/images.qrc"/>
<include location="../../../images/images.qrc"/>
<include location="../../../images/images.qrc"/>
<include location="../../../images/images.qrc"/>
<include location="../../../images/images.qrc"/>
<include location="../../../images/images.qrc"/>
<include location="../../../images/images.qrc"/>
<include location="../../../images/images.qrc"/>
<include location="../../../images/images.qrc"/>
<include location="../../../images/images.qrc"/>
<include location="../../../images/images.qrc"/>
<include location="../../../images/images.qrc"/>
<include location="../../../images/images.qrc"/>
<include location="../../../images/images.qrc"/>
<include location="../../../images/images.qrc"/>
<include location="../../../images/images.qrc"/>
<include location="../../../images/images.qrc"/>
<include location="../../../images/images.qrc"/>
<include location="../../../images/images.qrc"/>
<include location="../../../images/images.qrc"/>
<include location="../../../images/images.qrc"/>
<include location="../../../images/images.qrc"/>
<include location="../../../images/images.qrc"/>
</resources>
<connections/>
</ui>

View File

@ -0,0 +1,322 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>QgsColorRampShaderWidgetBase</class>
<widget class="QWidget" name="QgsColorRampShaderWidgetBase">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>396</width>
<height>605</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<property name="leftMargin">
<number>3</number>
</property>
<property name="topMargin">
<number>3</number>
</property>
<property name="rightMargin">
<number>3</number>
</property>
<property name="bottomMargin">
<number>3</number>
</property>
<item row="3" column="0" colspan="3">
<widget class="QTreeWidget" name="mColormapTreeWidget">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>250</height>
</size>
</property>
<attribute name="headerDefaultSectionSize">
<number>70</number>
</attribute>
<attribute name="headerMinimumSectionSize">
<number>10</number>
</attribute>
<attribute name="headerStretchLastSection">
<bool>true</bool>
</attribute>
<column>
<property name="text">
<string>Value</string>
</property>
</column>
<column>
<property name="text">
<string>Color</string>
</property>
</column>
<column>
<property name="text">
<string>Label</string>
</property>
</column>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="mColorInterpolationLabel_2">
<property name="text">
<string>Color ramp</string>
</property>
</widget>
</item>
<item row="1" column="1" colspan="2">
<widget class="QgsColorRampButton" name="btnColorRamp">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>120</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>16777215</height>
</size>
</property>
</widget>
</item>
<item row="0" column="1" colspan="2">
<widget class="QComboBox" name="mColorInterpolationComboBox"/>
</item>
<item row="0" column="0">
<widget class="QLabel" name="mColorInterpolationLabel">
<property name="text">
<string>Interpolation</string>
</property>
</widget>
</item>
<item row="5" column="0" colspan="3">
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QPushButton" name="mClassifyButton">
<property name="text">
<string>Classify</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="mAddEntryButton">
<property name="toolTip">
<string>Add values manually</string>
</property>
<property name="icon">
<iconset resource="../../images/images.qrc">
<normaloff>:/images/themes/default/symbologyAdd.svg</normaloff>:/images/themes/default/symbologyAdd.svg</iconset>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="mDeleteEntryButton">
<property name="toolTip">
<string>Remove selected row(s)</string>
</property>
<property name="icon">
<iconset resource="../../images/images.qrc">
<normaloff>:/images/themes/default/symbologyRemove.svg</normaloff>:/images/themes/default/symbologyRemove.svg</iconset>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="mLoadFromBandButton">
<property name="toolTip">
<string>Load color map from band</string>
</property>
<property name="icon">
<iconset resource="../../images/images.qrc">
<normaloff>:/images/themes/default/mActionDraw.svg</normaloff>:/images/themes/default/mActionDraw.svg</iconset>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="mLoadFromFileButton">
<property name="toolTip">
<string>Load color map from file</string>
</property>
<property name="icon">
<iconset resource="../../images/images.qrc">
<normaloff>:/images/themes/default/mActionFileOpen.svg</normaloff>:/images/themes/default/mActionFileOpen.svg</iconset>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="mExportToFileButton">
<property name="toolTip">
<string>Export color map to file</string>
</property>
<property name="icon">
<iconset resource="../../images/images.qrc">
<normaloff>:/images/themes/default/mActionFileSaveAs.svg</normaloff>:/images/themes/default/mActionFileSaveAs.svg</iconset>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>48</width>
<height>28</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item row="6" column="0" colspan="3">
<widget class="QCheckBox" name="mClipCheckBox">
<property name="toolTip">
<string>If checked, any pixels with a value out of range will not be rendered</string>
</property>
<property name="text">
<string>Clip out of range values</string>
</property>
</widget>
</item>
<item row="4" column="0" colspan="3">
<layout class="QHBoxLayout" name="horizontalLayout_5">
<item>
<widget class="QLabel" name="mClassificationModeLabel">
<property name="text">
<string>Mode</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="mClassificationModeComboBox"/>
</item>
<item>
<spacer name="horizontalSpacer_4">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="mNumberOfEntriesLabel">
<property name="text">
<string>Classes</string>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="mNumberOfEntriesSpinBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimum">
<number>2</number>
</property>
<property name="maximum">
<number>255</number>
</property>
<property name="value">
<number>5</number>
</property>
</widget>
</item>
</layout>
</item>
<item row="2" column="1" colspan="2">
<widget class="QLineEdit" name="mUnitLineEdit">
<property name="toolTip">
<string>Unit suffix</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="mUnitLabel">
<property name="text">
<string>Label unit
suffix</string>
</property>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>QgsColorRampButton</class>
<extends>QToolButton</extends>
<header>qgscolorrampbutton.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<tabstops>
<tabstop>mColorInterpolationComboBox</tabstop>
<tabstop>btnColorRamp</tabstop>
<tabstop>mUnitLineEdit</tabstop>
<tabstop>mColormapTreeWidget</tabstop>
<tabstop>mClassificationModeComboBox</tabstop>
<tabstop>mNumberOfEntriesSpinBox</tabstop>
<tabstop>mClassifyButton</tabstop>
<tabstop>mAddEntryButton</tabstop>
<tabstop>mDeleteEntryButton</tabstop>
<tabstop>mLoadFromBandButton</tabstop>
<tabstop>mLoadFromFileButton</tabstop>
<tabstop>mExportToFileButton</tabstop>
<tabstop>mClipCheckBox</tabstop>
</tabstops>
<resources>
<include location="../../images/images.qrc"/>
<include location="../../images/images.qrc"/>
<include location="../../images/images.qrc"/>
<include location="../../images/images.qrc"/>
<include location="../../images/images.qrc"/>
<include location="../../images/images.qrc"/>
<include location="../../images/images.qrc"/>
<include location="../../images/images.qrc"/>
<include location="../../images/images.qrc"/>
<include location="../../images/images.qrc"/>
<include location="../../images/images.qrc"/>
<include location="../../images/images.qrc"/>
<include location="../../images/images.qrc"/>
<include location="../../images/images.qrc"/>
<include location="../../images/images.qrc"/>
<include location="../../images/images.qrc"/>
<include location="../../images/images.qrc"/>
<include location="../../images/images.qrc"/>
<include location="../../images/images.qrc"/>
<include location="../../images/images.qrc"/>
<include location="../../images/images.qrc"/>
<include location="../../images/images.qrc"/>
<include location="../../images/images.qrc"/>
<include location="../../images/images.qrc"/>
<include location="../../images/images.qrc"/>
<include location="../../images/images.qrc"/>
<include location="../../images/images.qrc"/>
<include location="../../images/images.qrc"/>
<include location="../../images/images.qrc"/>
</resources>
<connections/>
</ui>

View File

@ -42,7 +42,16 @@
<enum>QFrame::Raised</enum>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<property name="margin">
<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>
@ -209,7 +218,16 @@
<enum>QFrame::Raised</enum>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3">
<property name="margin">
<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>
@ -232,7 +250,16 @@
</widget>
<widget class="QWidget" name="mOptsPage_Source">
<layout class="QVBoxLayout" name="verticalLayout_6">
<property name="margin">
<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>
@ -248,8 +275,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>744</width>
<height>705</height>
<width>643</width>
<height>729</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_7">
@ -302,7 +329,7 @@ border-radius: 2px;</string>
</layout>
</item>
<item>
<widget class="QgsProjectionSelectionWidget" name="mCrsSelector">
<widget class="QgsProjectionSelectionWidget" name="mCrsSelector" native="true">
<property name="focusPolicy">
<enum>Qt::StrongFocus</enum>
</property>
@ -329,7 +356,16 @@ border-radius: 2px;</string>
</widget>
<widget class="QWidget" name="mOptsPage_Style">
<layout class="QVBoxLayout" name="verticalLayout_14">
<property name="margin">
<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>
@ -345,8 +381,8 @@ border-radius: 2px;</string>
<rect>
<x>0</x>
<y>0</y>
<width>850</width>
<height>748</height>
<width>643</width>
<height>729</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_10">
@ -361,7 +397,7 @@ border-radius: 2px;</string>
<property name="title">
<string>Band rendering</string>
</property>
<property name="syncGroup">
<property name="syncGroup" stdset="0">
<string notr="true">rasterstyle</string>
</property>
<layout class="QGridLayout" name="gridLayout_14">
@ -406,13 +442,13 @@ border-radius: 2px;</string>
<property name="title">
<string>Color rendering</string>
</property>
<property name="collapsed">
<property name="collapsed" stdset="0">
<bool>false</bool>
</property>
<property name="syncGroup">
<property name="syncGroup" stdset="0">
<string notr="true">rasterstyle</string>
</property>
<property name="saveCollapsedState">
<property name="saveCollapsedState" stdset="0">
<bool>true</bool>
</property>
<layout class="QGridLayout" name="gridLayout_2">
@ -603,7 +639,7 @@ border-radius: 2px;</string>
<height>16777215</height>
</size>
</property>
<property name="text">
<property name="text" stdset="0">
<string/>
</property>
</widget>
@ -708,13 +744,13 @@ border-radius: 2px;</string>
<property name="checkable">
<bool>false</bool>
</property>
<property name="collapsed">
<property name="collapsed" stdset="0">
<bool>false</bool>
</property>
<property name="syncGroup">
<property name="syncGroup" stdset="0">
<string notr="true">rasterstyle</string>
</property>
<property name="saveCollapsedState">
<property name="saveCollapsedState" stdset="0">
<bool>true</bool>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
@ -908,7 +944,16 @@ border-radius: 2px;</string>
</widget>
<widget class="QWidget" name="mOptsPage_Transparency">
<layout class="QVBoxLayout" name="verticalLayout_4">
<property name="margin">
<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>
@ -924,8 +969,8 @@ border-radius: 2px;</string>
<rect>
<x>0</x>
<y>0</y>
<width>502</width>
<height>662</height>
<width>348</width>
<height>446</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_5">
@ -940,7 +985,7 @@ border-radius: 2px;</string>
<property name="title">
<string>Global opacity</string>
</property>
<property name="syncGroup">
<property name="syncGroup" stdset="0">
<string notr="true">rastertransp</string>
</property>
<layout class="QGridLayout" name="gridLayout_13">
@ -959,7 +1004,7 @@ border-radius: 2px;</string>
<property name="title">
<string>No data value</string>
</property>
<property name="syncGroup">
<property name="syncGroup" stdset="0">
<string notr="true">rastertransp</string>
</property>
<layout class="QGridLayout" name="gridLayout_11">
@ -1031,7 +1076,7 @@ border-radius: 2px;</string>
<property name="title">
<string>Custom transparency options</string>
</property>
<property name="syncGroup">
<property name="syncGroup" stdset="0">
<string notr="true">rastertransp</string>
</property>
<layout class="QGridLayout" name="gridLayout_3">
@ -1246,7 +1291,16 @@ border-radius: 2px;</string>
</widget>
<widget class="QWidget" name="mOptsPage_Histogram">
<layout class="QVBoxLayout" name="verticalLayout_15">
<property name="margin">
<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>
@ -1262,8 +1316,8 @@ border-radius: 2px;</string>
<rect>
<x>0</x>
<y>0</y>
<width>80</width>
<height>38</height>
<width>86</width>
<height>42</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_16">
@ -1307,18 +1361,27 @@ border-radius: 2px;</string>
<property name="checked">
<bool>false</bool>
</property>
<property name="syncGroup">
<property name="syncGroup" stdset="0">
<string notr="true">rastergeneral</string>
</property>
<layout class="QGridLayout" name="_5">
<property name="margin">
<property name="leftMargin">
<number>11</number>
</property>
<property name="topMargin">
<number>11</number>
</property>
<property name="rightMargin">
<number>11</number>
</property>
<property name="bottomMargin">
<number>11</number>
</property>
<property name="verticalSpacing">
<number>6</number>
</property>
<item row="0" column="0" colspan="2">
<widget class="QgsScaleRangeWidget" name="mScaleRangeWidget">
<widget class="QgsScaleRangeWidget" name="mScaleRangeWidget" native="true">
<property name="toolTip">
<string/>
</property>
@ -1393,7 +1456,16 @@ border-radius: 2px;</string>
</widget>
<widget class="QWidget" name="mOptsPage_Pyramids">
<layout class="QVBoxLayout" name="verticalLayout_9">
<property name="margin">
<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>
@ -1409,8 +1481,8 @@ border-radius: 2px;</string>
<rect>
<x>0</x>
<y>0</y>
<width>1004</width>
<height>254</height>
<width>553</width>
<height>193</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_12">
@ -1473,7 +1545,7 @@ border-radius: 2px;</string>
<string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
p, li { white-space: pre-wrap; }
&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'Noto Sans'; font-size:10pt; font-weight:400; font-style:normal;&quot;&gt;
&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;&quot;&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-family:'Cantarell'; font-size:11pt;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
</widget>
@ -1584,7 +1656,16 @@ p, li { white-space: pre-wrap; }
</widget>
<widget class="QWidget" name="mOptsPage_Server">
<layout class="QVBoxLayout" name="verticalLayout_8">
<property name="margin">
<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>
@ -1600,8 +1681,8 @@ p, li { white-space: pre-wrap; }
<rect>
<x>0</x>
<y>0</y>
<width>724</width>
<height>1060</height>
<width>643</width>
<height>729</height>
</rect>
</property>
<layout class="QGridLayout" name="gridLayout_12">
@ -1610,7 +1691,7 @@ p, li { white-space: pre-wrap; }
<property name="title">
<string>Description</string>
</property>
<property name="syncGroup">
<property name="syncGroup" stdset="0">
<string notr="true">rastermeta</string>
</property>
<layout class="QGridLayout" name="gridLayout_5">
@ -1746,7 +1827,7 @@ p, li { white-space: pre-wrap; }
<property name="title">
<string>Attribution</string>
</property>
<property name="syncGroup">
<property name="syncGroup" stdset="0">
<string notr="true">vectormeta</string>
</property>
<layout class="QGridLayout" name="gridLayout_7">
@ -1792,7 +1873,7 @@ p, li { white-space: pre-wrap; }
<property name="title">
<string>MetadataUrl</string>
</property>
<property name="syncGroup">
<property name="syncGroup" stdset="0">
<string notr="true">vectormeta</string>
</property>
<layout class="QGridLayout" name="gridLayout_9">
@ -2011,7 +2092,16 @@ p, li { white-space: pre-wrap; }
<enum>QFrame::Raised</enum>
</property>
<layout class="QGridLayout" name="gridLayout">
<property name="margin">
<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 row="0" column="0" colspan="2">
@ -2031,15 +2121,15 @@ p, li { white-space: pre-wrap; }
</widget>
<customwidgets>
<customwidget>
<class>QgsCollapsibleGroupBox</class>
<extends>QGroupBox</extends>
<header>qgscollapsiblegroupbox.h</header>
<class>QgsColorButton</class>
<extends>QFrame</extends>
<header>qgscolorbutton.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>QgsColorButton</class>
<extends>QPushButton</extends>
<header>qgscolorbutton.h</header>
<class>QgsCollapsibleGroupBox</class>
<extends>QGroupBox</extends>
<header>qgscollapsiblegroupbox.h</header>
<container>1</container>
</customwidget>
<customwidget>
@ -2155,6 +2245,34 @@ p, li { white-space: pre-wrap; }
</tabstops>
<resources>
<include location="../../images/images.qrc"/>
<include location="../../images/images.qrc"/>
<include location="../../images/images.qrc"/>
<include location="../../images/images.qrc"/>
<include location="../../images/images.qrc"/>
<include location="../../images/images.qrc"/>
<include location="../../images/images.qrc"/>
<include location="../../images/images.qrc"/>
<include location="../../images/images.qrc"/>
<include location="../../images/images.qrc"/>
<include location="../../images/images.qrc"/>
<include location="../../images/images.qrc"/>
<include location="../../images/images.qrc"/>
<include location="../../images/images.qrc"/>
<include location="../../images/images.qrc"/>
<include location="../../images/images.qrc"/>
<include location="../../images/images.qrc"/>
<include location="../../images/images.qrc"/>
<include location="../../images/images.qrc"/>
<include location="../../images/images.qrc"/>
<include location="../../images/images.qrc"/>
<include location="../../images/images.qrc"/>
<include location="../../images/images.qrc"/>
<include location="../../images/images.qrc"/>
<include location="../../images/images.qrc"/>
<include location="../../images/images.qrc"/>
<include location="../../images/images.qrc"/>
<include location="../../images/images.qrc"/>
<include location="../../images/images.qrc"/>
</resources>
<connections>
<connection>

View File

@ -342,6 +342,34 @@ suffix</string>
</tabstops>
<resources>
<include location="../../images/images.qrc"/>
<include location="../../images/images.qrc"/>
<include location="../../images/images.qrc"/>
<include location="../../images/images.qrc"/>
<include location="../../images/images.qrc"/>
<include location="../../images/images.qrc"/>
<include location="../../images/images.qrc"/>
<include location="../../images/images.qrc"/>
<include location="../../images/images.qrc"/>
<include location="../../images/images.qrc"/>
<include location="../../images/images.qrc"/>
<include location="../../images/images.qrc"/>
<include location="../../images/images.qrc"/>
<include location="../../images/images.qrc"/>
<include location="../../images/images.qrc"/>
<include location="../../images/images.qrc"/>
<include location="../../images/images.qrc"/>
<include location="../../images/images.qrc"/>
<include location="../../images/images.qrc"/>
<include location="../../images/images.qrc"/>
<include location="../../images/images.qrc"/>
<include location="../../images/images.qrc"/>
<include location="../../images/images.qrc"/>
<include location="../../images/images.qrc"/>
<include location="../../images/images.qrc"/>
<include location="../../images/images.qrc"/>
<include location="../../images/images.qrc"/>
<include location="../../images/images.qrc"/>
<include location="../../images/images.qrc"/>
</resources>
<connections/>
</ui>

View File

@ -0,0 +1,294 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>QgsColorRampShaderWidgetBase</class>
<widget class="QWidget" name="QgsColorRampShaderWidgetBase">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>396</width>
<height>605</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<property name="leftMargin">
<number>3</number>
</property>
<property name="topMargin">
<number>3</number>
</property>
<property name="rightMargin">
<number>3</number>
</property>
<property name="bottomMargin">
<number>3</number>
</property>
<item row="3" column="0" colspan="3">
<widget class="QTreeWidget" name="mColormapTreeWidget">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>250</height>
</size>
</property>
<attribute name="headerDefaultSectionSize">
<number>70</number>
</attribute>
<attribute name="headerMinimumSectionSize">
<number>10</number>
</attribute>
<attribute name="headerStretchLastSection">
<bool>true</bool>
</attribute>
<column>
<property name="text">
<string>Value</string>
</property>
</column>
<column>
<property name="text">
<string>Color</string>
</property>
</column>
<column>
<property name="text">
<string>Label</string>
</property>
</column>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="mColorInterpolationLabel_2">
<property name="text">
<string>Color ramp</string>
</property>
</widget>
</item>
<item row="1" column="1" colspan="2">
<widget class="QgsColorRampButton" name="btnColorRamp">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>120</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>16777215</height>
</size>
</property>
</widget>
</item>
<item row="0" column="1" colspan="2">
<widget class="QComboBox" name="mColorInterpolationComboBox"/>
</item>
<item row="0" column="0">
<widget class="QLabel" name="mColorInterpolationLabel">
<property name="text">
<string>Interpolation</string>
</property>
</widget>
</item>
<item row="5" column="0" colspan="3">
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QPushButton" name="mClassifyButton">
<property name="text">
<string>Classify</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="mAddEntryButton">
<property name="toolTip">
<string>Add values manually</string>
</property>
<property name="icon">
<iconset resource="../../images/images.qrc">
<normaloff>:/images/themes/default/symbologyAdd.svg</normaloff>:/images/themes/default/symbologyAdd.svg</iconset>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="mDeleteEntryButton">
<property name="toolTip">
<string>Remove selected row(s)</string>
</property>
<property name="icon">
<iconset resource="../../images/images.qrc">
<normaloff>:/images/themes/default/symbologyRemove.svg</normaloff>:/images/themes/default/symbologyRemove.svg</iconset>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="mLoadFromBandButton">
<property name="toolTip">
<string>Load color map from band</string>
</property>
<property name="icon">
<iconset resource="../../images/images.qrc">
<normaloff>:/images/themes/default/mActionDraw.svg</normaloff>:/images/themes/default/mActionDraw.svg</iconset>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="mLoadFromFileButton">
<property name="toolTip">
<string>Load color map from file</string>
</property>
<property name="icon">
<iconset resource="../../images/images.qrc">
<normaloff>:/images/themes/default/mActionFileOpen.svg</normaloff>:/images/themes/default/mActionFileOpen.svg</iconset>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="mExportToFileButton">
<property name="toolTip">
<string>Export color map to file</string>
</property>
<property name="icon">
<iconset resource="../../images/images.qrc">
<normaloff>:/images/themes/default/mActionFileSaveAs.svg</normaloff>:/images/themes/default/mActionFileSaveAs.svg</iconset>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>48</width>
<height>28</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item row="6" column="0" colspan="3">
<widget class="QCheckBox" name="mClipCheckBox">
<property name="toolTip">
<string>If checked, any pixels with a value out of range will not be rendered</string>
</property>
<property name="text">
<string>Clip out of range values</string>
</property>
</widget>
</item>
<item row="4" column="0" colspan="3">
<layout class="QHBoxLayout" name="horizontalLayout_5">
<item>
<widget class="QLabel" name="mClassificationModeLabel">
<property name="text">
<string>Mode</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="mClassificationModeComboBox"/>
</item>
<item>
<spacer name="horizontalSpacer_4">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="mNumberOfEntriesLabel">
<property name="text">
<string>Classes</string>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="mNumberOfEntriesSpinBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimum">
<number>2</number>
</property>
<property name="maximum">
<number>255</number>
</property>
<property name="value">
<number>5</number>
</property>
</widget>
</item>
</layout>
</item>
<item row="2" column="1" colspan="2">
<widget class="QLineEdit" name="mUnitLineEdit">
<property name="toolTip">
<string>Unit suffix</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="mUnitLabel">
<property name="text">
<string>Label unit
suffix</string>
</property>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>QgsColorRampButton</class>
<extends>QToolButton</extends>
<header>qgscolorrampbutton.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<tabstops>
<tabstop>mColorInterpolationComboBox</tabstop>
<tabstop>btnColorRamp</tabstop>
<tabstop>mUnitLineEdit</tabstop>
<tabstop>mColormapTreeWidget</tabstop>
<tabstop>mClassificationModeComboBox</tabstop>
<tabstop>mNumberOfEntriesSpinBox</tabstop>
<tabstop>mClassifyButton</tabstop>
<tabstop>mAddEntryButton</tabstop>
<tabstop>mDeleteEntryButton</tabstop>
<tabstop>mLoadFromBandButton</tabstop>
<tabstop>mLoadFromFileButton</tabstop>
<tabstop>mExportToFileButton</tabstop>
<tabstop>mClipCheckBox</tabstop>
</tabstops>
<resources>
<include location="../../images/images.qrc"/>
</resources>
<connections/>
</ui>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 78 KiB

After

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 78 KiB

After

Width:  |  Height:  |  Size: 78 KiB