This commit is contained in:
Radim Blazek 2012-06-15 16:47:57 +02:00
commit ab1c989ff2
51 changed files with 5491 additions and 166 deletions

View File

@ -34,6 +34,7 @@
<file>themes/default/mActionAddRing.png</file>
<file>themes/default/mActionAddSpatiaLiteLayer.png</file>
<file>themes/default/mActionAddVertex.png</file>
<file>themes/default/mActionAddWcsLayer.png</file>
<file>themes/default/mActionAddWmsLayer.png</file>
<file>themes/default/mActionAlignBottom.png</file>
<file>themes/default/mActionAlignHCenter.png</file>
@ -173,6 +174,7 @@
<file>themes/default/mIconMssql.png</file>
<file>themes/default/mIconNext.png</file>
<file>themes/default/mIconNoPyramid.png</file>
<file>themes/default/mIconOws.png</file>
<file>themes/default/mIconPointLayer.png</file>
<file>themes/default/mIconPolygonLayer.png</file>
<file>themes/default/mIconPostgis.png</file>
@ -190,7 +192,9 @@
<file>themes/default/mIconSymbology.png</file>
<file>themes/default/mIconTableLayer.png</file>
<file>themes/default/mIconUnknownLayerType.png</file>
<file>themes/default/mIconVectorLayer.png</file>
<file>themes/default/mIconWaitingForLayerType.png</file>
<file>themes/default/mIconWcs.png</file>
<file>themes/default/mIconWfs.png</file>
<file>themes/default/mIconWms.png</file>
<file>themes/default/mIconWmsLayer.png</file>
@ -247,6 +251,7 @@
<file>themes/gis/mActionAddRing.png</file>
<file>themes/gis/mActionAddSpatiaLiteLayer.png</file>
<file>themes/gis/mActionAddVertex.png</file>
<file>themes/gis/mActionAddWcsLayer.png</file>
<file>themes/gis/mActionAddWfsLayer.png</file>
<file>themes/gis/mActionAddWmsLayer.png</file>
<file>themes/gis/mActionAlignBottom.png</file>
@ -370,6 +375,9 @@
<file>themes/default/plugins/north_arrow.png</file>
<file>themes/default/plugins/scale_bar.png</file>
<file>themes/default/mActionAddWfsLayer.png</file>
<file>themes/gis/mIconOws.png</file>
<file>themes/gis/mIconVectorLayer.png</file>
<file>themes/gis/mIconWcs.png</file>
<file>themes/gis/mIconWms.png</file>
<file>themes/gis/mIconWfs.png</file>
<file>themes/gis/mIconSpatialite.png</file>

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 971 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 948 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@ -0,0 +1,675 @@
<?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="24"
height="24"
id="svg5692"
version="1.1"
inkscape:version="0.47 r22583"
sodipodi:docname="layer-ows.svg"
inkscape:export-filename="/mnt/home1/robert/svn/graphics/trunk/toolbar-icons/24x24/layer-wfs.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90"
style="display:inline">
<title
id="title4950">layer OGC Web service</title>
<defs
id="defs5694">
<linearGradient
inkscape:collect="always"
id="linearGradient2937">
<stop
style="stop-color:#ce5c00;stop-opacity:1;"
offset="0"
id="stop2939" />
<stop
style="stop-color:#ce5c00;stop-opacity:0;"
offset="1"
id="stop2941" />
</linearGradient>
<linearGradient
id="linearGradient7624">
<stop
style="stop-color:#555753;stop-opacity:1;"
offset="0"
id="stop7626" />
<stop
id="stop7634"
offset="0.40000001"
style="stop-color:#555753;stop-opacity:0.39215687;" />
<stop
style="stop-color:#555753;stop-opacity:0;"
offset="0.5"
id="stop7640" />
<stop
id="stop7632"
offset="0.60000002"
style="stop-color:#555753;stop-opacity:0.39215687;" />
<stop
style="stop-color:#555753;stop-opacity:1;"
offset="1"
id="stop7628" />
</linearGradient>
<linearGradient
id="linearGradient7614">
<stop
style="stop-color:#d3d7cf;stop-opacity:1;"
offset="0"
id="stop7616" />
<stop
id="stop7636"
offset="0.40000001"
style="stop-color:#d3d7cf;stop-opacity:0.38666666;" />
<stop
style="stop-color:#d3d7cf;stop-opacity:0;"
offset="0.5"
id="stop7638" />
<stop
id="stop7622"
offset="0.60000002"
style="stop-color:#d3d7cf;stop-opacity:0.39215687;" />
<stop
style="stop-color:#d3d7cf;stop-opacity:1;"
offset="1"
id="stop7618" />
</linearGradient>
<linearGradient
id="linearGradient2843">
<stop
style="stop-color:#eeeeec;stop-opacity:1;"
offset="0"
id="stop2845" />
<stop
style="stop-color:#c8c8c2;stop-opacity:1;"
offset="1"
id="stop2847" />
</linearGradient>
<linearGradient
id="linearGradient2835">
<stop
style="stop-color:#ccf2a6;stop-opacity:1;"
offset="0"
id="stop2837" />
<stop
style="stop-color:#8ae234;stop-opacity:1;"
offset="1"
id="stop2839" />
</linearGradient>
<inkscape:perspective
sodipodi:type="inkscape:persp3d"
inkscape:vp_x="0 : 16 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_z="32 : 16 : 1"
inkscape:persp3d-origin="16 : 10.666667 : 1"
id="perspective3257" />
<inkscape:perspective
id="perspective6979"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<inkscape:perspective
id="perspective7934"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<inkscape:perspective
id="perspective8023"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<inkscape:perspective
id="perspective8057"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<inkscape:perspective
id="perspective8095"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<inkscape:perspective
id="perspective8219"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<inkscape:perspective
id="perspective8279"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<inkscape:perspective
id="perspective3803"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<inkscape:perspective
id="perspective3869"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<inkscape:perspective
id="perspective3929"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<inkscape:perspective
id="perspective3968"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<inkscape:perspective
id="perspective4002"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<inkscape:perspective
id="perspective4032"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<inkscape:perspective
id="perspective4053"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<inkscape:perspective
id="perspective2905"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<inkscape:perspective
id="perspective2979"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<inkscape:perspective
id="perspective2842"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<inkscape:perspective
id="perspective2978"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<inkscape:perspective
id="perspective6803"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<inkscape:perspective
id="perspective3034"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<inkscape:perspective
id="perspective5795"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<inkscape:perspective
id="perspective5850"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<inkscape:perspective
id="perspective5892"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<inkscape:perspective
id="perspective5932"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<inkscape:perspective
id="perspective5981"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<inkscape:perspective
id="perspective6018"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<inkscape:perspective
id="perspective3800"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<inkscape:perspective
id="perspective3494"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<inkscape:perspective
id="perspective3528"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<inkscape:perspective
id="perspective8590"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<inkscape:perspective
id="perspective8612"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<inkscape:perspective
id="perspective3221"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<inkscape:perspective
id="perspective7131"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<inkscape:perspective
id="perspective7196"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<inkscape:perspective
id="perspective7227"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<inkscape:perspective
id="perspective8031"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<inkscape:perspective
id="perspective8138"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<inkscape:perspective
id="perspective8138-2"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<inkscape:perspective
id="perspective8138-4"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<inkscape:perspective
id="perspective8175"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<inkscape:perspective
id="perspective8196"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<inkscape:perspective
id="perspective8196-6"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<inkscape:perspective
id="perspective8225"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<inkscape:perspective
id="perspective8225-2"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<inkscape:perspective
id="perspective8225-4"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<inkscape:perspective
id="perspective8225-0"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<inkscape:perspective
id="perspective8225-40"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<inkscape:perspective
id="perspective8278"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<inkscape:perspective
id="perspective8299"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<inkscape:perspective
id="perspective8320"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<inkscape:perspective
id="perspective14145"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<inkscape:perspective
id="perspective14200"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<inkscape:perspective
id="perspective6861"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient2937"
id="linearGradient2943"
x1="7"
y1="17"
x2="2"
y2="22"
gradientUnits="userSpaceOnUse" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient2937"
id="linearGradient2947"
gradientUnits="userSpaceOnUse"
x1="7"
y1="17"
x2="2"
y2="22"
gradientTransform="matrix(-1,0,0,-1,26,30)" />
<inkscape:perspective
id="perspective4866"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<inkscape:perspective
id="perspective4855"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<inkscape:perspective
id="perspective4880"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<inkscape:perspective
id="perspective4921"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<inkscape:perspective
id="perspective4981"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="29.041667"
inkscape:cx="12"
inkscape:cy="12"
inkscape:current-layer="layer4"
showgrid="true"
inkscape:grid-bbox="true"
inkscape:document-units="px"
borderlayer="false"
inkscape:window-width="1280"
inkscape:window-height="950"
inkscape:window-x="0"
inkscape:window-y="25"
inkscape:window-maximized="1"
showguides="true"
inkscape:guide-bbox="true"
inkscape:snap-bbox="true"
inkscape:snap-object-midpoints="true"
inkscape:snap-nodes="true"
inkscape:snap-to-guides="false">
<inkscape:grid
type="xygrid"
id="grid5700"
empspacing="5"
visible="true"
enabled="true"
snapvisiblegridlinesonly="true"
dotted="true"
originx="2.5px"
originy="2.5px"
spacingx="1px"
spacingy="1px" />
</sodipodi:namedview>
<metadata
id="metadata5697">
<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>layer OGC Web service</dc:title>
<dc:date>2012-04-30</dc:date>
<dc:creator>
<cc:Agent>
<dc:title>Robert Szczepanek</dc:title>
</cc:Agent>
</dc:creator>
<dc:rights>
<cc:Agent>
<dc:title>Robert Szczepanek</dc:title>
</cc:Agent>
</dc:rights>
<dc:subject>
<rdf:Bag>
<rdf:li>layer</rdf:li>
<rdf:li>OGC</rdf:li>
<rdf:li>web service</rdf:li>
</rdf:Bag>
</dc:subject>
<dc:coverage>GIS icons 0.2</dc:coverage>
<cc:license
rdf:resource="http://creativecommons.org/licenses/by-sa/3.0/" />
<dc:description>Generic icon for OGC Web service - OWS
(WMS,WFS,WCS)</dc:description>
</cc:Work>
<cc:License
rdf:about="http://creativecommons.org/licenses/by-sa/3.0/">
<cc:permits
rdf:resource="http://creativecommons.org/ns#Reproduction" />
<cc:permits
rdf:resource="http://creativecommons.org/ns#Distribution" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#Notice" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#Attribution" />
<cc:permits
rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#ShareAlike" />
</cc:License>
</rdf:RDF>
</metadata>
<g
inkscape:groupmode="layer"
id="layer4"
inkscape:label="1"
style="display:inline"
transform="translate(0,-8)">
<path
sodipodi:nodetypes="ccccc"
id="rect4012"
d="m 2.5,13.5 15,0 0,15 -15,0 0,-15 z"
style="fill:#e6e6e6;fill-opacity:1;stroke:#969696;stroke-width:1;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;display:inline;enable-background:new" />
<path
sodipodi:nodetypes="ccc"
id="path4020"
d="m 0.5,18.5 0,12 6,0"
style="fill:none;stroke:#969696;stroke-width:1px;stroke-linecap:square;stroke-linejoin:miter;stroke-opacity:1;display:inline;enable-background:new" />
<g
transform="translate(0,8)"
style="display:inline;enable-background:new"
id="g4906">
<path
style="fill:#82a0b4;fill-opacity:1;fill-rule:evenodd;stroke:#3c5a6e;stroke-width:0.75;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
d="M 14.5,14 C 18.097359,14 21,11.097359 21,7.5 21,3.902641 18.097359,1 14.5,1 10.913157,1 8.017,3.917127 8,7.5 l 6.5,0 0,6.5 z"
id="path3724"
sodipodi:nodetypes="cssccc" />
<path
style="fill:#82a0b4;fill-opacity:1;fill-rule:nonzero;stroke:#3c5a6e;stroke-width:0.75;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
d="m 15,7.5 6,0"
id="path3077" />
<path
style="fill:none;stroke:#3c5a6e;stroke-width:0.75;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
d="m 15,1 c 3,3 3,10 0,13"
id="path3079"
sodipodi:nodetypes="cc" />
<path
sodipodi:nodetypes="cc"
id="path3082"
d="M 14,1 C 12,3 12,7 12,7"
style="fill:none;stroke:#3c5a6e;stroke-width:0.75;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
<path
style="opacity:0.5;fill:#82a0b4;fill-opacity:1;fill-rule:nonzero;stroke:#fcffff;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
d="M 10,6.5 C 10,3.5 13,2 14,2"
id="path2830"
sodipodi:nodetypes="cc" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 709 B

View File

@ -0,0 +1,237 @@
<?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:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="32px"
height="32px"
id="svg5692"
version="1.1"
inkscape:version="0.47 r22583"
sodipodi:docname="layer-vector.svg"
inkscape:export-filename="/media/home1/robert/svn/graphics/trunk/toolbar-icons/32x32/layer-vector.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90">
<title
id="title2829">GIS icon theme 0.2</title>
<defs
id="defs5694">
<inkscape:perspective
sodipodi:type="inkscape:persp3d"
inkscape:vp_x="0 : 16 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_z="32 : 16 : 1"
inkscape:persp3d-origin="16 : 10.666667 : 1"
id="perspective3486" />
<inkscape:perspective
id="perspective3496"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<inkscape:perspective
id="perspective3600"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<inkscape:perspective
id="perspective7871"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<inkscape:perspective
id="perspective8710"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<inkscape:perspective
id="perspective9811"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<inkscape:perspective
id="perspective4762"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="15.9375"
inkscape:cx="16"
inkscape:cy="16"
inkscape:current-layer="layer2"
showgrid="true"
inkscape:grid-bbox="true"
inkscape:document-units="px"
borderlayer="false"
inkscape:window-width="1024"
inkscape:window-height="744"
inkscape:window-x="1280"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:snap-global="true">
<inkscape:grid
type="xygrid"
id="grid5700"
empspacing="5"
visible="true"
enabled="true"
snapvisiblegridlinesonly="true"
dotted="true"
originx="2.5px"
originy="2.5px" />
</sodipodi:namedview>
<metadata
id="metadata5697">
<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>GIS icon theme 0.2</dc:title>
<dc:creator>
<cc:Agent>
<dc:title>Robert Szczepanek</dc:title>
</cc:Agent>
</dc:creator>
<dc:rights>
<cc:Agent>
<dc:title>Robert Szczepanek</dc:title>
</cc:Agent>
</dc:rights>
<dc:subject>
<rdf:Bag>
<rdf:li>GIS icons</rdf:li>
</rdf:Bag>
</dc:subject>
<dc:coverage>GIS icons</dc:coverage>
<dc:description>http://robert.szczepanek.pl/</dc:description>
<cc:license
rdf:resource="http://creativecommons.org/licenses/by-sa/3.0/" />
</cc:Work>
<cc:License
rdf:about="http://creativecommons.org/licenses/by-sa/3.0/">
<cc:permits
rdf:resource="http://creativecommons.org/ns#Reproduction" />
<cc:permits
rdf:resource="http://creativecommons.org/ns#Distribution" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#Notice" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#Attribution" />
<cc:permits
rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#ShareAlike" />
</cc:License>
</rdf:RDF>
</metadata>
<g
inkscape:groupmode="layer"
id="layer2"
inkscape:label="Layer"
style="display:inline">
<path
sodipodi:nodetypes="ccccc"
id="rect4012"
d="m 4.5,10.5 17,0 0,17 -17,0 0,-17 z"
style="fill:#eeeeec;fill-opacity:1;stroke:#888a85;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;display:inline;enable-background:new" />
<path
sodipodi:nodetypes="ccc"
id="path4020"
d="m 2.5,17.5 0,12 6,0"
style="fill:none;stroke:#888a85;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1;display:inline;enable-background:new" />
<g
id="g4247">
<path
sodipodi:nodetypes="ccccccc"
id="path3756"
d="m 27.5,7.5 -9,16 -9,-16 0,-5 9,10 9,-10 0,5 z"
style="fill:#c8e6fa;fill-rule:evenodd;stroke:#204a87;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline;enable-background:new;opacity:0.8" />
<path
d="m 4,20 a 1,1 0 1 1 -2,0 1,1 0 1 1 2,0 z"
sodipodi:ry="1"
sodipodi:rx="1"
sodipodi:cy="20"
sodipodi:cx="3"
id="path3761"
style="fill:#c8e6fa;fill-opacity:1;fill-rule:nonzero;stroke:#204a87;stroke-width:0.75000000000000000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
sodipodi:type="arc"
transform="translate(15.5,-7.5)" />
<path
transform="translate(6.5,-17.5)"
sodipodi:type="arc"
style="fill:#c8e6fa;fill-opacity:1;fill-rule:nonzero;stroke:#204a87;stroke-width:0.75;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
id="path3763"
sodipodi:cx="3"
sodipodi:cy="20"
sodipodi:rx="1"
sodipodi:ry="1"
d="m 4,20 a 1,1 0 1 1 -2,0 1,1 0 1 1 2,0 z" />
<path
d="m 4,20 a 1,1 0 1 1 -2,0 1,1 0 1 1 2,0 z"
sodipodi:ry="1"
sodipodi:rx="1"
sodipodi:cy="20"
sodipodi:cx="3"
id="path3765"
style="fill:#c8e6fa;fill-opacity:1;fill-rule:nonzero;stroke:#204a87;stroke-width:0.75;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
sodipodi:type="arc"
transform="translate(24.5,-17.5)" />
<path
transform="translate(15.5,3.5)"
sodipodi:type="arc"
style="fill:#c8e6fa;fill-opacity:1;fill-rule:nonzero;stroke:#204a87;stroke-width:0.75;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
id="path3767"
sodipodi:cx="3"
sodipodi:cy="20"
sodipodi:rx="1"
sodipodi:ry="1"
d="m 4,20 a 1,1 0 1 1 -2,0 1,1 0 1 1 2,0 z" />
<path
transform="translate(6.5,-12.5)"
sodipodi:type="arc"
style="fill:#c8e6fa;fill-opacity:1;fill-rule:nonzero;stroke:#204a87;stroke-width:0.75;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
id="path4593"
sodipodi:cx="3"
sodipodi:cy="20"
sodipodi:rx="1"
sodipodi:ry="1"
d="m 4,20 a 1,1 0 1 1 -2,0 1,1 0 1 1 2,0 z" />
<path
d="m 4,20 a 1,1 0 1 1 -2,0 1,1 0 1 1 2,0 z"
sodipodi:ry="1"
sodipodi:rx="1"
sodipodi:cy="20"
sodipodi:cx="3"
id="path4595"
style="fill:#c8e6fa;fill-opacity:1;fill-rule:nonzero;stroke:#204a87;stroke-width:0.75;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
sodipodi:type="arc"
transform="translate(24.5,-12.5)" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 9.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 992 B

View File

@ -891,6 +891,7 @@ void QgisApp::createActions()
connect( mActionAddSpatiaLiteLayer, SIGNAL( triggered() ), this, SLOT( addSpatiaLiteLayer() ) );
connect( mActionAddMssqlLayer, SIGNAL( triggered() ), this, SLOT( addMssqlLayer() ) );
connect( mActionAddWmsLayer, SIGNAL( triggered() ), this, SLOT( addWmsLayer() ) );
connect( mActionAddWcsLayer, SIGNAL( triggered() ), this, SLOT( addWcsLayer() ) );
connect( mActionAddWfsLayer, SIGNAL( triggered() ), this, SLOT( addWfsLayer() ) );
connect( mActionOpenTable, SIGNAL( triggered() ), this, SLOT( attributeTable() ) );
connect( mActionToggleEditing, SIGNAL( triggered() ), this, SLOT( toggleEditing() ) );
@ -1595,6 +1596,7 @@ void QgisApp::setTheme( QString theThemeName )
mActionNewBookmark->setIcon( getThemeIcon( "/mActionNewBookmark.png" ) );
mActionCustomProjection->setIcon( getThemeIcon( "/mActionCustomProjection.png" ) );
mActionAddWmsLayer->setIcon( getThemeIcon( "/mActionAddWmsLayer.png" ) );
mActionAddWcsLayer->setIcon( getThemeIcon( "/mActionAddWcsLayer.png" ) );
mActionAddWfsLayer->setIcon( getThemeIcon( "/mActionAddWfsLayer.png" ) );
mActionAddToOverview->setIcon( getThemeIcon( "/mActionInOverview.png" ) );
mActionAnnotation->setIcon( getThemeIcon( "/mActionAnnotation.png" ) );
@ -2638,6 +2640,27 @@ void QgisApp::addWmsLayer()
delete wmss;
}
void QgisApp::addWcsLayer()
{
if ( mMapCanvas && mMapCanvas->isDrawing() )
{
return;
}
QgsDebugMsg( "about to addWcsLayer" );
// TODO: QDialog for now, switch to QWidget in future
QDialog *wcss = dynamic_cast<QDialog*>( QgsProviderRegistry::instance()->selectWidget( QString( "gdal" ), this ) );
if ( !wcss )
{
QMessageBox::warning( this, tr( "WCS" ), tr( "Cannot get WCS select dialog from provider." ) );
return;
}
connect( wcss , SIGNAL( addRasterLayer( QString const &, QString const &, QString const & ) ),
this , SLOT( addRasterLayer( QString const &, QString const &, QString const & ) ) );
wcss->exec();
delete wcss;
}
void QgisApp::addWfsLayer()
{
if ( !mMapCanvas )

View File

@ -280,6 +280,7 @@ class QgisApp : public QMainWindow, private Ui::MainWindow
QAction *actionAddPgLayer() { return mActionAddPgLayer; }
QAction *actionAddSpatiaLiteLayer() { return mActionAddSpatiaLiteLayer; };
QAction *actionAddWmsLayer() { return mActionAddWmsLayer; }
QAction *actionAddWcsLayer() { return mActionAddWcsLayer; }
QAction *actionAddWfsLayer() { return mActionAddWfsLayer; }
QAction *actionOpenTable() { return mActionOpenTable; }
QAction *actionToggleEditing() { return mActionToggleEditing; }
@ -771,6 +772,8 @@ class QgisApp : public QMainWindow, private Ui::MainWindow
void fileExit();
//! Add a WMS layer to the map
void addWmsLayer();
//! Add a WCS layer to the map
void addWcsLayer();
//! Add a WFS layer to the map
void addWfsLayer();
//! Set map tool to Zoom out

View File

@ -76,6 +76,7 @@ SET(QGIS_CORE_SRCS
qgsmessagelog.cpp
qgscredentials.cpp
qgsoverlayobject.cpp
qgsowsconnection.cpp
qgspalgeometry.cpp
qgspallabeling.cpp
qgspalobjectpositionmanager.cpp
@ -337,6 +338,7 @@ SET(QGIS_CORE_HDRS
qgsmimedatautils.h
qgscredentials.h
qgsoverlayobjectpositionmanager.h
qgsowsconnection.h
qgspallabeling.h
qgspalobjectpositionmanager.h
qgspluginlayer.h

View File

@ -150,10 +150,16 @@ const QIcon &QgsZipItem::iconZip()
QgsDataItem::QgsDataItem( QgsDataItem::Type type, QgsDataItem* parent, QString name, QString path )
: QObject( parent ), mType( type ), mParent( parent ), mPopulated( false ), mName( name ), mPath( path )
// Do not pass parent to QObject, Qt would delete this when parent is deleted
: QObject(), mType( type ), mParent( parent ), mPopulated( false ), mName( name ), mPath( path )
{
}
QgsDataItem::~QgsDataItem()
{
QgsDebugMsg( "mName = " + mName + " mPath = " + mPath);
}
// TODO: This is copy from QgisApp, bad
// TODO: add some caching mechanism ?
QPixmap QgsDataItem::getThemePixmap( const QString theName )
@ -282,6 +288,26 @@ void QgsDataItem::deleteChildItem( QgsDataItem * child )
emit endRemoveItems();
}
QgsDataItem * QgsDataItem::removeChildItem( QgsDataItem * child )
{
QgsDebugMsg( "mName = " + child->mName );
int i = mChildren.indexOf( child );
Q_ASSERT( i >= 0 );
emit beginRemoveItems( this, i, i );
mChildren.remove( i );
emit endRemoveItems();
disconnect( child, SIGNAL( beginInsertItems( QgsDataItem*, int, int ) ),
this, SLOT( emitBeginInsertItems( QgsDataItem*, int, int ) ) );
disconnect( child, SIGNAL( endInsertItems() ),
this, SLOT( emitEndInsertItems() ) );
disconnect( child, SIGNAL( beginRemoveItems( QgsDataItem*, int, int ) ),
this, SLOT( emitBeginRemoveItems( QgsDataItem*, int, int ) ) );
disconnect( child, SIGNAL( endRemoveItems() ),
this, SLOT( emitEndRemoveItems() ) );
child->setParent(0);
return child;
}
int QgsDataItem::findItem( QVector<QgsDataItem*> items, QgsDataItem * item )
{
for ( int i = 0; i < items.size(); i++ )
@ -388,8 +414,12 @@ QgsDataCollectionItem::QgsDataCollectionItem( QgsDataItem* parent, QString name,
QgsDataCollectionItem::~QgsDataCollectionItem()
{
QgsDebugMsg( "Entered");
foreach( QgsDataItem* i, mChildren )
delete i;
{
QgsDebugMsg( QString("delete child = 0x%0").arg((qlonglong)i,8,16,QLatin1Char('0')) );
delete i;
}
}
//-----------------------------------------------------------------------

View File

@ -51,7 +51,7 @@ class CORE_EXPORT QgsDataItem : public QObject
};
QgsDataItem( QgsDataItem::Type type, QgsDataItem* parent, QString name, QString path );
virtual ~QgsDataItem() {}
virtual ~QgsDataItem();
bool hasChildren();
@ -74,6 +74,10 @@ class CORE_EXPORT QgsDataItem : public QObject
// remove and delete child item, signals to browser are emited
virtual void deleteChildItem( QgsDataItem * child );
// remove child item but don't delete it, signals to browser are emited
// returns pointer to the removed item or null if no such item was found
virtual QgsDataItem * removeChildItem( QgsDataItem * child );
virtual bool equal( const QgsDataItem *other );
virtual QWidget * paramWidget() { return 0; }
@ -112,6 +116,7 @@ class CORE_EXPORT QgsDataItem : public QObject
Type type() const { return mType; }
QgsDataItem* parent() const { return mParent; }
void setParent( QgsDataItem* parent ) { mParent = parent; }
QVector<QgsDataItem*> children() const { return mChildren; }
QIcon icon() const { return mIcon; }
QString name() const { return mName; }

View File

@ -0,0 +1,181 @@
/***************************************************************************
qgsowsconnection.cpp - selector for WMS servers, etc.
-------------------
begin : 3 April 2005
copyright :
original : (C) 2005 by Brendan Morley email : morb at ozemail dot com dot au
wms search : (C) 2009 Mathias Walker <mwa at sourcepole.ch>, Sourcepole AG
wms-c support : (C) 2010 Juergen E. Fischer < jef at norbit dot de >, norBIT GmbH
generalized : (C) 2012 Radim Blazek, based on qgswmsconnection.cpp
***************************************************************************/
/***************************************************************************
* *
* 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 "../providers/wms/qgswmsprovider.h"
#include "qgis.h" // GEO_EPSG_CRS_ID
//#include "qgisapp.h" //for getThemeIcon
//#include "qgscontexthelp.h"
//#include "qgscoordinatereferencesystem.h"
#include "qgsdatasourceuri.h"
//#include "qgsgenericprojectionselector.h"
#include "qgslogger.h"
//#include "qgsmanageconnectionsdialog.h"
//#include "qgsmessageviewer.h"
//#include "qgsnewhttpconnection.h"
//#include "qgsnumericsortlistviewitem.h"
#include "qgsproject.h"
#include "qgsproviderregistry.h"
#include "qgsowsconnection.h"
//#include "qgsnetworkaccessmanager.h"
//#include <QButtonGroup>
//#include <QFileDialog>
//#include <QRadioButton>
//#include <QDomDocument>
//#include <QHeaderView>
//#include <QImageReader>
#include <QInputDialog>
//#include <QMap>
#include <QMessageBox>
#include <QPicture>
#include <QSettings>
#include <QUrl>
#include <QNetworkRequest>
#include <QNetworkReply>
QgsOWSConnection::QgsOWSConnection( const QString & theService, const QString & theConnName ) :
mConnName( theConnName ),
mService( theService )
{
QgsDebugMsg( "theConnName = " + theConnName );
QSettings settings;
// WMS (providers/wfs/qgswmsconnection.cpp):
//QString key = "/Qgis/connections-wms/" + mConnName;
//QString credentialsKey = "/Qgis/WMS/" + mConnName;
// WFS (providers/wfs/qgswfsconnection.cpp):
//QString key = "/Qgis/connections-wfs/" + mConnName + "/url";
// WCS - there was no WCS before
QString key = "/Qgis/connections-" + mService.toLower() + "/" + mConnName;
QString credentialsKey = "/Qgis/" + mService + "/" + mConnName;
QStringList connStringParts;
mConnectionInfo = settings.value( key + "/url" ).toString();
mUri.setParam( "url", settings.value( key + "/url" ).toString() );
// Check for credentials and prepend to the connection info
QString username = settings.value( credentialsKey + "/username" ).toString();
QString password = settings.value( credentialsKey + "/password" ).toString();
if ( !username.isEmpty() )
{
// check for a password, if none prompt to get it
if ( password.isEmpty() )
{
//password = QInputDialog::getText( this, tr( "WMS Password for %1" ).arg( theConnName ), "Password", QLineEdit::Password );
password = QInputDialog::getText( 0, tr( "WMS Password for %1" ).arg( mConnName ), "Password", QLineEdit::Password );
}
mConnectionInfo = "username=" + username + ",password=" + password + ",url=" + mConnectionInfo;
mUri.setParam( "username", username );
mUri.setParam( "password", password );
}
bool ignoreGetMap = settings.value( key + "/ignoreGetMapURI", false ).toBool();
bool ignoreGetFeatureInfo = settings.value( key + "/ignoreGetFeatureInfoURI", false ).toBool();
bool ignoreAxisOrientation = settings.value( key + "/ignoreAxisOrientation", false ).toBool();
bool invertAxisOrientation = settings.value( key + "/invertAxisOrientation", false ).toBool();
if ( ignoreGetMap )
{
mUri.setParam( "IgnoreGetMapUrl", "1" );
}
if ( ignoreGetFeatureInfo )
{
mUri.setParam( "IgnoreGetFeatureInfoUrl", "1" );
}
if ( ignoreAxisOrientation )
{
mUri.setParam( "IgnoreAxisOrientation", "1" );
}
if ( invertAxisOrientation )
{
mUri.setParam( "InvertAxisOrientation", "1" );
}
QgsDebugMsg( QString( "Connection info: '%1'." ).arg( mConnectionInfo ) );
}
QgsOWSConnection::~QgsOWSConnection()
{
}
QString QgsOWSConnection::connectionInfo( )
{
return mConnectionInfo;
}
QgsDataSourceURI QgsOWSConnection::uri()
{
return mUri;
}
/*
QgsDataProvider * QgsOWSConnection::provider( )
{
// TODO: remove completely from this class?
// load the server data provider plugin
QgsProviderRegistry * pReg = QgsProviderRegistry::instance();
//QMap<QString,QString> keys;
QgsDataProvider *provider =
( QgsDataProvider* ) pReg->provider( "wms", mUri.encodedUri() );
return provider;
}
*/
QStringList QgsOWSConnection::connectionList( const QString & theService )
{
QSettings settings;
//settings.beginGroup( "/Qgis/connections-wms" );
settings.beginGroup( "/Qgis/connections-" + theService.toLower() );
return settings.childGroups();
}
QString QgsOWSConnection::selectedConnection( const QString & theService )
{
QSettings settings;
//return settings.value( "/Qgis/connections-wms/selected" ).toString();
return settings.value( "/Qgis/connections-" + theService.toLower() + "/selected" ).toString();
}
void QgsOWSConnection::setSelectedConnection( const QString & theService, const QString & name )
{
QSettings settings;
//settings.setValue( "/Qgis/connections-wms/selected", name );
settings.setValue( "/Qgis/connections-" + theService.toLower() + "/selected", name );
}
void QgsOWSConnection::deleteConnection( const QString & theService, const QString & name )
{
QSettings settings;
//settings.remove( "/Qgis/connections-wms/" + name );
//settings.remove( "/Qgis/WMS/" + name );
settings.remove( "/Qgis/connections-" + theService.toLower() + "/" + name );
settings.remove( "/Qgis/" + theService + "/" + name );
}

View File

@ -0,0 +1,75 @@
/***************************************************************************
qgsowsconnection.h - OWS connection
-------------------
begin : 3 April 2005
original : (C) 2005 by Brendan Morley email : morb at ozemail dot com dot au
wms search : (C) 2009 Mathias Walker <mwa at sourcepole.ch>, Sourcepole AG
generalized : (C) 2012 Radim Blazek, based on qgswmsconnection.h
***************************************************************************/
/***************************************************************************
* *
* 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 QGSOWSCONNECTION_H
#define QGSOWSCONNECTION_H
#include "qgsdatasourceuri.h"
//#include "qgisgui.h"
//#include "qgscontexthelp.h"
#include <QStringList>
#include <QPushButton>
class QgisApp;
//class QgsDataProvider;
class QgsDataProvider;
/*class QButtonGroup;*/
/*class QgsNumericSortTreeWidgetItem;*/
class QDomDocument;
class QDomElement;
/*!
* \brief Connections management
*/
class QgsOWSConnection : public QObject
{
// Q_OBJECT
public:
/**
* Constructor
* @param theService service name: WMS,WFS,WCS
*/
QgsOWSConnection( const QString & theService, const QString & theConnName );
//! Destructor
~QgsOWSConnection();
static QStringList connectionList( const QString & theService );
static void deleteConnection( const QString & theService, const QString & name );
static QString selectedConnection( const QString & theService );
static void setSelectedConnection( const QString & theService, const QString & name );
public:
//QgsDataProvider *provider();
QString connectionInfo();
QString mConnName;
QString mConnectionInfo;
QgsDataSourceURI uri();
private:
QgsDataSourceURI mUri;
QString mService;
};
#endif // QGSOWSCONNECTION_H

View File

@ -2312,6 +2312,10 @@ void QgsRasterLayer::setDataProvider( QString const & provider )
{
return;
}
if ( !mDataProvider->isValid() )
{
return;
}
if ( provider == "gdal" )
{

View File

@ -70,6 +70,7 @@ qgsnewhttpconnection.cpp
qgsnewvectorlayerdialog.cpp
qgsnumericsortlistviewitem.cpp
qgscredentialdialog.cpp
qgsowssourceselect.cpp
qgsprojectbadlayerguihandler.cpp
qgsprojectionselector.cpp
qgsquickprint.cpp
@ -147,6 +148,7 @@ qgsmessagelogviewer.h
qgsnewhttpconnection.h
qgsnewvectorlayerdialog.h
qgscredentialdialog.h
qgsowssourceselect.h
qgsprojectionselector.h
qgsquickprint.h
qgsludialog.h
@ -182,6 +184,7 @@ qgsmaptoolpan.h
qgsmaptoolzoom.h
qgsmessageviewer.h
qgscredentialdialog.h
qgsowssourceselect.h
qgsprojectionselector.h
qgsrubberband.h
qgsvertexmarker.h
@ -214,6 +217,7 @@ ${CMAKE_CURRENT_BINARY_DIR}/../ui/ui_qgsdetaileditemwidgetbase.h
${CMAKE_CURRENT_BINARY_DIR}/../ui/ui_qgsgenericprojectionselectorbase.h
${CMAKE_CURRENT_BINARY_DIR}/../ui/ui_qgsmessageviewer.h
${CMAKE_CURRENT_BINARY_DIR}/../ui/ui_qgsmessagelogviewer.h
${CMAKE_CURRENT_BINARY_DIR}/../ui/ui_qgsowssourceselectbase.h
${CMAKE_CURRENT_BINARY_DIR}/../ui/ui_qgscredentialdialog.h
${CMAKE_CURRENT_BINARY_DIR}/../ui/ui_qgsprojectionselectorbase.h
${CMAKE_CURRENT_BINARY_DIR}/../ui/ui_qgsquerybuilderbase.h

View File

@ -100,7 +100,7 @@ void QgsManageConnectionsDialog::doExportImport()
switch ( mConnectionType )
{
case WMS:
doc = saveWMSConnections( items );
doc = saveOWSConnections( items, "WMS" );
break;
case WFS:
doc = saveWFSConnections( items );
@ -111,6 +111,9 @@ void QgsManageConnectionsDialog::doExportImport()
case MSSQL:
doc = saveMssqlConnections( items );
break;
case WCS:
doc = saveOWSConnections( items, "WCS" );
break;
}
QFile file( mFileName );
@ -156,7 +159,7 @@ void QgsManageConnectionsDialog::doExportImport()
switch ( mConnectionType )
{
case WMS:
loadWMSConnections( doc, items );
loadOWSConnections( doc, items, "WMS" );
break;
case WFS:
loadWFSConnections( doc, items );
@ -167,6 +170,9 @@ void QgsManageConnectionsDialog::doExportImport()
case MSSQL:
loadMssqlConnections( doc, items );
break;
case WCS:
loadOWSConnections( doc, items, "WCS" );
break;
}
// clear connections list and close window
listConnections->clear();
@ -190,6 +196,9 @@ bool QgsManageConnectionsDialog::populateConnections()
case WFS:
settings.beginGroup( "/Qgis/connections-wfs" );
break;
case WCS:
settings.beginGroup( "/Qgis/connections-wcs" );
break;
case PostGIS:
settings.beginGroup( "/PostgreSQL/connections" );
break;
@ -257,6 +266,15 @@ bool QgsManageConnectionsDialog::populateConnections()
}
break;
case WCS:
if ( root.tagName() != "qgsWCSConnections" )
{
QMessageBox::information( this, tr( "Loading connections" ),
tr( "The file is not an WCS connections exchange file." ) );
return false;
}
break;
case PostGIS:
if ( root.tagName() != "qgsPgConnections" )
{
@ -288,10 +306,10 @@ bool QgsManageConnectionsDialog::populateConnections()
return true;
}
QDomDocument QgsManageConnectionsDialog::saveWMSConnections( const QStringList &connections )
QDomDocument QgsManageConnectionsDialog::saveOWSConnections( const QStringList &connections, const QString & service )
{
QDomDocument doc( "connections" );
QDomElement root = doc.createElement( "qgsWMSConnections" );
QDomElement root = doc.createElement( "qgs" + service.toUpper() + "Connections" );
root.setAttribute( "version", "1.0" );
doc.appendChild( root );
@ -299,16 +317,20 @@ QDomDocument QgsManageConnectionsDialog::saveWMSConnections( const QStringList &
QString path;
for ( int i = 0; i < connections.count(); ++i )
{
path = "/Qgis/connections-wms/";
QDomElement el = doc.createElement( "wms" );
path = "/Qgis/connections-" + service.toLower() + "/";
QDomElement el = doc.createElement( service.toLower() );
el.setAttribute( "name", connections[ i ] );
el.setAttribute( "url", settings.value( path + connections[ i ] + "/url", "" ).toString() );
el.setAttribute( "ignoreGetMapURI", settings.value( path + connections[i] + "/ignoreGetMapURI", false ).toBool() ? "true" : "false" );
el.setAttribute( "ignoreGetFeatureInfoURI", settings.value( path + connections[i] + "/ignoreGetFeatureInfoURI", false ).toBool() ? "true" : "false" );
el.setAttribute( "ignoreAxisOrientation", settings.value( path + connections[i] + "/ignoreAxisOrientation", false ).toBool() ? "true" : "false" );
el.setAttribute( "invertAxisOrientation", settings.value( path + connections[i] + "/invertAxisOrientation", false ).toBool() ? "true" : "false" );
path = "/Qgis/WMS/";
if ( service == "WMS" )
{
el.setAttribute( "ignoreGetMapURI", settings.value( path + connections[i] + "/ignoreGetMapURI", false ).toBool() ? "true" : "false" );
el.setAttribute( "ignoreGetFeatureInfoURI", settings.value( path + connections[i] + "/ignoreGetFeatureInfoURI", false ).toBool() ? "true" : "false" );
el.setAttribute( "ignoreAxisOrientation", settings.value( path + connections[i] + "/ignoreAxisOrientation", false ).toBool() ? "true" : "false" );
el.setAttribute( "invertAxisOrientation", settings.value( path + connections[i] + "/invertAxisOrientation", false ).toBool() ? "true" : "false" );
}
path = "/Qgis/" + service.toUpper() + "/";
el.setAttribute( "username", settings.value( path + connections[ i ] + "/username", "" ).toString() );
el.setAttribute( "password", settings.value( path + connections[ i ] + "/password", "" ).toString() );
root.appendChild( el );
@ -424,19 +446,19 @@ QDomDocument QgsManageConnectionsDialog::saveMssqlConnections( const QStringList
return doc;
}
void QgsManageConnectionsDialog::loadWMSConnections( const QDomDocument &doc, const QStringList &items )
void QgsManageConnectionsDialog::loadOWSConnections( const QDomDocument &doc, const QStringList &items, const QString &service )
{
QDomElement root = doc.documentElement();
if ( root.tagName() != "qgsWMSConnections" )
if ( root.tagName() != "qgs" + service.toUpper() + "Connections" )
{
QMessageBox::information( this, tr( "Loading connections" ),
tr( "The file is not an WMS connections exchange file." ) );
tr( "The file is not an %1 connections exchange file." ).arg( service ) );
return;
}
QString connectionName;
QSettings settings;
settings.beginGroup( "/Qgis/connections-wms" );
settings.beginGroup( "/Qgis/connections-" + service.toLower() );
QStringList keys = settings.childGroups();
settings.endGroup();
QDomElement child = root.firstChildElement();
@ -489,7 +511,7 @@ void QgsManageConnectionsDialog::loadWMSConnections( const QDomDocument &doc, co
}
// no dups detected or overwrite is allowed
settings.beginGroup( "/Qgis/connections-wms" );
settings.beginGroup( "/Qgis/connections-" + service.toLower() );
settings.setValue( QString( "/" + connectionName + "/url" ) , child.attribute( "url" ) );
settings.setValue( QString( "/" + connectionName + "/ignoreGetMapURI" ), child.attribute( "ignoreGetMapURI" ) == "true" );
settings.setValue( QString( "/" + connectionName + "/ignoreGetFeatureInfoURI" ), child.attribute( "ignoreGetFeatureInfoURI" ) == "true" );
@ -499,7 +521,7 @@ void QgsManageConnectionsDialog::loadWMSConnections( const QDomDocument &doc, co
if ( !child.attribute( "username" ).isEmpty() )
{
settings.beginGroup( "/Qgis/WMS/" + connectionName );
settings.beginGroup( "/Qgis/" + service.toUpper() + "/" + connectionName );
settings.setValue( "/username", child.attribute( "username" ) );
settings.setValue( "/password", child.attribute( "password" ) );
settings.endGroup();

View File

@ -39,6 +39,7 @@ class GUI_EXPORT QgsManageConnectionsDialog : public QDialog, private Ui::QgsMan
PostGIS,
WFS,
MSSQL,
WCS
};
// constructor
@ -53,11 +54,11 @@ class GUI_EXPORT QgsManageConnectionsDialog : public QDialog, private Ui::QgsMan
private:
bool populateConnections();
QDomDocument saveWMSConnections( const QStringList &connections );
QDomDocument saveOWSConnections( const QStringList &connections, const QString &service );
QDomDocument saveWFSConnections( const QStringList &connections );
QDomDocument savePgConnections( const QStringList & connections );
QDomDocument saveMssqlConnections( const QStringList & connections );
void loadWMSConnections( const QDomDocument &doc, const QStringList &items );
void loadOWSConnections( const QDomDocument &doc, const QStringList &items, const QString &service );
void loadWFSConnections( const QDomDocument &doc, const QStringList &items );
void loadPgConnections( const QDomDocument &doc, const QStringList &items );
void loadMssqlConnections( const QDomDocument &doc, const QStringList &items );

View File

@ -29,6 +29,9 @@ QgsNewHttpConnection::QgsNewHttpConnection(
{
setupUi( this );
QString service = baseKey.mid( 18, 3 ).toUpper();
setWindowTitle( tr( "Create a new %1 connection" ).arg( service ) );
// It would be obviously much better to use mBaseKey also for credentials,
// but for some strange reason a different hardcoded key was used instead.
// WFS and WMS credentials were mixed with the same key WMS.
@ -66,6 +69,18 @@ QgsNewHttpConnection::QgsNewHttpConnection(
txtUserName->setText( settings.value( credentialsKey + "/username" ).toString() );
txtPassword->setText( settings.value( credentialsKey + "/password" ).toString() );
}
if ( mBaseKey != "/Qgis/connections-wms/" )
{
cbxIgnoreGetMapURI->setVisible( false );
cbxIgnoreGetFeatureInfoURI->setVisible( false );
mGroupBox->layout()->removeWidget( cbxIgnoreGetMapURI );
mGroupBox->layout()->removeWidget( cbxIgnoreGetFeatureInfoURI );
// Adjust height
int w = width();
adjustSize();
resize( w, height() );
}
on_txtName_textChanged( connName );
}

View File

@ -0,0 +1,798 @@
/***************************************************************************
qgsowssourceselect.cpp - selector for WMS,WFS,WCS
-------------------
begin : 3 April 2005
copyright :
original : (C) 2005 by Brendan Morley email : morb at ozemail dot com dot au
wms search : (C) 2009 Mathias Walker <mwa at sourcepole.ch>, Sourcepole AG
wms-c support : (C) 2010 Juergen E. Fischer < jef at norbit dot de >, norBIT GmbH
generalized : (C) 2012 Radim Blazek, based on qgswmssourceselect.cpp
***************************************************************************/
/***************************************************************************
* *
* 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 "qgis.h" // GEO_EPSG_CRS_ID
#include "qgscontexthelp.h"
#include "qgscoordinatereferencesystem.h"
#include "qgsdatasourceuri.h"
#include "qgsgenericprojectionselector.h"
#include "qgslogger.h"
#include "qgsmanageconnectionsdialog.h"
#include "qgsmessageviewer.h"
#include "qgsnewhttpconnection.h"
#include "qgsnumericsortlistviewitem.h"
#include "qgsproject.h"
#include "qgsproviderregistry.h"
#include "qgsowsconnection.h"
#include "qgsdataprovider.h"
#include "qgsowssourceselect.h"
#include "qgsnetworkaccessmanager.h"
#include <QButtonGroup>
#include <QFileDialog>
#include <QRadioButton>
#include <QDomDocument>
#include <QHeaderView>
#include <QImageReader>
#include <QInputDialog>
#include <QMap>
#include <QMessageBox>
#include <QPicture>
#include <QSettings>
#include <QUrl>
#include <QValidator>
#include <QNetworkRequest>
#include <QNetworkReply>
QgsOWSSourceSelect::QgsOWSSourceSelect( QString service, QWidget * parent, Qt::WFlags fl, bool managerMode, bool embeddedMode )
: QDialog( parent, fl )
, mService( service )
, mManagerMode( managerMode )
, mEmbeddedMode( embeddedMode )
, mCurrentTileset( 0 )
{
setupUi( this );
if ( mEmbeddedMode )
{
mDialogButtonBox->button( QDialogButtonBox::Close )->hide();
}
mAddButton = mDialogButtonBox->button( QDialogButtonBox::Apply );
mAddButton->setText( tr( "&Add" ) );
mAddButton->setToolTip( tr( "Add selected layers to map" ) );
mAddButton->setEnabled( false );
mTileWidthLineEdit->setValidator( new QIntValidator( 0, 9999, this ) );
mTileHeightLineEdit->setValidator( new QIntValidator( 0, 9999, this ) );
mFeatureCountLineEdit->setValidator( new QIntValidator( 0, 9999, this ) );
mImageFormatGroup = new QButtonGroup;
if ( !mManagerMode )
{
connect( mAddButton, SIGNAL( clicked() ), this, SLOT( addClicked() ) );
//set the current project CRS if available
long currentCRS = QgsProject::instance()->readNumEntry( "SpatialRefSys", "/ProjectCRSID", -1 );
if ( currentCRS != -1 )
{
//convert CRS id to epsg
QgsCoordinateReferenceSystem currentRefSys( currentCRS, QgsCoordinateReferenceSystem::InternalCrsId );
if ( currentRefSys.isValid() )
{
mSelectedCRS = currentRefSys.authid();
}
}
}
else
{
mTabWidget->removeTab( mTabWidget->indexOf( mLayerOrderTab ) );
mTabWidget->removeTab( mTabWidget->indexOf( mTilesetsTab ) );
mImageFormatsGroupBox->hide();
mLayersTab->layout()->removeWidget( mImageFormatsGroupBox );
mCRSGroupBox->hide();
mLayersTab->layout()->removeWidget( mCRSGroupBox );
mAddButton->hide();
}
// set up the WMS connections we already know about
populateConnectionList();
QSettings settings;
QgsDebugMsg( "restoring geometry" );
restoreGeometry( settings.value( "/Windows/WMSSourceSelect/geometry" ).toByteArray() );
}
QgsOWSSourceSelect::~QgsOWSSourceSelect()
{
QSettings settings;
QgsDebugMsg( "saving geometry" );
settings.setValue( "/Windows/WMSSourceSelect/geometry", saveGeometry() );
}
void QgsOWSSourceSelect::clearFormats()
{
int i = 0;
while ( QRadioButton *btn = dynamic_cast<QRadioButton*>( mImageFormatGroup->button( i++ ) ) )
{
btn->setVisible( false );
}
}
void QgsOWSSourceSelect::populateFormats()
{
QgsDebugMsg( "entered" );
// A server may offer more similar formats, which are mapped
// to the same GDAL format, e.g. GeoTIFF and TIFF
// -> recreate always buttons for all available formats, enable supported
clearFormats();
QHBoxLayout *layout = dynamic_cast<QHBoxLayout*>( mImageFormatsGroupBox->layout() );
if ( !layout )
{
layout = new QHBoxLayout;
mImageFormatsGroupBox->setLayout( layout );
layout->addStretch();
}
if ( mProviderFormats.size() == 0 )
{
mProviderFormats = providerFormats();
for ( int i = 0; i < mProviderFormats.size(); i++ )
{
// GDAL mime types may be image/tiff, image/png, ...
mMimeLabelMap.insert( mProviderFormats[i].format, mProviderFormats[i].label );
}
}
// selectedLayersFormats may come in various forms:
// image/tiff, GTiff, GeoTIFF, TIFF, geotiff_int16, geotiff_rgb,
// PNG, GTOPO30, ARCGRID, IMAGEMOSAIC,
QMap<QString, QString> formatsMap;
formatsMap.insert( "geotiff", "tiff" );
formatsMap.insert( "gtiff", "tiff" );
formatsMap.insert( "tiff", "tiff" );
formatsMap.insert( "tif", "tiff" );
formatsMap.insert( "gif", "gif" );
formatsMap.insert( "jpeg", "jpeg" );
formatsMap.insert( "jpg", "jpeg" );
formatsMap.insert( "png", "png" );
int prefered = -1;
int firstEnabled = -1;
QStringList layersFormats = selectedLayersFormats();
for ( int i = 0; i < layersFormats.size(); i++ )
{
QString format = layersFormats.value( i );
QgsDebugMsg( "server format = " + format );
QString simpleFormat = format.toLower().replace( "image/", "" ).replace( QRegExp( "_.*" ), "" );
QgsDebugMsg( "server simpleFormat = " + simpleFormat );
QString mimeFormat = "image/" + formatsMap.value( simpleFormat );
QgsDebugMsg( "server mimeFormat = " + mimeFormat );
QString label = format;
QString tip = tr( "Server format" ) + " " + format;
QRadioButton *btn;
btn = dynamic_cast<QRadioButton*>( mImageFormatGroup->button( i ) );
if ( !btn )
{
btn = new QRadioButton( label );
mImageFormatGroup->addButton( btn, i );
layout->insertWidget( layout->count() - 1, btn ); // before stretch
}
btn->setVisible( true );
if ( mMimeLabelMap.contains( mimeFormat ) )
{
btn->setEnabled( true );
if ( format != mMimeLabelMap.value( mimeFormat ) )
{
label += " / " + mMimeLabelMap.value( mimeFormat );
}
tip += " " + tr( "is supported by GDAL %1 driver." ).arg( mMimeLabelMap.value( mimeFormat ) );
if ( firstEnabled < 0 ) { firstEnabled = i; }
if ( simpleFormat.contains( "tif" ) ) // prefer *tif*
{
if ( prefered < 0 || simpleFormat.startsWith( "g" ) ) // prefere geotiff
{
prefered = i;
}
}
}
else
{
QgsDebugMsg( QString( "format %1 not supported." ).arg( format ) );
btn->setEnabled( false );
tip += " " + tr( "is not supported by GDAL" );
}
btn->setText( label );
btn->setToolTip( tip );
}
// Set prefered
prefered = prefered >= 0 ? prefered : firstEnabled;
if ( prefered >= 0 )
{
mImageFormatGroup->button( prefered )->setChecked( true );
}
mImageFormatsGroupBox->setEnabled( true );
}
void QgsOWSSourceSelect::populateConnectionList()
{
mConnectionsComboBox->clear();
mConnectionsComboBox->addItems( QgsOWSConnection::connectionList( mService ) );
setConnectionListPosition();
if ( mConnectionsComboBox->count() == 0 )
{
// No connections - disable various buttons
mConnectButton->setEnabled( false );
mEditButton->setEnabled( false );
mDeleteButton->setEnabled( false );
}
else
{
// Connections - enable various buttons
mConnectButton->setEnabled( true );
mEditButton->setEnabled( true );
mDeleteButton->setEnabled( true );
}
}
void QgsOWSSourceSelect::on_mNewButton_clicked()
{
QgsNewHttpConnection *nc = new QgsNewHttpConnection( this, "/Qgis/connections-" + mService.toLower() + "/" );
if ( nc->exec() )
{
populateConnectionList();
emit connectionsChanged();
}
delete nc;
}
void QgsOWSSourceSelect::on_mEditButton_clicked()
{
QgsNewHttpConnection *nc = new QgsNewHttpConnection( this, "/Qgis/connections-" + mService.toLower() + "/", mConnectionsComboBox->currentText() );
if ( nc->exec() )
{
populateConnectionList();
emit connectionsChanged();
}
delete nc;
}
void QgsOWSSourceSelect::on_mDeleteButton_clicked()
{
QString msg = tr( "Are you sure you want to remove the %1 connection and all associated settings?" )
.arg( mConnectionsComboBox->currentText() );
QMessageBox::StandardButton result = QMessageBox::information( this, tr( "Confirm Delete" ), msg, QMessageBox::Ok | QMessageBox::Cancel );
if ( result == QMessageBox::Ok )
{
QgsOWSConnection::deleteConnection( mService, mConnectionsComboBox->currentText() );
mConnectionsComboBox->removeItem( mConnectionsComboBox->currentIndex() ); // populateConnectionList();
setConnectionListPosition();
emit connectionsChanged();
}
}
void QgsOWSSourceSelect::on_mSaveButton_clicked()
{
QgsManageConnectionsDialog dlg( this, QgsManageConnectionsDialog::Export, QgsManageConnectionsDialog::WCS );
dlg.exec();
}
void QgsOWSSourceSelect::on_mLoadButton_clicked()
{
QString fileName = QFileDialog::getOpenFileName( this, tr( "Load connections" ), ".",
tr( "XML files (*.xml *XML)" ) );
if ( fileName.isEmpty() )
{
return;
}
QgsManageConnectionsDialog dlg( this, QgsManageConnectionsDialog::Import, QgsManageConnectionsDialog::WCS, fileName );
dlg.exec();
populateConnectionList();
emit connectionsChanged();
}
QgsNumericSortTreeWidgetItem *QgsOWSSourceSelect::createItem(
int id,
const QStringList &names,
QMap<int, QgsNumericSortTreeWidgetItem *> &items,
int &layerAndStyleCount,
const QMap<int, int> &layerParents,
const QMap<int, QStringList> &layerParentNames )
{
QgsDebugMsg( QString( "id = %1 layerAndStyleCount = %2 names = %3 " ).arg( id ).arg( layerAndStyleCount ).arg( names.join( "," ) ) );
if ( items.contains( id ) )
return items[id];
QgsNumericSortTreeWidgetItem *item;
if ( layerParents.contains( id ) )
{
// it has parent -> create first its parent
int parent = layerParents[ id ];
item = new QgsNumericSortTreeWidgetItem( createItem( parent, layerParentNames[ parent ], items, layerAndStyleCount, layerParents, layerParentNames ) );
}
else
item = new QgsNumericSortTreeWidgetItem( mLayersTreeWidget );
item->setText( 0, QString::number( ++layerAndStyleCount ) );
item->setText( 1, names[0].simplified() );
item->setText( 2, names[1].simplified() );
item->setText( 3, names[2].simplified() );
item->setToolTip( 3, "<font color=black>" + names[2].simplified() + "</font>" );
items[ id ] = item;
return item;
}
void QgsOWSSourceSelect::populateLayerList( )
{
}
void QgsOWSSourceSelect::on_mConnectButton_clicked()
{
QgsDebugMsg( "entered" );
mLayersTreeWidget->clear();
clearFormats();
mConnName = mConnectionsComboBox->currentText();
QgsOWSConnection connection( mService, mConnectionsComboBox->currentText() );
//QgsDataProvider *theProvider = connection.provider( );
mConnectionInfo = connection.connectionInfo();
mUri = connection.uri();
QApplication::setOverrideCursor( Qt::WaitCursor );
QgsDebugMsg( "call populateLayerList" );
populateLayerList();
QApplication::restoreOverrideCursor();
}
void QgsOWSSourceSelect::addClicked()
{
QgsDebugMsg( "entered" );
}
void QgsOWSSourceSelect::enableLayersForCrs( QTreeWidgetItem *item )
{
}
void QgsOWSSourceSelect::on_mChangeCRSButton_clicked()
{
QStringList layers;
foreach( QTreeWidgetItem *item, mLayersTreeWidget->selectedItems() )
{
QString layer = item->data( 0, Qt::UserRole + 0 ).toString();
if ( !layer.isEmpty() )
layers << layer;
}
QgsGenericProjectionSelector * mySelector = new QgsGenericProjectionSelector( this );
mySelector->setMessage();
mySelector->setOgcWmsCrsFilter( mSelectedLayersCRSs );
QString myDefaultCrs = QgsProject::instance()->readEntry( "SpatialRefSys", "/ProjectCrs", GEO_EPSG_CRS_AUTHID );
QgsCoordinateReferenceSystem defaultCRS;
if ( defaultCRS.createFromOgcWmsCrs( myDefaultCrs ) )
{
mySelector->setSelectedCrsId( defaultCRS.srsid() );
}
if ( !mySelector->exec() )
return;
mSelectedCRS = mySelector->selectedAuthId();
delete mySelector;
mSelectedCRSLabel->setText( descriptionForAuthId( mSelectedCRS ) );
for ( int i = 0; i < mLayersTreeWidget->topLevelItemCount(); i++ )
{
enableLayersForCrs( mLayersTreeWidget->topLevelItem( i ) );
}
updateButtons();
}
void QgsOWSSourceSelect::on_mLayersTreeWidget_itemSelectionChanged()
{
}
void QgsOWSSourceSelect::populateCRS()
{
mSelectedLayersCRSs = selectedLayersCRSs().toSet();
mCRSGroupBox->setTitle( tr( "Coordinate Reference System (%n available)", "crs count", mSelectedLayersCRSs.count() ) );
mChangeCRSButton->setDisabled( mSelectedLayersCRSs.isEmpty() );
if ( !mSelectedLayersCRSs.isEmpty() )
{
// check whether current CRS is supported
// if not, use one of the available CRS
QString defaultCRS;
QSet<QString>::const_iterator it = mSelectedLayersCRSs.begin();
for ( ; it != mSelectedLayersCRSs.end(); it++ )
{
if ( it->compare( mSelectedCRS, Qt::CaseInsensitive ) == 0 )
break;
// save first CRS in case the current CRS is not available
if ( it == mSelectedLayersCRSs.begin() )
defaultCRS = *it;
// prefer value of DEFAULT_GEO_EPSG_CRS_ID if available
if ( *it == GEO_EPSG_CRS_AUTHID )
defaultCRS = *it;
}
if ( it == mSelectedLayersCRSs.end() )
{
// not found
mSelectedCRS = defaultCRS;
}
mSelectedCRSLabel->setText( descriptionForAuthId( mSelectedCRS ) );
}
else
{
mSelectedCRS = "";
mSelectedCRSLabel->setText( "" );
}
mChangeCRSButton->setEnabled( !mSelectedLayersCRSs.isEmpty() );
}
void QgsOWSSourceSelect::on_mTilesetsTableWidget_itemClicked( QTableWidgetItem *item )
{
Q_UNUSED( item );
QTableWidgetItem *rowItem = mTilesetsTableWidget->item( mTilesetsTableWidget->currentRow(), 0 );
bool wasSelected = mCurrentTileset == rowItem;
mTilesetsTableWidget->blockSignals( true );
mTilesetsTableWidget->clearSelection();
if ( !wasSelected )
{
QgsDebugMsg( QString( "selecting current row %1" ).arg( mTilesetsTableWidget->currentRow() ) );
mTilesetsTableWidget->selectRow( mTilesetsTableWidget->currentRow() );
mCurrentTileset = rowItem;
}
else
{
mCurrentTileset = 0;
}
mTilesetsTableWidget->blockSignals( false );
updateButtons();
}
QString QgsOWSSourceSelect::connName()
{
return mConnName;
}
QString QgsOWSSourceSelect::connectionInfo()
{
return mConnectionInfo;
}
QString QgsOWSSourceSelect::selectedFormat()
{
// TODO: Match this hard coded list to the list of formats Qt reports it can actually handle.
int id = mImageFormatGroup->checkedId();
if ( id < 0 )
{
return "";
}
else
{
// TODO: do format in subclass (WMS)
//return QUrl::toPercentEncoding( mProviderFormats[ id ].format );
return selectedLayersFormats().value( id );
}
}
QString QgsOWSSourceSelect::selectedCRS()
{
return mSelectedCRS;
}
void QgsOWSSourceSelect::setConnectionListPosition()
{
QString toSelect = QgsOWSConnection::selectedConnection( mService );
mConnectionsComboBox->setCurrentIndex( mConnectionsComboBox->findText( toSelect ) );
if ( mConnectionsComboBox->currentIndex() < 0 )
{
if ( toSelect.isNull() )
mConnectionsComboBox->setCurrentIndex( 0 );
else
mConnectionsComboBox->setCurrentIndex( mConnectionsComboBox->count() - 1 );
}
QgsOWSConnection::setSelectedConnection( mService, mConnectionsComboBox->currentText() );
}
void QgsOWSSourceSelect::showStatusMessage( QString const &theMessage )
{
mStatusLabel->setText( theMessage );
// update the display of this widget
update();
}
void QgsOWSSourceSelect::showError( QString const &theTitle, QString const &theFormat, QString const &theError )
{
QgsMessageViewer * mv = new QgsMessageViewer( this );
mv->setWindowTitle( theTitle );
if ( theFormat == "text/html" )
{
mv->setMessageAsHtml( theError );
}
else
{
mv->setMessageAsPlainText( tr( "Could not understand the response:\n%1" ).arg( theError ) );
}
mv->showMessage( true ); // Is deleted when closed
}
void QgsOWSSourceSelect::on_mConnectionsComboBox_activated( int )
{
// Remember which server was selected.
QgsOWSConnection::setSelectedConnection( mService, mConnectionsComboBox->currentText() );
}
void QgsOWSSourceSelect::on_mAddDefaultButton_clicked()
{
addDefaultServers();
}
QString QgsOWSSourceSelect::descriptionForAuthId( QString authId )
{
if ( mCrsNames.contains( authId ) )
return mCrsNames[ authId ];
QgsCoordinateReferenceSystem qgisSrs;
qgisSrs.createFromOgcWmsCrs( authId );
mCrsNames.insert( authId, qgisSrs.description() );
return qgisSrs.description();
}
void QgsOWSSourceSelect::addDefaultServers()
{
QMap<QString, QString> exampleServers;
exampleServers["DM Solutions GMap"] = "http://www2.dmsolutions.ca/cgi-bin/mswms_gmap";
exampleServers["Lizardtech server"] = "http://wms.lizardtech.com/lizardtech/iserv/ows";
// Nice to have the qgis users map, but I'm not sure of the URL at the moment.
// exampleServers["Qgis users map"] = "http://qgis.org/wms.cgi";
QSettings settings;
settings.beginGroup( "/Qgis/connections-" + mService.toLower() );
QMap<QString, QString>::const_iterator i = exampleServers.constBegin();
for ( ; i != exampleServers.constEnd(); ++i )
{
// Only do a server if it's name doesn't already exist.
QStringList keys = settings.childGroups();
if ( !keys.contains( i.key() ) )
{
QString path = i.key();
settings.setValue( path + "/url", i.value() );
}
}
settings.endGroup();
populateConnectionList();
QMessageBox::information( this, tr( "WMS proxies" ), "<p>" + tr( "Several WMS servers have "
"been added to the server list. Note that if "
"you access the internet via a web proxy, you will "
"need to set the proxy settings in the QGIS options dialog." ) + "</p>" );
}
void QgsOWSSourceSelect::addWMSListRow( const QDomElement& item, int row )
{
QDomElement title = item.firstChildElement( "title" );
addWMSListItem( title, row, 0 );
QDomElement description = item.firstChildElement( "description" );
addWMSListItem( description, row, 1 );
QDomElement link = item.firstChildElement( "link" );
addWMSListItem( link, row, 2 );
}
void QgsOWSSourceSelect::addWMSListItem( const QDomElement& el, int row, int column )
{
if ( !el.isNull() )
{
QTableWidgetItem* tableItem = new QTableWidgetItem( el.text() );
// TODO: add linebreaks to long tooltips?
tableItem->setToolTip( el.text() );
mSearchTableWidget->setItem( row, column, tableItem );
}
}
void QgsOWSSourceSelect::on_mSearchButton_clicked()
{
// clear results
mSearchTableWidget->clearContents();
mSearchTableWidget->setRowCount( 0 );
// disable Add WMS button
mSearchAddButton->setEnabled( false );
QApplication::setOverrideCursor( Qt::WaitCursor );
QSettings settings;
// geopole.org (geopole.ch) 25.4.2012 : 503 Service Unavailable, archive: Recently added 20 Jul 2011
QString mySearchUrl = settings.value( "/qgis/WMSSearchUrl", "http://geopole.org/wms/search?search=%1&type=rss" ).toString();
QUrl url( mySearchUrl.arg( mSearchTermLineEdit->text() ) );
QgsDebugMsg( url.toString() );
QNetworkReply *r = QgsNetworkAccessManager::instance()->get( QNetworkRequest( url ) );
connect( r, SIGNAL( finished() ), SLOT( searchFinished() ) );
}
void QgsOWSSourceSelect::searchFinished()
{
QApplication::restoreOverrideCursor();
QNetworkReply *r = qobject_cast<QNetworkReply *>( sender() );
if ( !r )
return;
if ( r->error() == QNetworkReply::NoError )
{
// parse results
QDomDocument doc( "RSS" );
QByteArray res = r->readAll();
QString error;
int line, column;
if ( doc.setContent( res, &error, &line, &column ) )
{
QDomNodeList list = doc.elementsByTagName( "item" );
mSearchTableWidget->setRowCount( list.size() );
for ( int i = 0; i < list.size(); i++ )
{
if ( list.item( i ).isElement() )
{
QDomElement item = list.item( i ).toElement();
addWMSListRow( item, i );
}
}
mSearchTableWidget->resizeColumnsToContents();
}
else
{
QgsDebugMsg( "setContent failed" );
showStatusMessage( tr( "parse error at row %1, column %2: %3" ).arg( line ).arg( column ).arg( error ) );
}
}
else
{
showStatusMessage( tr( "network error: %1" ).arg( r->error() ) );
}
r->deleteLater();
}
void QgsOWSSourceSelect::on_mAddWMSButton_clicked()
{
// TODO: deactivate button if dialog is open?
// TODO: remove from config on close?
int selectedRow = mSearchTableWidget->currentRow();
if ( selectedRow == -1 )
{
return;
}
QString wmsTitle = mSearchTableWidget->item( selectedRow, 0 )->text();
QString wmsUrl = mSearchTableWidget->item( selectedRow, 2 )->text();
QSettings settings;
if ( settings.contains( QString( "Qgis/connections-wms/%1/url" ).arg( wmsTitle ) ) )
{
QString msg = tr( "The %1 connection already exists. Do you want to overwrite it?" ).arg( wmsTitle );
QMessageBox::StandardButton result = QMessageBox::information( this, tr( "Confirm Overwrite" ), msg, QMessageBox::Ok | QMessageBox::Cancel );
if ( result != QMessageBox::Ok )
{
return;
}
}
// add selected WMS to config and mark as current
settings.setValue( QString( "Qgis/connections-wms/%1/url" ).arg( wmsTitle ), wmsUrl );
QgsOWSConnection::setSelectedConnection( mService, wmsTitle );
populateConnectionList();
mTabWidget->setCurrentIndex( 0 );
}
void QgsOWSSourceSelect::on_mSearchTableWidget_itemSelectionChanged()
{
mSearchAddButton->setEnabled( mSearchTableWidget->currentRow() != -1 );
}
void QgsOWSSourceSelect::on_mLayerUpButton_clicked()
{
QList<QTreeWidgetItem *> selectionList = mLayerOrderTreeWidget->selectedItems();
if ( selectionList.size() < 1 )
{
return;
}
int selectedIndex = mLayerOrderTreeWidget->indexOfTopLevelItem( selectionList[0] );
if ( selectedIndex < 1 )
{
return; //item not existing or already on top
}
QTreeWidgetItem* selectedItem = mLayerOrderTreeWidget->takeTopLevelItem( selectedIndex );
mLayerOrderTreeWidget->insertTopLevelItem( selectedIndex - 1, selectedItem );
mLayerOrderTreeWidget->clearSelection();
selectedItem->setSelected( true );
}
void QgsOWSSourceSelect::on_mLayerDownButton_clicked()
{
QList<QTreeWidgetItem *> selectionList = mLayerOrderTreeWidget->selectedItems();
if ( selectionList.size() < 1 )
{
return;
}
int selectedIndex = mLayerOrderTreeWidget->indexOfTopLevelItem( selectionList[0] );
if ( selectedIndex < 0 || selectedIndex > mLayerOrderTreeWidget->topLevelItemCount() - 2 )
{
return; //item not existing or already at bottom
}
QTreeWidgetItem* selectedItem = mLayerOrderTreeWidget->takeTopLevelItem( selectedIndex );
mLayerOrderTreeWidget->insertTopLevelItem( selectedIndex + 1, selectedItem );
mLayerOrderTreeWidget->clearSelection();
selectedItem->setSelected( true );
}
QList<QgsOWSSupportedFormat> QgsOWSSourceSelect::providerFormats()
{
return QList<QgsOWSSupportedFormat>();
}
QStringList QgsOWSSourceSelect::selectedLayersFormats()
{
return QStringList();
}
QStringList QgsOWSSourceSelect::selectedLayersCRSs()
{
return QStringList();
}
void QgsOWSSourceSelect::updateButtons()
{
}

View File

@ -0,0 +1,237 @@
/***************************************************************************
qgsowssourceselect.h - selector for WMS,WFS,WCS layers
-------------------
begin : 3 April 2005
original : (C) 2005 by Brendan Morley email : morb at ozemail dot com dot au
wms search : (C) 2009 Mathias Walker <mwa at sourcepole.ch>, Sourcepole AG
generalized : (C) 2012 Radim Blazek, based on qgsowsconnection.h
***************************************************************************/
/***************************************************************************
* *
* 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 QGSOWSSOURCESELECT_H
#define QGSOWSSOURCESELECT_H
#include "ui_qgsowssourceselectbase.h"
#include "qgsdatasourceuri.h"
#include "qgisgui.h"
#include "qgscontexthelp.h"
#include "qgsdataprovider.h"
#include <QStringList>
#include <QPushButton>
class QgisApp;
class QgsDataProvider;
class QButtonGroup;
class QgsNumericSortTreeWidgetItem;
class QDomDocument;
class QDomElement;
/** Formats supported by provider */
struct QgsOWSSupportedFormat
{
QString format;
QString label;
};
/*!
* \brief Dialog to create connections and add layers from WMS, WFS, WCS etc.
*
* This dialog allows the user to define and save connection information
* for WMS servers, etc.
*
* The user can then connect and add
* layers from the WMS server to the map canvas.
*/
class QgsOWSSourceSelect : public QDialog, public Ui::QgsOWSSourceSelectBase
{
Q_OBJECT
public:
//! Constructor
QgsOWSSourceSelect( QString service, QWidget *parent = 0, Qt::WFlags fl = QgisGui::ModalDialogFlags, bool managerMode = false, bool embeddedMode = false );
//! Destructor
~QgsOWSSourceSelect();
public slots:
//! Opens the create connection dialog to build a new connection
void on_mNewButton_clicked();
//! Opens a dialog to edit an existing connection
void on_mEditButton_clicked();
//! Deletes the selected connection
void on_mDeleteButton_clicked();
//! Saves connections to the file
void on_mSaveButton_clicked();
//! Loads connections from the file
void on_mLoadButton_clicked();
/*! Connects to the database using the stored connection parameters.
* Once connected, available layers are displayed.
*/
void on_mConnectButton_clicked();
//! Determines the layers the user selected
virtual void addClicked();
void searchFinished();
//! Opens the Spatial Reference System dialog.
void on_mChangeCRSButton_clicked();
//! Signaled when a layer selection is changed.
virtual void on_mLayersTreeWidget_itemSelectionChanged();
//! Set status message to theMessage
void showStatusMessage( QString const &theMessage );
//! show whatever error is exposed.
void showError( QString const &theTitle, QString const &theFormat, QString const &theError );
//! Stores the selected datasource whenerver it is changed
void on_mConnectionsComboBox_activated( int );
//! Add some default wms servers to the list
void on_mAddDefaultButton_clicked();
void on_mDialogButtonBox_helpRequested() { QgsContextHelp::run( metaObject()->className() ); }
signals:
void addRasterLayer( QString const & rasterLayerPath,
QString const & baseName,
QString const & providerKey );
void connectionsChanged();
protected:
/**
* List of image formats (encodings) supported by provider
* @return list of format/label pairs
*/
virtual QList<QgsOWSSupportedFormat> providerFormats();
//! List of formats supported for currently selected layer item(s)
virtual QStringList selectedLayersFormats();
//! Server CRS supported for currently selected layer item(s)
virtual QStringList selectedLayersCRSs();
//virtual QStringList layerCRS( int id );
//! Populate the connection list combo box
void populateConnectionList();
//! Populate supported formats
void populateFormats();
//! Clear previously set formats
void clearFormats();
//! Set supported CRSs
void populateCRS();
//! Connection name
QString connName();
//! Connection info (uri)
QString connectionInfo();
//! Set the server connection combo box to that stored in the config file.
void setConnectionListPosition();
//! Add a few example servers to the list.
void addDefaultServers();
//! Service name
QString mService;
//! Connections manager mode
bool mManagerMode;
//! Embedded mode, without 'Close'
bool mEmbeddedMode;
/**
* \brief Populate the layer list.
*
* \retval false if the layers could not be retrieved or parsed
*/
virtual void populateLayerList( );
//! create an item including possible parents
QgsNumericSortTreeWidgetItem *createItem( int id,
const QStringList &names,
QMap<int, QgsNumericSortTreeWidgetItem *> &items,
int &layerAndStyleCount,
const QMap<int, int> &layerParents,
const QMap<int, QStringList> &layerParentNames );
//! Returns a textual description for the authority id
QString descriptionForAuthId( QString authId );
//! layer name derived from latest layer selection (updated as long it's not edited manually)
QString mLastLayerName;
//! The widget that controls the image format radio buttons
QButtonGroup *mImageFormatGroup;
QPushButton *mAddButton;
QMap<QString, QString> mCrsNames;
void addWMSListRow( const QDomElement& item, int row );
void addWMSListItem( const QDomElement& el, int row, int column );
virtual void enableLayersForCrs( QTreeWidgetItem *item );
//! Returns currently selected format
QString selectedFormat();
//! Returns currently selected Crs
QString selectedCRS();
QList<QTreeWidgetItem*> mCurrentSelection;
QTableWidgetItem* mCurrentTileset;
//! Name for selected connection
QString mConnName;
//! Cnnection info for selected connection
QString mConnectionInfo;
//! URI for selected connection
QgsDataSourceURI mUri;
private:
//! Selected CRS
QString mSelectedCRS;
//! Common CRSs for selected layers
QSet<QString> mSelectedLayersCRSs;
//! Supported formats
QList<QgsOWSSupportedFormat> mProviderFormats;
//! Map mime type labels to supported formats
QMap<QString, QString> mMimeLabelMap;
private slots:
void on_mSearchButton_clicked();
void on_mAddWMSButton_clicked();
void on_mSearchTableWidget_itemSelectionChanged();
void on_mTilesetsTableWidget_itemClicked( QTableWidgetItem *item );
void on_mLayerUpButton_clicked();
void on_mLayerDownButton_clicked();
virtual void updateButtons();
};
#endif // QGSOWSSOURCESELECT_H

View File

@ -10,6 +10,7 @@ ADD_SUBDIRECTORY(osm)
ADD_SUBDIRECTORY(sqlanywhere)
ADD_SUBDIRECTORY(gdal)
ADD_SUBDIRECTORY(mssql)
ADD_SUBDIRECTORY(ows)
IF (POSTGRES_FOUND)
ADD_SUBDIRECTORY(postgres)

View File

@ -1,9 +1,21 @@
SET(GDAL_SRCS qgsgdalprovider.cpp qgsgdaldataitems.cpp)
SET(GDAL_MOC_HDRS qgsgdalprovider.h)
SET(GDAL_SRCS
qgsgdalprovider.cpp
qgsgdaldataitems.cpp
qgswcscapabilities.cpp
qgswcssourceselect.cpp
)
SET(GDAL_MOC_HDRS
qgsgdalprovider.h
qgsgdaldataitems.h
qgswcscapabilities.h
qgswcssourceselect.h
)
INCLUDE_DIRECTORIES (
../../core
../../core/raster
../../gui
${CMAKE_CURRENT_BINARY_DIR}/../../ui
${GDAL_INCLUDE_DIR}
# ${PROJ_INCLUDE_DIR}
# ${GEOS_INCLUDE_DIR}
@ -14,6 +26,7 @@ ADD_LIBRARY (gdalprovider MODULE ${GDAL_SRCS} ${GDAL_MOC_SRCS})
TARGET_LINK_LIBRARIES (gdalprovider
qgis_core
qgis_gui
)
INSTALL(TARGETS gdalprovider

View File

@ -15,6 +15,10 @@
#include "qgsgdaldataitems.h"
#include "qgsgdalprovider.h"
#include "qgslogger.h"
#include "qgsdatasourceuri.h"
#include "qgswcssourceselect.h"
#include "qgsowsconnection.h"
#include "qgsnewhttpconnection.h"
#include <QFileInfo>
#include <QSettings>
@ -112,6 +116,259 @@ QString QgsGdalLayerItem::layerName() const
return info.completeBaseName();
}
// ---------------------------------------------------------------------------
QgsWCSConnectionItem::QgsWCSConnectionItem( QgsDataItem* parent, QString name, QString path )
: QgsDataCollectionItem( parent, name, path )
{
mIcon = QIcon( getThemePixmap( "mIconWcs.png" ) );
}
QgsWCSConnectionItem::~QgsWCSConnectionItem()
{
QgsDebugMsg( "Entered" );
}
QVector<QgsDataItem*> QgsWCSConnectionItem::createChildren()
{
QgsDebugMsg( "Entered" );
QVector<QgsDataItem*> children;
QString encodedUri = mPath;
QgsDataSourceURI uri;
uri.setEncodedUri( encodedUri );
QgsDebugMsg( "encodedUri = " + encodedUri );
mCapabilities.setUri( uri );
// Attention: supportedLayers() gives tree leafes, not top level
if ( !mCapabilities.lastError().isEmpty() )
{
//children.append( new QgsErrorItem( this, tr( "Failed to retrieve layers" ), mPath + "/error" ) );
// TODO: show the error without adding child
return children;
}
foreach( QgsWcsCoverageSummary coverageSummary, mCapabilities.capabilities().contents.coverageSummary )
{
// Attention, the name may be empty
QgsDebugMsg( QString::number( coverageSummary.orderId ) + " " + coverageSummary.identifier + " " + coverageSummary.title );
QString pathName = coverageSummary.identifier.isEmpty() ? QString::number( coverageSummary.orderId ) : coverageSummary.identifier;
QgsWCSLayerItem * layer = new QgsWCSLayerItem( this, coverageSummary.title, mPath + "/" + pathName, mCapabilities.capabilities(), uri, coverageSummary );
children.append( layer );
}
return children;
}
bool QgsWCSConnectionItem::equal( const QgsDataItem *other )
{
if ( type() != other->type() )
{
return false;
}
const QgsWCSConnectionItem *o = dynamic_cast<const QgsWCSConnectionItem *>( other );
if ( !o )
{
return false;
}
return ( mPath == o->mPath && mName == o->mName );
}
QList<QAction*> QgsWCSConnectionItem::actions()
{
QList<QAction*> lst;
QAction* actionEdit = new QAction( tr( "Edit..." ), this );
connect( actionEdit, SIGNAL( triggered() ), this, SLOT( editConnection() ) );
lst.append( actionEdit );
QAction* actionDelete = new QAction( tr( "Delete" ), this );
connect( actionDelete, SIGNAL( triggered() ), this, SLOT( deleteConnection() ) );
lst.append( actionDelete );
return lst;
}
void QgsWCSConnectionItem::editConnection()
{
QgsNewHttpConnection nc( 0, "/Qgis/connections-wcs/", mName );
if ( nc.exec() )
{
// the parent should be updated
mParent->refresh();
}
}
void QgsWCSConnectionItem::deleteConnection()
{
QgsOWSConnection::deleteConnection( "WCS", mName );
// the parent should be updated
mParent->refresh();
}
// ---------------------------------------------------------------------------
QgsWCSLayerItem::QgsWCSLayerItem( QgsDataItem* parent, QString name, QString path, QgsWcsCapabilitiesProperty capabilitiesProperty, QgsDataSourceURI dataSourceUri, QgsWcsCoverageSummary coverageSummary )
: QgsLayerItem( parent, name, path, QString(), QgsLayerItem::Raster, "gdal" ),
mCapabilities( capabilitiesProperty ),
mDataSourceUri( dataSourceUri ),
mCoverageSummary( coverageSummary )
{
QgsDebugMsg( "uri = " + mDataSourceUri.encodedUri() );
mUri = createUri();
// Populate everything, it costs nothing, all info about layers is collected
foreach( QgsWcsCoverageSummary coverageSummary, mCoverageSummary.coverageSummary )
{
// Attention, the name may be empty
QgsDebugMsg( QString::number( coverageSummary.orderId ) + " " + coverageSummary.identifier + " " + coverageSummary.title );
QString pathName = coverageSummary.identifier.isEmpty() ? QString::number( coverageSummary.orderId ) : coverageSummary.identifier;
QgsWCSLayerItem * layer = new QgsWCSLayerItem( this, coverageSummary.title, mPath + "/" + pathName, mCapabilities, mDataSourceUri, coverageSummary );
mChildren.append( layer );
}
if ( mChildren.size() == 0 )
{
//mIcon = iconRaster();
mIcon = QIcon( getThemePixmap( "mIconWcs.png" ) );
}
mPopulated = true;
}
QgsWCSLayerItem::~QgsWCSLayerItem()
{
}
QString QgsWCSLayerItem::createUri()
{
if ( mCoverageSummary.identifier.isEmpty() )
return ""; // layer collection
// Number of styles must match number of layers
mDataSourceUri.setParam( "identifier", mCoverageSummary.identifier );
// TODO(?): with WCS 1.0 GetCapabilities does not contain CRS and formats,
// to get them we would need to call QgsWcsCapabilities::describeCoverage
// but it is problematic to get QgsWcsCapabilities here (copy not allowed
// by QObject, pointer is dangerous (OWS provider is changing parent))
// We leave CRS and format default for now.
QString format;
// get first supported by GDAL and server
QStringList mimes = QgsGdalProvider::supportedMimes().keys();
// prefer tiff
if ( mimes.contains( "image/tiff" ) && mCoverageSummary.supportedFormat.contains( "image/tiff" ) )
{
format = "image/tiff";
}
else
{
foreach( QString f, mimes )
{
if ( mCoverageSummary.supportedFormat.indexOf( f ) >= 0 )
{
format = f;
break;
}
}
}
if ( !format.isEmpty() )
{
mDataSourceUri.setParam( "format", format );
}
QString crs;
// TODO: prefer project CRS
// get first known if possible
QgsCoordinateReferenceSystem testCrs;
foreach( QString c, mCoverageSummary.supportedCrs )
{
testCrs.createFromOgcWmsCrs( c );
if ( testCrs.isValid() )
{
crs = c;
break;
}
}
if ( crs.isEmpty() && mCoverageSummary.supportedCrs.size() > 0 )
{
crs = mCoverageSummary.supportedCrs.value( 0 );
}
if ( !crs.isEmpty() )
{
mDataSourceUri.setParam( "crs", crs );
}
return mDataSourceUri.encodedUri();
}
// ---------------------------------------------------------------------------
QgsWCSRootItem::QgsWCSRootItem( QgsDataItem* parent, QString name, QString path )
: QgsDataCollectionItem( parent, name, path )
{
mIcon = QIcon( getThemePixmap( "mIconWcs.png" ) );
populate();
}
QgsWCSRootItem::~QgsWCSRootItem()
{
}
QVector<QgsDataItem*>QgsWCSRootItem::createChildren()
{
QVector<QgsDataItem*> connections;
foreach( QString connName, QgsOWSConnection::connectionList( "WCS" ) )
{
//QgsDataItem * conn = new QgsWCSConnectionItem( this, connName, mPath + "/" + connName );
QgsOWSConnection connection( "WCS", connName );
QgsDataItem * conn = new QgsWCSConnectionItem( this, connName, connection.uri().encodedUri() );
conn->setIcon( QIcon( getThemePixmap( "mIconConnect.png" ) ) );
connections.append( conn );
}
return connections;
}
QList<QAction*> QgsWCSRootItem::actions()
{
QList<QAction*> lst;
QAction* actionNew = new QAction( tr( "New Connection..." ), this );
connect( actionNew, SIGNAL( triggered() ), this, SLOT( newConnection() ) );
lst.append( actionNew );
return lst;
}
QWidget * QgsWCSRootItem::paramWidget()
{
QgsWCSSourceSelect *select = new QgsWCSSourceSelect( 0, 0, true, true );
connect( select, SIGNAL( connectionsChanged() ), this, SLOT( connectionsChanged() ) );
return select;
return 0;
}
void QgsWCSRootItem::connectionsChanged()
{
refresh();
}
void QgsWCSRootItem::newConnection()
{
QgsNewHttpConnection nc( 0, "/Qgis/connections-wcs/" );
if ( nc.exec() )
{
refresh();
}
}
// ---------------------------------------------------------------------------
static QString filterString;
@ -120,13 +377,24 @@ static QStringList wildcards = QStringList();
QGISEXTERN int dataCapabilities()
{
return QgsDataProvider::File | QgsDataProvider::Dir;
return QgsDataProvider::File | QgsDataProvider::Dir | QgsDataProvider::Net;
}
QGISEXTERN QgsDataItem * dataItem( QString thePath, QgsDataItem* parentItem )
{
QgsDebugMsg( "thePath = " + thePath );
if ( thePath.isEmpty() )
return 0;
{
// Top level WCS
return new QgsWCSRootItem( parentItem, "WCS", "wcs:" );
}
if ( thePath.contains( "url=" ) )
{
// OWS server
QgsDebugMsg( "connection found in uri" );
return new QgsWCSConnectionItem( parentItem, "WCS", thePath );
}
// zip settings + info
QSettings settings;
@ -259,3 +527,8 @@ QGISEXTERN QgsDataItem * dataItem( QString thePath, QgsDataItem* parentItem )
return item;
}
QGISEXTERN QgsWCSSourceSelect * selectWidget( QWidget * parent, Qt::WFlags fl )
{
return new QgsWCSSourceSelect( parent, fl );
}

View File

@ -16,6 +16,9 @@
#define QGSGDALDATAITEMS_H
#include "qgsdataitem.h"
#include "qgsdatasourceuri.h"
//#include "qgsowsconnection.h"
#include "qgswcscapabilities.h"
class QgsGdalLayerItem : public QgsLayerItem
{
@ -37,5 +40,60 @@ class QgsGdalLayerItem : public QgsLayerItem
QString layerName() const;
};
class QgsWCSConnectionItem : public QgsDataCollectionItem
{
Q_OBJECT
public:
QgsWCSConnectionItem( QgsDataItem* parent, QString name, QString path );
~QgsWCSConnectionItem();
QVector<QgsDataItem*> createChildren();
virtual bool equal( const QgsDataItem *other );
virtual QList<QAction*> actions();
QgsWcsCapabilities mCapabilities;
QVector<QgsWcsCoverageSummary> mLayerProperties;
public slots:
void editConnection();
void deleteConnection();
};
// WCS Layers may be nested, so that they may be both QgsDataCollectionItem and QgsLayerItem
// We have to use QgsDataCollectionItem and support layer methods if necessary
class QgsWCSLayerItem : public QgsLayerItem
{
Q_OBJECT
public:
QgsWCSLayerItem( QgsDataItem* parent, QString name, QString path,
QgsWcsCapabilitiesProperty capabilitiesProperty, QgsDataSourceURI dataSourceUri, QgsWcsCoverageSummary coverageSummary );
~QgsWCSLayerItem();
QString createUri();
QgsWcsCapabilitiesProperty mCapabilities;
QgsDataSourceURI mDataSourceUri;
QgsWcsCoverageSummary mCoverageSummary;
};
class QgsWCSRootItem : public QgsDataCollectionItem
{
Q_OBJECT
public:
QgsWCSRootItem( QgsDataItem* parent, QString name, QString path );
~QgsWCSRootItem();
QVector<QgsDataItem*> createChildren();
virtual QList<QAction*> actions();
virtual QWidget * paramWidget();
public slots:
void connectionsChanged();
void newConnection();
};
#endif // QGSGDALDATAITEMS_H

View File

@ -24,11 +24,14 @@
#include "qgsapplication.h"
#include "qgscoordinatetransform.h"
#include "qgsdataitem.h"
#include "qgsdatasourceuri.h"
#include "qgsmessagelog.h"
#include "qgsrectangle.h"
#include "qgscoordinatereferencesystem.h"
#include "qgsrasterbandstats.h"
#include "qgsrasterlayer.h"
#include "qgsrasterpyramid.h"
#include "qgswcscapabilities.h"
#include <QImage>
#include <QSettings>
@ -41,6 +44,7 @@
#include <QHash>
#include <QTime>
#include <QSettings>
#include <QTextDocument>
#include "gdalwarper.h"
#include "ogr_spatialref.h"
@ -122,13 +126,79 @@ QgsGdalProvider::QgsGdalProvider( QString const & uri )
QgsDebugMsg( QString( "Trying /vsigzip syntax, uri= %1" ).arg( dataSourceUri() ) );
}
//mGdalBaseDataset = GDALOpen( QFile::encodeName( uri ).constData(), GA_ReadOnly );
mGdalBaseDataset = GDALOpen( TO8F( dataSourceUri() ), GA_ReadOnly );
// The uri is either a file name or encoded parameters for WCS
QString gdalUri = dataSourceUri();
if ( uri.contains( "url=" ) && uri.contains( "identifier=" ) && !QFile::exists( uri ) )
{
// - GDAL currently (4/2012) supports WCS 1.0.0 (default) and 1.1.0
// We cannot use 1.1.0 because of wrong longlat bbox send by GDAL
// and impossibility to set GridOffsets.
// - WCS 1.0.0 does not work with GDAL r24316 2012-04-25 + Mapserver 6.0.2
// 1) with geographic CRS
// GDAL sends BOUNDINGBOX=min_long,min_lat,max_lon,max_lat,urn:ogc:def:crs:EPSG::4326
// Mapserver works with min_lat,min_long,max_lon,max_lat
// OGC 07-067r5 (WCS 1.1.2) referes to OGC 06-121r3 which says:
// "The number of axes included, and the order of these axes, shall be as
// specified by the referenced CRS."
// EPSG defines for EPSG:4326 Axes: latitude, longitude
// (don't confuse with OGC:CRS84 with lon,lat order)
// Created a ticket: http://trac.osgeo.org/gdal/ticket/4639
// 2) Mapserver ignores RangeSubset (not implemented in mapserver)
// and GDAL fails with "Returned tile does not match expected band count"
// because it requested single band but recieved all bands
// Created ticket: https://github.com/mapserver/mapserver/issues/4299
// Other problems:
// - GDAL WCS fails to open 1.1 with space in RangeSubset, there is a ticket about
// it http://trac.osgeo.org/gdal/ticket/1833 without conclusion, Frank suggests
// that ServiceURL should be expected to be escaped while CoverageName should not
QgsDataSourceURI dsUri;
dsUri.setEncodedUri( uri );
gdalUri = "<WCS_GDAL>";
gdalUri += "<Version>1.0.0</Version>";
//gdalUri += "<Version>1.1.0</Version>";
// prepareUri adds ? or & if necessary, GDAL fails otherwise
gdalUri += "<ServiceURL>" + Qt::escape( QgsWcsCapabilities::prepareUri( dsUri.param( "url" ) ) ) + "</ServiceURL>";
gdalUri += "<CoverageName>" + dsUri.param( "identifier" ) + "</CoverageName>";
if ( dsUri.hasParam( "format" ) )
{
gdalUri += "<PreferredFormat>" + dsUri.param( "format" ) + "</PreferredFormat>";
}
// - CRS : there is undocumented GDAL CRS tag, but it only overrides CRS param
// in requests but the BBOX is left unchanged and thus results in server error (usually).
// 1.0 : RESPONSE_CRS
if ( dsUri.hasParam( "crs" ) )
{
gdalUri += "<GetCoverageExtra>&amp;RESPONSE_CRS=" + dsUri.param( "crs" ) + "</GetCoverageExtra>";
}
// 1.1 : Required parameters are: GridBaseCRS and GridOffsets (resolution)
// We dont have the GridOffsets here and it should be probably dynamic
// according to requested data (zoom).
// Mapserver 6.0.2 works without the GridOffsets, but other servers may not.
//QString crsUrn = "urn:ogc:def:crs:" + dsUri.param("crs").replace(":","::");
//gdalUri += "<GetCoverageExtra>&amp;GridBaseCRS=" + crsUrn + "</GetCoverageExtra>";
if ( dsUri.hasParam( "username" ) && dsUri.hasParam( "password" ) )
{
gdalUri += "<UserPwd>" + dsUri.param( "username" ) + ":" + dsUri.param( "password" ) + "</UserPwd>";
}
gdalUri += "</WCS_GDAL>";
QgsDebugMsg( "WCS uri: " + gdalUri );
}
CPLErrorReset();
mGdalBaseDataset = GDALOpen( TO8F( gdalUri ), GA_ReadOnly );
if ( !mGdalBaseDataset )
{
QgsDebugMsg( QString( "Cannot open GDAL dataset %1: %2" ).arg( dataSourceUri() ).arg( QString::fromUtf8( CPLGetLastErrorMsg() ) ) );
QString msg = QString( "Cannot open GDAL dataset %1:\n%2" ).arg( dataSourceUri() ).arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
QgsDebugMsg( msg );
QgsMessageLog::logMessage( msg );
return;
}
@ -1188,6 +1258,8 @@ int QgsGdalProvider::srcDataType( int bandNo ) const
int QgsGdalProvider::dataType( int bandNo ) const
{
if ( mGdalDataType.size() == 0 ) return QgsRasterDataProvider::UnknownDataType;
return dataTypeFormGdal( mGdalDataType[bandNo-1] );
}
@ -2002,3 +2074,34 @@ QGISEXTERN void buildSupportedRasterFileFilter( QString & theFileFiltersString )
buildSupportedRasterFileFilterAndExtensions( theFileFiltersString, exts, wildcards );
}
QMap<QString, QString> QgsGdalProvider::supportedMimes()
{
QMap<QString, QString> mimes;
GDALAllRegister();
QgsDebugMsg( QString( "GDAL drivers cont %1" ).arg( GDALGetDriverCount() ) );
for ( int i = 0; i < GDALGetDriverCount(); ++i )
{
GDALDriverH driver = GDALGetDriver( i );
Q_CHECK_PTR( driver );
if ( !driver )
{
QgsLogger::warning( "unable to get driver " + QString::number( i ) );
continue;
}
QString desc = GDALGetDescription( driver );
QString mimeType = GDALGetMetadataItem( driver, "DMD_MIMETYPE", "" );
if ( mimeType.isEmpty() ) continue;
desc = desc.isEmpty() ? mimeType : desc;
QgsDebugMsg( "add GDAL format " + mimeType + " " + desc );
mimes[mimeType] = desc;
}
return mimes;
}

View File

@ -260,6 +260,8 @@ class QgsGdalProvider : public QgsRasterDataProvider
/** Emit a signal to notify of the progress event. */
void emitProgress( int theType, double theProgress, QString theMessage );
static QMap<QString, QString> supportedMimes();
signals:
void statusChanged( QString );

View File

@ -0,0 +1,873 @@
/***************************************************************************
qgswcscapabilities.cpp - WCS capabilities
-------------------
begin : 17 Mar, 2005
copyright : (C) 2005 by Brendan Morley
email : morb at ozemail dot com dot au
wcs : 4/2012 Radim Blazek, based on qgswmsprovider.cpp
***************************************************************************/
/***************************************************************************
* *
* 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 <typeinfo>
#define WCS_THRESHOLD 200 // time to wait for an answer without emitting dataChanged()
#include "qgslogger.h"
#include "qgswcscapabilities.h"
#include "qgsowsconnection.h"
#include <cmath>
#include "qgscoordinatetransform.h"
#include "qgsdatasourceuri.h"
#include "qgsrasterlayer.h"
#include "qgsrectangle.h"
#include "qgscoordinatereferencesystem.h"
#include "qgsnetworkaccessmanager.h"
#include <qgsmessageoutput.h>
#include <qgsmessagelog.h>
#include <QNetworkRequest>
#include <QNetworkReply>
#include <QNetworkProxy>
#if QT_VERSION >= 0x40500
#include <QNetworkDiskCache>
#endif
#include <QUrl>
#include <QIcon>
#include <QImage>
#include <QImageReader>
#include <QPainter>
#include <QPixmap>
#include <QSet>
#include <QSettings>
#include <QEventLoop>
#include <QCoreApplication>
#include <QTime>
#ifdef _MSC_VER
#include <float.h>
#define isfinite(x) _finite(x)
#endif
#ifdef QGISDEBUG
#include <QFile>
#include <QDir>
#endif
/*
QgsWcsCapabilities::QgsWcsCapabilities( QString const &theUri )
{
mUri.setEncodedUri( theUri );
QgsDebugMsg( "theUri = " + theUri );
}
*/
QgsWcsCapabilities::QgsWcsCapabilities( QgsDataSourceURI const &theUri ):
mUri( theUri ),
mCoverageCount( 0 )
{
QgsDebugMsg( "uri = " + mUri.encodedUri() );
retrieveServerCapabilities();
}
QgsWcsCapabilities::QgsWcsCapabilities( ):
mCoverageCount( 0 )
{
}
QgsWcsCapabilities::~QgsWcsCapabilities()
{
QgsDebugMsg( "deconstructing." );
}
void QgsWcsCapabilities::setUri( QgsDataSourceURI const &theUri )
{
mUri = theUri;
mCoverageCount = 0;
mCoveragesSupported.clear();
QgsWcsCapabilitiesProperty c;
mCapabilities = c;
retrieveServerCapabilities( true );
}
QString QgsWcsCapabilities::prepareUri( QString uri )
{
if ( !uri.contains( "?" ) )
{
uri.append( "?" );
}
else if ( uri.right( 1 ) != "?" && uri.right( 1 ) != "&" )
{
uri.append( "&" );
}
return uri;
}
QgsWcsCapabilitiesProperty QgsWcsCapabilities::capabilities()
{
return mCapabilities;
}
bool QgsWcsCapabilities::supportedCoverages( QVector<QgsWcsCoverageSummary> &coverageSummary )
{
QgsDebugMsg( "Entering." );
// Allow the provider to collect the capabilities first.
if ( !retrieveServerCapabilities() )
{
return false;
}
coverageSummary = mCoveragesSupported;
QgsDebugMsg( "Exiting." );
return true;
}
QString QgsWcsCapabilities::getCoverageUrl() const
{
QString url = mCapabilities.operationsMetadata.getCoverage.dcp.http.get.xlinkHref;
if ( url.isEmpty() )
{
url = mUri.param( "url" );
}
return url;
}
bool QgsWcsCapabilities::sendRequest( QString const & url )
{
QgsDebugMsg( "url = " + url );
mError = "";
QNetworkRequest request( url );
setAuthorization( request );
request.setAttribute( QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferNetwork );
request.setAttribute( QNetworkRequest::CacheSaveControlAttribute, true );
QgsDebugMsg( QString( "getcapabilities: %1" ).arg( url ) );
mCapabilitiesReply = QgsNetworkAccessManager::instance()->get( request );
connect( mCapabilitiesReply, SIGNAL( finished() ), this, SLOT( capabilitiesReplyFinished() ) );
connect( mCapabilitiesReply, SIGNAL( downloadProgress( qint64, qint64 ) ), this, SLOT( capabilitiesReplyProgress( qint64, qint64 ) ) );
while ( mCapabilitiesReply )
{
QCoreApplication::processEvents( QEventLoop::ExcludeUserInputEvents );
}
if ( mCapabilitiesResponse.isEmpty() )
{
if ( mError.isEmpty() )
{
mErrorFormat = "text/plain";
mError = tr( "empty capabilities document" );
}
return false;
}
if ( mCapabilitiesResponse.startsWith( "<html>" ) ||
mCapabilitiesResponse.startsWith( "<HTML>" ) )
{
mErrorFormat = "text/html";
mError = mCapabilitiesResponse;
return false;
}
return true;
}
bool QgsWcsCapabilities::retrieveServerCapabilities( bool forceRefresh )
{
if ( mCapabilitiesResponse.isNull() || forceRefresh )
{
// Check if user tried to force version
QString userVersion = QUrl( mUri.param( "url" ) ).queryItemValue( "VERSION" );
if ( !userVersion.isEmpty() && !userVersion.startsWith( "1.0." ) )
{
mErrorTitle = tr( "Version not supported" );
mErrorFormat = "text/plain";
mError = tr( "The version %1 specified in connection URL parameter VERSION is not supported by QGIS" ).arg( userVersion );
return false;
}
QString url = prepareUri( mUri.param( "url" ) ) + "SERVICE=WCS&REQUEST=GetCapabilities&VERSION=1.0.0";
if ( ! sendRequest( url ) ) { return false; }
QgsDebugMsg( "Converting to Dom." );
bool domOK;
domOK = parseCapabilitiesDom( mCapabilitiesResponse, mCapabilities );
if ( !domOK )
{
// We had an Dom exception -
// mErrorTitle and mError are pre-filled by parseCapabilitiesDom
mError += tr( "\nTried URL: %1" ).arg( url );
QgsDebugMsg( "!domOK: " + mError );
return false;
}
}
return true;
}
bool QgsWcsCapabilities::describeCoverage( QString const &identifier, bool forceRefresh )
{
QgsDebugMsg( " identifier = " + identifier );
if ( !mVersion.startsWith( "1.0." ) ) { return true; } // no need for 1.1
QgsWcsCoverageSummary *coverage = coverageSummary( identifier );
if ( !coverage )
{
QgsDebugMsg( "coverage not found" );
return false;
}
if ( coverage->described && ! forceRefresh ) return true;
QString url = prepareUri( mUri.param( "url" ) ) + "SERVICE=WCS&REQUEST=DescribeCoverage&VERSION=1.0.0&COVERAGE=" + coverage->identifier;
if ( ! sendRequest( url ) ) { return false; }
QgsDebugMsg( "Converting to Dom." );
bool domOK;
domOK = parseDescribeCoverageDom( mCapabilitiesResponse, coverage );
QgsDebugMsg( "supportedFormat = " + coverage->supportedFormat.join( "," ) );
if ( !domOK )
{
// We had an Dom exception -
// mErrorTitle and mError are pre-filled by parseCapabilitiesDom
mError += tr( "\nTried URL: %1" ).arg( url );
QgsDebugMsg( "!domOK: " + mError );
return false;
}
return true;
}
void QgsWcsCapabilities::capabilitiesReplyFinished()
{
if ( mCapabilitiesReply->error() == QNetworkReply::NoError )
{
QVariant redirect = mCapabilitiesReply->attribute( QNetworkRequest::RedirectionTargetAttribute );
if ( !redirect.isNull() )
{
emit statusChanged( tr( "Capabilities request redirected." ) );
QNetworkRequest request( redirect.toUrl() );
setAuthorization( request );
request.setAttribute( QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferNetwork );
request.setAttribute( QNetworkRequest::CacheSaveControlAttribute, true );
mCapabilitiesReply->deleteLater();
QgsDebugMsg( QString( "redirected getcapabilities: %1" ).arg( redirect.toString() ) );
mCapabilitiesReply = QgsNetworkAccessManager::instance()->get( request );
connect( mCapabilitiesReply, SIGNAL( finished() ), this, SLOT( capabilitiesReplyFinished() ) );
connect( mCapabilitiesReply, SIGNAL( downloadProgress( qint64, qint64 ) ), this, SLOT( capabilitiesReplyProgress( qint64, qint64 ) ) );
return;
}
mCapabilitiesResponse = mCapabilitiesReply->readAll();
if ( mCapabilitiesResponse.isEmpty() )
{
mErrorFormat = "text/plain";
mError = tr( "empty of capabilities: %1" ).arg( mCapabilitiesReply->errorString() );
}
}
else
{
mErrorFormat = "text/plain";
mError = tr( "Download of capabilities failed: %1" ).arg( mCapabilitiesReply->errorString() );
QgsMessageLog::logMessage( mError, tr( "WCS" ) );
mCapabilitiesResponse.clear();
}
mCapabilitiesReply->deleteLater();
mCapabilitiesReply = 0;
}
void QgsWcsCapabilities::capabilitiesReplyProgress( qint64 bytesReceived, qint64 bytesTotal )
{
QString msg = tr( "%1 of %2 bytes of capabilities downloaded." ).arg( bytesReceived ).arg( bytesTotal < 0 ? QString( "unknown number of" ) : QString::number( bytesTotal ) );
QgsDebugMsg( msg );
emit statusChanged( msg );
}
QString QgsWcsCapabilities::stripNS( const QString & name )
{
return name.contains( ":" ) ? name.section( ':', 1 ) : name;
}
bool QgsWcsCapabilities::parseCapabilitiesDom( QByteArray const &xml, QgsWcsCapabilitiesProperty &capabilities )
{
QgsDebugMsg( "Entered." );
#ifdef QGISDEBUG
QFile file( QDir::tempPath() + "/qgis-wcs-capabilities.xml" );
if ( file.open( QIODevice::WriteOnly ) )
{
file.write( xml );
file.close();
}
#endif
if ( ! convertToDom( xml ) ) return false;
QDomElement docElem = mCapabilitiesDom.documentElement();
// Assert that the DTD is what we expected (i.e. a WCS Capabilities document)
QgsDebugMsg( "testing tagName " + docElem.tagName() );
QString tagName = stripNS( docElem.tagName() );
if (
// We don't support 1.0, but try WCS_Capabilities tag to get version
tagName != "WCS_Capabilities" && // 1.0
tagName != "Capabilities" // 1.1, tags seen: Capabilities, wcs:Capabilities
)
{
mErrorTitle = tr( "Dom Exception" );
mErrorFormat = "text/plain";
mError = tr( "Could not get WCS capabilities in the expected format (DTD): no %1 found.\nThis might be due to an incorrect WCS Server URL.\nTag:%3\nResponse was:\n%4" )
.arg( "Capabilities" )
.arg( docElem.tagName() )
.arg( QString( xml ) );
QgsLogger::debug( "Dom Exception: " + mError );
return false;
}
capabilities.version = docElem.attribute( "version" );
mVersion = capabilities.version;
if ( !mVersion.startsWith( "1.0." ) )
{
mErrorTitle = tr( "Version not supported" );
mErrorFormat = "text/plain";
mError = tr( "Could not get WCS capabilities in the expected version 1.1.\nResponse version was: %1" )
.arg( mVersion );
QgsLogger::debug( "WCS version: " + mError );
return false;
}
// Start walking through XML.
QDomNode n = docElem.firstChild();
while ( !n.isNull() )
{
QDomElement e = n.toElement();
if ( !e.isNull() )
{
// Version 1.0
QString tagName = stripNS( e.tagName() );
QgsDebugMsg( tagName );
if ( tagName == "Service" )
{
parseService( e, capabilities.serviceIdentification );
}
else if ( tagName == "Capability" )
{
parseCapability( e, capabilities.operationsMetadata );
}
else if ( tagName == "ContentMetadata" )
{
parseContentMetadata( e, capabilities.contents );
}
// Version 1.1
else if ( tagName == "ServiceIdentification" )
{
parseServiceIdentification( e, capabilities.serviceIdentification );
}
else if ( tagName == "OperationsMetadata" )
{
parseOperationsMetadata( e, capabilities.operationsMetadata );
}
else if ( tagName == "Contents" )
{
parseCoverageSummary( e, capabilities.contents );
}
}
n = n.nextSibling();
}
return true;
}
QDomElement QgsWcsCapabilities::firstChild( const QDomElement &element, const QString & name )
{
QDomNode n1 = element.firstChild();
while ( !n1.isNull() )
{
QDomElement el = n1.toElement();
if ( !el.isNull() )
{
QString tagName = stripNS( el.tagName() );
if ( tagName == name )
{
QgsDebugMsg( name + " found" );
return el;
}
}
n1 = n1.nextSibling();
}
QgsDebugMsg( name + " not found" );
return QDomElement();
}
QString QgsWcsCapabilities::firstChildText( const QDomElement &element, const QString & name )
{
QDomElement el = firstChild( element, name );
if ( !el.isNull() )
{
QgsDebugMsg( name + " : " + el.text() );
return el.text();
}
return QString();
}
// ------------------------ 1.0 ----------------------------------------------
void QgsWcsCapabilities::parseService( const QDomElement &e, QgsWcsServiceIdentification &serviceIdentification ) // 1.0
{
serviceIdentification.title = firstChildText( e, "name" );
serviceIdentification.abstract = firstChildText( e, "description" );
// 1.0 has also "label"
}
void QgsWcsCapabilities::parseCapability( QDomElement const & e, QgsWcsOperationsMetadata &operationsMetadata )
{
QDomElement requestElement = firstChild( e, "Request" );
QDomElement getCoverageElement = firstChild( requestElement, "GetCoverage" );
QDomElement dcpTypeElement = firstChild( getCoverageElement, "DCPType" );
QDomElement httpElement = firstChild( dcpTypeElement, "HTTP" );
QDomElement getElement = firstChild( httpElement, "Get" );
QDomElement onlineResourceElement = firstChild( getElement, "OnlineResource" );
operationsMetadata.getCoverage.dcp.http.get.xlinkHref = onlineResourceElement.attribute( "xlink:href" );
QgsDebugMsg( "getCoverage.dcp.http.get.xlinkHref = " + operationsMetadata.getCoverage.dcp.http.get.xlinkHref );
}
void QgsWcsCapabilities::parseContentMetadata( QDomElement const & e, QgsWcsCoverageSummary &coverageSummary )
{
QDomNode n1 = e.firstChild();
while ( !n1.isNull() )
{
QDomElement el = n1.toElement();
if ( !el.isNull() )
{
QString tagName = stripNS( el.tagName() );
if ( tagName == "CoverageOfferingBrief" )
{
QgsWcsCoverageSummary subCoverageSummary;
subCoverageSummary.described = false;
parseCoverageOfferingBrief( el, subCoverageSummary, &coverageSummary );
coverageSummary.coverageSummary.push_back( subCoverageSummary );
}
}
n1 = n1.nextSibling();
}
}
void QgsWcsCapabilities::parseCoverageOfferingBrief( QDomElement const & e, QgsWcsCoverageSummary &coverageSummary, QgsWcsCoverageSummary *parent )
{
QgsDebugMsg( "Entered" );
coverageSummary.orderId = ++mCoverageCount;
coverageSummary.identifier = firstChildText( e, "name" );
coverageSummary.title = firstChildText( e, "label" );
coverageSummary.abstract = firstChildText( e, "description" );
QDomElement lonLatEnvelopeElement = firstChild( e, "lonLatEnvelope" );
QDomNodeList posNodes = lonLatEnvelopeElement.elementsByTagName( "pos" );
QList<double> lon, lat;
for ( int i = 0; i < posNodes.size(); i++ )
{
QDomNode posNode = posNodes.at( i );
QString lonLatText = posNode.toElement().text();
QStringList lonLat = lonLatText.split( QRegExp( " +" ) );
if ( lonLat.size() != 2 )
{
QgsDebugMsg( "Cannot parse lonLatEnvelope: " + lonLatText );
continue;
}
double lo, la;
bool loOk, laOk;
lo = lonLat.value( 0 ).toDouble( &loOk );
la = lonLat.value( 1 ).toDouble( &laOk );
if ( loOk && laOk )
{
lon << lo;
lat << la;
}
else
{
QgsDebugMsg( "Cannot parse lonLatEnvelope: " + lonLatText );
}
}
if ( lon.size() == 2 )
{
double w, e, s, n;
w = qMin( lon[0], lon[1] );
e = qMax( lon[0], lon[1] );
n = qMax( lat[0], lat[1] );
s = qMin( lat[0], lat[1] );
coverageSummary.wgs84BoundingBox = QgsRectangle( w, s, e, n );
QgsDebugMsg( "wgs84BoundingBox = " + coverageSummary.wgs84BoundingBox.toString() );
}
if ( !coverageSummary.identifier.isEmpty() )
{
QgsDebugMsg( "add coverage " + coverageSummary.identifier + " to supported" );
mCoveragesSupported.push_back( coverageSummary );
}
if ( !coverageSummary.coverageSummary.empty() )
{
mCoverageParentIdentifiers[ coverageSummary.orderId ] = QStringList() << coverageSummary.identifier << coverageSummary.title << coverageSummary.abstract;
}
QgsDebugMsg( QString( "coverage orderId = %1 identifier = %2" ).arg( coverageSummary.orderId ).arg( coverageSummary.identifier ) );
}
bool QgsWcsCapabilities::convertToDom( QByteArray const &xml )
{
QgsDebugMsg( "Entered." );
// Convert completed document into a Dom
QString errorMsg;
int errorLine;
int errorColumn;
bool contentSuccess = mCapabilitiesDom.setContent( xml, false, &errorMsg, &errorLine, &errorColumn );
if ( !contentSuccess )
{
mErrorTitle = tr( "Dom Exception" );
mErrorFormat = "text/plain";
mError = tr( "Could not get WCS capabilities: %1 at line %2 column %3\nThis is probably due to an incorrect WCS Server URL.\nResponse was:\n\n%4" )
.arg( errorMsg )
.arg( errorLine )
.arg( errorColumn )
.arg( QString( xml ) );
QgsLogger::debug( "Dom Exception: " + mError );
return false;
}
return true;
}
bool QgsWcsCapabilities::parseDescribeCoverageDom( QByteArray const &xml, QgsWcsCoverageSummary *coverage )
{
QgsDebugMsg( "coverage->identifier = " + coverage->identifier );
if ( ! convertToDom( xml ) ) return false;
QDomElement docElem = mCapabilitiesDom.documentElement();
QgsDebugMsg( "testing tagName " + docElem.tagName() );
QString tagName = stripNS( docElem.tagName() );
if ( tagName != "CoverageDescription" )
{
mErrorTitle = tr( "Dom Exception" );
mErrorFormat = "text/plain";
mError = tr( "Could not get WCS capabilities in the expected format (DTD): no %1 found.\nThis might be due to an incorrect WCS Server URL.\nTag:%3\nResponse was:\n%4" )
.arg( "CoverageDescription" )
.arg( docElem.tagName() )
.arg( QString( xml ) );
QgsLogger::debug( "Dom Exception: " + mError );
return false;
}
QDomElement coverageOfferingElement = firstChild( docElem, "CoverageOffering" );
if ( coverageOfferingElement.isNull() ) return false;
QDomElement supportedCRSsElement = firstChild( coverageOfferingElement, "supportedCRSs" );
QDomNode n1 = supportedCRSsElement.firstChild();
while ( !n1.isNull() )
{
QDomElement el = n1.toElement();
if ( !el.isNull() )
{
QString tagName = stripNS( el.tagName() );
if ( tagName == "requestResponseCRSs" )
{
coverage->supportedCrs << el.text();
}
}
n1 = n1.nextSibling();
}
QgsDebugMsg( "supportedCrs = " + coverage->supportedCrs.join( "," ) );
QDomElement supportedFormatsElement = firstChild( coverageOfferingElement, "supportedFormats" );
n1 = supportedFormatsElement.firstChild();
while ( !n1.isNull() )
{
QDomElement el = n1.toElement();
if ( !el.isNull() )
{
QString tagName = stripNS( el.tagName() );
if ( tagName == "formats" )
{
// may be GTiff, GeoTIFF, TIFF, GIF, ....
coverage->supportedFormat << el.text();
}
}
n1 = n1.nextSibling();
}
QgsDebugMsg( "supportedFormat = " + coverage->supportedFormat.join( "," ) );
coverage->described = true;
return true;
}
// ------------------------ 1.1 ----------------------------------------------
void QgsWcsCapabilities::parseServiceIdentification( const QDomElement &e, QgsWcsServiceIdentification &serviceIdentification ) // 1.1
{
serviceIdentification.title = firstChildText( e, "Title" );
serviceIdentification.abstract = firstChildText( e, "Abstract" );
}
void QgsWcsCapabilities::parseHttp( QDomElement const & e, QgsWcsHTTP& http )
{
http.get.xlinkHref = firstChild( e, "Get" ).attribute( "xlink:href" );
QgsDebugMsg( "http.get.xlinkHref = " + http.get.xlinkHref );
}
void QgsWcsCapabilities::parseDcp( QDomElement const & e, QgsWcsDCP& dcp )
{
QDomElement el = firstChild( e, "HTTP" );
parseHttp( el, dcp.http );
}
void QgsWcsCapabilities::parseOperation( QDomElement const & e, QgsWcsOperation& operation )
{
QDomElement el = firstChild( e, "DCP" );
parseDcp( el, operation.dcp );
}
void QgsWcsCapabilities::parseOperationsMetadata( QDomElement const & e, QgsWcsOperationsMetadata &operationsMetadata )
{
QDomNode n1 = e.firstChild();
while ( !n1.isNull() )
{
QDomElement el = n1.toElement();
if ( !el.isNull() )
{
QString tagName = stripNS( el.tagName() );
if ( tagName == "Operation" && el.attribute( "name" ) == "GetCoverage" )
{
parseOperation( el, operationsMetadata.getCoverage );
}
}
n1 = n1.nextSibling();
}
}
void QgsWcsCapabilities::parseCoverageSummary( QDomElement const & e, QgsWcsCoverageSummary &coverageSummary, QgsWcsCoverageSummary *parent )
{
coverageSummary.orderId = ++mCoverageCount;
coverageSummary.identifier = firstChildText( e, "Identifier" );
coverageSummary.title = firstChildText( e, "Title" );
coverageSummary.abstract = firstChildText( e, "Abstract" );
QDomNode n1 = e.firstChild();
while ( !n1.isNull() )
{
QDomElement el = n1.toElement();
if ( !el.isNull() )
{
QString tagName = stripNS( el.tagName() );
QgsDebugMsg( tagName + " : " + el.text() );
if ( tagName == "SupportedFormat" )
{
// image/tiff, ...
coverageSummary.supportedFormat << el.text();
}
else if ( tagName == "SupportedCRS" )
{
// TODO: SupportedCRS may be URL referencing a document
// URN format: urn:ogc:def:objectType:authority:version:code
// URN example: urn:ogc:def:crs:EPSG::4326
QStringList urn = el.text().split( ":" );
if ( urn.size() == 7 )
{
coverageSummary.supportedCrs << urn.value( 4 ) + ":" + urn.value( 6 );
}
}
else if ( tagName == "WGS84BoundingBox" )
{
QDomElement wBoundLongitudeElem, eBoundLongitudeElem, sBoundLatitudeElem, nBoundLatitudeElem;
QStringList lower = n1.namedItem( "ows:LowerCorner" ).toElement().text().split( QRegExp( " +" ) );
QStringList upper = n1.namedItem( "ows:UpperCorner" ).toElement().text().split( QRegExp( " +" ) );
double w, e, s, n;
bool wOk, eOk, sOk, nOk;
w = lower.value( 0 ).toDouble( &wOk );
s = lower.value( 1 ).toDouble( &sOk );
e = upper.value( 0 ).toDouble( &eOk );
n = upper.value( 1 ).toDouble( &nOk );
if ( wOk && eOk && sOk && nOk )
{
coverageSummary.wgs84BoundingBox = QgsRectangle( w, s, e, n );
}
}
}
n1 = n1.nextSibling();
}
// We collected params to be inherited, do children
n1 = e.firstChild();
while ( !n1.isNull() )
{
QDomElement el = n1.toElement();
if ( !el.isNull() )
{
QString tagName = stripNS( el.tagName() );
if ( tagName == "CoverageSummary" )
{
QgsDebugMsg( " Nested coverage." );
QgsWcsCoverageSummary subCoverageSummary;
// Inherit
subCoverageSummary.supportedCrs = coverageSummary.supportedCrs;
subCoverageSummary.supportedFormat = coverageSummary.supportedFormat;
parseCoverageSummary( el, subCoverageSummary, &coverageSummary );
coverageSummary.coverageSummary.push_back( subCoverageSummary );
}
}
n1 = n1.nextSibling();
}
if ( parent && parent->orderId > 1 ) // ignore Contents to put them on top level
{
QgsDebugMsg( QString( "coverage orderId = %1 identifier = %2 has parent %3" ).arg( coverageSummary.orderId ).arg( coverageSummary.identifier ).arg( parent->orderId ) );
mCoverageParents[ coverageSummary.orderId ] = parent->orderId;
}
if ( !coverageSummary.identifier.isEmpty() )
{
QgsDebugMsg( "add coverage " + coverageSummary.identifier + " to supported" );
mCoveragesSupported.push_back( coverageSummary );
}
if ( !coverageSummary.coverageSummary.empty() )
{
mCoverageParentIdentifiers[ coverageSummary.orderId ] = QStringList() << coverageSummary.identifier << coverageSummary.title << coverageSummary.abstract;
}
QgsDebugMsg( QString( "coverage orderId = %1 identifier = %2" ).arg( coverageSummary.orderId ).arg( coverageSummary.identifier ) );
}
void QgsWcsCapabilities::coverageParents( QMap<int, int> &parents, QMap<int, QStringList> &parentNames ) const
{
parents = mCoverageParents;
parentNames = mCoverageParentIdentifiers;
}
QString QgsWcsCapabilities::lastErrorTitle()
{
return mErrorTitle;
}
QString QgsWcsCapabilities::lastError()
{
QgsDebugMsg( "returning '" + mError + "'." );
return mError;
}
QString QgsWcsCapabilities::lastErrorFormat()
{
return mErrorFormat;
}
void QgsWcsCapabilities::setAuthorization( QNetworkRequest &request ) const
{
QgsDebugMsg( "entered" );
if ( mUri.hasParam( "username" ) && mUri.hasParam( "password" ) )
{
QgsDebugMsg( "setAuthorization " + mUri.param( "username" ) );
request.setRawHeader( "Authorization", "Basic " + QString( "%1:%2" ).arg( mUri.param( "username" ) ).arg( mUri.param( "password" ) ).toAscii().toBase64() );
}
}
void QgsWcsCapabilities::showMessageBox( const QString& title, const QString& text )
{
QgsMessageOutput *message = QgsMessageOutput::createMessageOutput();
message->setTitle( title );
message->setMessage( text, QgsMessageOutput::MessageText );
message->showMessage();
}
QgsWcsCoverageSummary* QgsWcsCapabilities::coverageSummary( QString const & theIdentifier, QgsWcsCoverageSummary* parent )
{
//QgsDebugMsg( "theIdentifier = " + theIdentifier );
if ( !parent )
{
parent = &( mCapabilities.contents );
}
//foreach( const QgsWcsCoverageSummary &c, parent->coverageSummary )
for ( QVector<QgsWcsCoverageSummary>::iterator c = parent->coverageSummary.begin(); c != parent->coverageSummary.end(); ++c )
{
//QgsDebugMsg( "c->identifier = " + c->identifier );
if ( c->identifier == theIdentifier )
{
return c;
}
else
{
// search sub coverages
QgsWcsCoverageSummary * sc = coverageSummary( theIdentifier, c );
if ( sc )
{
return sc;
}
}
}
return 0;
}

View File

@ -0,0 +1,362 @@
/***************************************************************************
qgswcscapabilities.h - WCS capabilities
-------------------
begin : 17 Mar, 2005
copyright : (C) 2005 by Brendan Morley
email : morb at ozemail dot com dot au
wcs : 4/2012 Radim Blazek, based on qgswmsprovider.h
***************************************************************************/
/***************************************************************************
* *
* 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 QGSWCSCAPABILITIES_H
#define QGSWCSCAPABILITIES_H
//#include "qgsrasterdataprovider.h"
#include "qgsdatasourceuri.h"
#include "qgsrectangle.h"
#include <QString>
#include <QStringList>
#include <QDomElement>
#include <QMap>
#include <QVector>
#include <QUrl>
class QgsCoordinateTransform;
class QNetworkAccessManager;
class QNetworkReply;
class QNetworkRequest;
/*
* The following structs reflect the WCS XML schema,
* as illustrated in ... the Web Coverage Service standard, version x.x xxxx-xx-xx.
*/
/** Get Property structure */
struct QgsWcsGet
{
QString xlinkHref;
};
/** HTTP Property structure */
struct QgsWcsHTTP
{
QgsWcsGet get;
};
/** DCP Type Property structure */
struct QgsWcsDCP
{
QgsWcsHTTP http;
};
/** Version parameter */
struct QgsWcsVersion
{
QStringList allowedValues;
};
/** Operation type structure */
struct QgsWcsOperation
{
QgsWcsVersion version;
QgsWcsDCP dcp;
};
/** OperationsMetadata */
struct QgsWcsOperationsMetadata
{
QgsWcsOperation getCoverage;
};
/** ServiceerviceIdentification structure */
struct QgsWcsServiceIdentification
{
QString title;
QString abstract;
};
/** CoverageSummary structure */
struct QgsWcsCoverageSummary
{
int orderId;
QString identifier;
QString title;
QString abstract;
QStringList supportedCrs;
QStringList supportedFormat;
QgsRectangle wgs84BoundingBox;
QVector<QgsWcsCoverageSummary> coverageSummary;
bool described; // 1.0
};
/** Contents structure */
/*
struct QgsWcsContents
{
QStringList supportedCrs;
QStringList supportedFormat;
QVector<QgsWcsCoverageSummary> coverageSummary;
};
*/
/** Capability Property structure */
struct QgsWcsCapabilitiesProperty
{
QString version;
QgsWcsServiceIdentification serviceIdentification;
QgsWcsOperationsMetadata operationsMetadata;
// QgsWcsContents contents;
// using QgsWcsCoverageSummary for contents for simplification
QgsWcsCoverageSummary contents;
};
/**
\brief Data provider for OGC WCS layers.
*/
class QgsWcsCapabilities : public QObject
{
Q_OBJECT
public:
/**
* Constructor for the provider.
*
* \param uri HTTP URL of the Web Server. If needed a proxy will be used
* otherwise we contact the host directly.
*
*/
QgsWcsCapabilities( QgsDataSourceURI const & theUri );
QgsWcsCapabilities( );
//! Destructor
~QgsWcsCapabilities();
void setUri( QgsDataSourceURI const &theUri );
QgsWcsCapabilitiesProperty capabilities();
/**
* \brief Returns a list of the supported layers of the WCS server
*
* \param[out] layers The list of layers will be placed here.
*
* \retval false if the layers could not be retrieved or parsed -
* see lastError() for more info
*/
bool supportedCoverages( QVector<QgsWcsCoverageSummary> &coverageSummary );
/**
* \brief Returns a map for the hierarchy of layers
*/
void coverageParents( QMap<int, int> &parents, QMap<int, QStringList> &parentNames ) const;
//! Get coverage summare for identifier
QgsWcsCoverageSummary * coverageSummary( QString const & theIdentifier, QgsWcsCoverageSummary* parent = 0 );
/**
* \brief Prepare the URI so that we can later simply append param=value
* \param uri uri to prepare
* \retval prepared uri
*/
static QString prepareUri( QString uri );
/**Returns the GetCoverage url
* @added in 1.5
*/
QString getCoverageUrl() const;
//! Send request to server
bool sendRequest( QString const & url );
/** Get additional coverage info from server. Version 1.0 GetCapabilities
* response does not contain all info (CRS, formats).
*/
bool describeCoverage( QString const &identifier, bool forceRefresh = false );
bool convertToDom( QByteArray const &xml );
bool parseDescribeCoverageDom( QByteArray const &xml, QgsWcsCoverageSummary *coverage );
//! set authorization header
void setAuthorization( QNetworkRequest &request ) const;
/**
* \brief Returns the caption error text for the last error in this provider
*
* If an operation returns 0 (e.g. draw()), this function
* returns the text of the error associated with the failure.
* Interactive users of this provider can then, for example,
* call a QMessageBox to display the contents.
*/
QString lastErrorTitle();
/**
* \brief Returns the verbose error text for the last error in this provider
*
* If an operation returns 0 (e.g. draw()), this function
* returns the text of the error associated with the failure.
* Interactive users of this provider can then, for example,
* call a QMessageBox to display the contents.
*/
QString lastError();
/**
* \brief Returns the format of the error message (text or html)
*/
QString lastErrorFormat();
signals:
/** \brief emit a signal to notify of a progress event */
void progressChanged( int theProgress, int theTotalSteps );
/** \brief emit a signal to be caught by qgisapp and display a msg on status bar */
void statusChanged( QString const & theStatusQString );
private slots:
void capabilitiesReplyFinished();
void capabilitiesReplyProgress( qint64, qint64 );
private:
void showMessageBox( const QString &title, const QString &text );
//! Get tag name without namespace
QString stripNS( const QString &name );
//! Get text of first child of specified name, NS is ignored
QString firstChildText( const QDomElement &element, const QString &name );
//! Get first child of specified name, NS is ignored
QDomElement firstChild( const QDomElement &element, const QString &name );
/**
* \brief Retrieve and parse the (cached) Capabilities document from the server
*
* \param forceRefresh if true, ignores any previous response cached in memory
* and always contact the server for a new copy.
* \retval false if the capabilities document could not be retrieved or parsed -
* see lastError() for more info
*
* When this returns, "layers" will make sense.
*
* TODO: Make network-timeout tolerant
*/
bool retrieveServerCapabilities( bool forceRefresh = false );
//! \return false if the capabilities document could not be parsed - see lastError() for more info
bool parseCapabilitiesDom( QByteArray const &xml, QgsWcsCapabilitiesProperty &capabilities );
// ------------- 1.0 --------------------
//! parse the WCS Service XML element
void parseService( QDomElement const &e, QgsWcsServiceIdentification &serviceIdentification );
//! parse the WCS Capability XML element
void parseCapability( QDomElement const &e, QgsWcsOperationsMetadata &operationsMetadata );
//! parse the WCS Layer XML element
void parseContentMetadata( QDomElement const &e, QgsWcsCoverageSummary &coverageSummary );
//! parse the WCS Layer XML element
void parseCoverageOfferingBrief( QDomElement const &e, QgsWcsCoverageSummary &coverageSummary,
QgsWcsCoverageSummary *parent = 0 );
// ------------- 1.1 --------------------
//! parse the WCS ServiceIdentificatio XML element
void parseServiceIdentification( QDomElement const &e, QgsWcsServiceIdentification &serviceIdentification );
//! parse the WCS OperationsMetadata XML element
void parseOperationsMetadata( QDomElement const &e, QgsWcsOperationsMetadata &operationsMetadata );
//! parse the WCS GetCoverage
void parseOperation( QDomElement const & e, QgsWcsOperation& operation );
//! parse the WCS HTTP XML element
void parseHttp( QDomElement const &e, QgsWcsHTTP &http );
//! parse the WCS DCPType XML element
void parseDcp( QDomElement const &e, QgsWcsDCP &dcp );
//! parse the WCS Layer XML element
void parseCoverageSummary( QDomElement const &e, QgsWcsCoverageSummary &coverageSummary,
QgsWcsCoverageSummary *parent = 0 );
//! Data source uri
QgsDataSourceURI mUri;
//! Response capabilities version
QString mVersion;
/**
* Capabilities of the WCS Server (raw)
*/
QByteArray mCapabilitiesResponse;
/**
* Capabilities of the WCS Server
*/
QDomDocument mCapabilitiesDom;
/**
* Last Service Exception Report from the WCS Server
*/
QDomDocument mServiceExceptionReportDom;
/**
* Parsed capabilities of the WCS Server
*/
QgsWcsCapabilitiesProperty mCapabilities;
/**
* layers hosted by the WCS Server
* This vector contain initial copies which are not updated by coverageSummary()!!!
*/
QVector<QgsWcsCoverageSummary> mCoveragesSupported;
/**
* The reply to the capabilities request
*/
QNetworkReply *mCapabilitiesReply;
/**
* The error caption associated with the last WCS error.
*/
QString mErrorTitle;
/**
* The error message associated with the last WCS error.
*/
QString mError;
/** The mime type of the message
*/
QString mErrorFormat;
int mCoverageCount;
//! number of layers and parents
QMap<int, int> mCoverageParents;
QMap<int, QStringList> mCoverageParentIdentifiers;
//! Username for basic http authentication
QString mUserName;
//! Password for basic http authentication
QString mPassword;
};
#endif
// ENDS

View File

@ -0,0 +1,239 @@
/***************************************************************************
qgswcssourceselect.cpp - selector for WCS
-------------------
begin : 04 2012
copyright :
original : (C) 2012 Radim Blazek
***************************************************************************/
/***************************************************************************
* *
* 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 "qgis.h"
#include "qgslogger.h"
#include "qgsgdalprovider.h"
#include "qgswcssourceselect.h"
#include "qgswcscapabilities.h"
#include "qgsnumericsortlistviewitem.h"
#include <QWidget>
#define CPL_SUPRESS_CPLUSPLUS
#include <gdal.h>
#if defined(GDAL_VERSION_NUM) && GDAL_VERSION_NUM >= 1800
#define TO8F(x) (x).toUtf8().constData()
#define FROM8(x) QString::fromUtf8(x)
#else
#define TO8F(x) QFile::encodeName( x ).constData()
#define FROM8(x) QString::fromLocal8Bit(x)
#endif
QgsWCSSourceSelect::QgsWCSSourceSelect( QWidget * parent, Qt::WFlags fl, bool managerMode, bool embeddedMode )
: QgsOWSSourceSelect( "WCS", parent, fl, managerMode, embeddedMode )
{
// Hide irrelevant widgets
mWMSGroupBox->hide();
mLayersTab->layout()->removeWidget( mWMSGroupBox );
mTabWidget->removeTab( mTabWidget->indexOf( mLayerOrderTab ) );
mTabWidget->removeTab( mTabWidget->indexOf( mTilesetsTab ) );
mTabWidget->removeTab( mTabWidget->indexOf( mSearchTab ) );
mAddDefaultButton->hide();
mLayersTreeWidget->setSelectionMode( QAbstractItemView::SingleSelection );
}
QgsWCSSourceSelect::~QgsWCSSourceSelect()
{
}
void QgsWCSSourceSelect::populateLayerList( )
{
QgsDebugMsg( "entered" );
mLayersTreeWidget->clear();
mCapabilities.setUri( mUri );
if ( !mCapabilities.lastError().isEmpty() )
{
showError( mCapabilities.lastErrorTitle(), mCapabilities.lastErrorFormat(), mCapabilities.lastError() );
return;
}
QVector<QgsWcsCoverageSummary> coverages;
if ( !mCapabilities.supportedCoverages( coverages ) )
return;
QMap<int, QgsNumericSortTreeWidgetItem *> items;
QMap<int, int> coverageParents;
QMap<int, QStringList> coverageParentNames;
mCapabilities.coverageParents( coverageParents, coverageParentNames );
mLayersTreeWidget->setSortingEnabled( true );
int coverageAndStyleCount = -1;
for ( QVector<QgsWcsCoverageSummary>::iterator coverage = coverages.begin();
coverage != coverages.end();
coverage++ )
{
QgsDebugMsg( QString( "coverage orderId = %1 identifier = %2" ).arg( coverage->orderId ).arg( coverage->identifier ) );
QgsNumericSortTreeWidgetItem *lItem = createItem( coverage->orderId, QStringList() << coverage->identifier << coverage->title << coverage->abstract, items, coverageAndStyleCount, coverageParents, coverageParentNames );
lItem->setData( 0, Qt::UserRole + 0, coverage->identifier );
lItem->setData( 0, Qt::UserRole + 1, "" );
// Make only leaves selectable
if ( coverageParents.keys( coverage->orderId ).size() > 0 )
{
lItem->setFlags( Qt::ItemIsEnabled );
}
}
mLayersTreeWidget->sortByColumn( 0, Qt::AscendingOrder );
// If we got some coverages, let the user add them to the map
if ( mLayersTreeWidget->topLevelItemCount() == 1 )
{
mLayersTreeWidget->expandItem( mLayersTreeWidget->topLevelItem( 0 ) );
}
}
QString QgsWCSSourceSelect::selectedIdentifier()
{
QList<QTreeWidgetItem *> selectionList = mLayersTreeWidget->selectedItems();
if ( selectionList.size() < 1 ) return QString(); // should not happen
QString identifier = selectionList.value( 0 )->data( 0, Qt::UserRole + 0 ).toString();
QgsDebugMsg( " identifier = " + identifier );
return identifier;
}
void QgsWCSSourceSelect::addClicked( )
{
QgsDebugMsg( "entered" );
QgsDataSourceURI uri = mUri;
QString identifier = selectedIdentifier();
if ( identifier.isEmpty() ) { return; }
uri.setParam( "identifier", identifier );
// Set crs only if necessary (multiple offered), so that we can decide in the
// provider if WCS 1.0 with RESPONSE_CRS has to be used. Not perfect, they can
// add more CRS in future and URI will be saved in project without any.
if ( selectedLayersCRSs().size() > 1 )
{
uri.setParam( "crs", selectedCRS() );
}
QgsDebugMsg( "selectedFormat = " + selectedFormat() );
if ( !selectedFormat().isEmpty() )
{
uri.setParam( "format", selectedFormat() );
}
emit addRasterLayer( uri.encodedUri(), identifier, "gdal" );
}
void QgsWCSSourceSelect::on_mLayersTreeWidget_itemSelectionChanged()
{
QgsDebugMsg( "entered" );
QString identifier = selectedIdentifier();
if ( identifier.isEmpty() ) { return; }
mCapabilities.describeCoverage( identifier ); // 1.0 get additional info
populateFormats();
populateCRS();
updateButtons();
mAddButton->setEnabled( true );
}
void QgsWCSSourceSelect::updateButtons()
{
QgsDebugMsg( "entered" );
if ( mLayersTreeWidget->selectedItems().isEmpty() )
{
showStatusMessage( tr( "Select a layer" ) );
}
else
{
if ( selectedCRS().isEmpty() )
{
showStatusMessage( tr( "No CRS selected" ) );
}
}
mAddButton->setEnabled( !mLayersTreeWidget->selectedItems().isEmpty() && !selectedCRS().isEmpty() && !selectedFormat().isEmpty() );
}
QList<QgsOWSSupportedFormat> QgsWCSSourceSelect::providerFormats()
{
QgsDebugMsg( "entered" );
QList<QgsOWSSupportedFormat> formats;
QMap<QString, QString> mimes = QgsGdalProvider::supportedMimes();
foreach( QString mime, mimes.keys() )
{
QgsOWSSupportedFormat format = { mime, mimes.value( mime ) };
// prefer tiff
if ( mime == "image/tiff" )
{
formats.prepend( format );
}
else
{
formats.append( format );
}
}
return formats;
}
QStringList QgsWCSSourceSelect::selectedLayersFormats()
{
QgsDebugMsg( "entered" );
QString identifier = selectedIdentifier();
if ( identifier.isEmpty() ) { return QStringList(); }
QgsWcsCoverageSummary * c = mCapabilities.coverageSummary( identifier );
if ( !c ) { return QStringList(); }
QgsDebugMsg( "supportedFormat = " + c->supportedFormat.join( "," ) );
return c->supportedFormat;
}
QStringList QgsWCSSourceSelect::selectedLayersCRSs()
{
QgsDebugMsg( "entered" );
QString identifier = selectedIdentifier();
if ( identifier.isEmpty() ) { return QStringList(); }
QgsWcsCoverageSummary * c = mCapabilities.coverageSummary( identifier );
if ( !c ) { return QStringList(); }
return c->supportedCrs;
}
void QgsWCSSourceSelect::enableLayersForCrs( QTreeWidgetItem *item )
{
// TODO: I am not convinced to disable layers according to selected CRS
}

View File

@ -0,0 +1,83 @@
/***************************************************************************
qgswcssourceselect.h - selector for WCS layers
-------------------
begin : 3 April 2005
original : (C) 2005 by Brendan Morley email : morb at ozemail dot com dot au
wms search : (C) 2009 Mathias Walker <mwa at sourcepole.ch>, Sourcepole AG
generalized : (C) 2012 Radim Blazek, based on qgsowsconnection.h
***************************************************************************/
/***************************************************************************
* *
* 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 QGSWCSSOURCESELECT_H
#define QGSWCSSOURCESELECT_H
#include "qgsowssourceselect.h"
#include "qgsdatasourceuri.h"
#include "qgisgui.h"
#include "qgscontexthelp.h"
#include "qgswcscapabilities.h"
#include "qgsdataprovider.h"
#include <QStringList>
#include <QPushButton>
class QgisApp;
class QgsDataProvider;
class QButtonGroup;
class QgsNumericSortTreeWidgetItem;
class QDomDocument;
class QDomElement;
/*!
* \brief Dialog to create connections and add layers from WMS, WFS, WCS etc.
*
* This dialog allows the user to define and save connection information
* for WMS servers, etc.
*
* The user can then connect and add
* layers from the WMS server to the map canvas.
*/
class QgsWCSSourceSelect : public QgsOWSSourceSelect
{
Q_OBJECT
public:
//! Constructor
QgsWCSSourceSelect( QWidget *parent = 0, Qt::WFlags fl = QgisGui::ModalDialogFlags, bool managerMode = false, bool embeddedMode = false );
//! Destructor
~QgsWCSSourceSelect();
public slots:
signals:
void addRasterLayer( QString const & rasterLayerPath,
QString const & baseName,
QString const & providerKey );
private:
QgsWcsCapabilities mCapabilities;
QString selectedIdentifier();
// QgsWcsCapabilities virtual methods
void populateLayerList( );
void addClicked();
void on_mLayersTreeWidget_itemSelectionChanged();
void enableLayersForCrs( QTreeWidgetItem *item );
void updateButtons();
QList<QgsOWSSupportedFormat> providerFormats();
QStringList selectedLayersFormats();
QStringList selectedLayersCRSs();
};
#endif // QGSWCSSOURCESELECT_H

View File

@ -0,0 +1,26 @@
SET(OWS_SRCS
qgsowsprovider.cpp
qgsowsdataitems.cpp
)
SET(OWS_MOC_HDRS
qgsowsprovider.h
qgsowsdataitems.h
)
INCLUDE_DIRECTORIES (
../../core
../../gui
${CMAKE_CURRENT_BINARY_DIR}/../../ui
)
QT4_WRAP_CPP(OWS_MOC_SRCS ${OWS_MOC_HDRS})
ADD_LIBRARY (owsprovider MODULE ${OWS_SRCS} ${OWS_MOC_SRCS})
TARGET_LINK_LIBRARIES (owsprovider
qgis_core
qgis_gui
)
INSTALL(TARGETS owsprovider
RUNTIME DESTINATION ${QGIS_PLUGIN_DIR}
LIBRARY DESTINATION ${QGIS_PLUGIN_DIR})

View File

@ -0,0 +1,239 @@
#include "qgsproviderregistry.h"
#include "qgsowsdataitems.h"
#include "qgsowsprovider.h"
#include "qgslogger.h"
#include "qgsdatasourceuri.h"
//#include "qgsowssourceselect.h"
#include "qgsowsconnection.h"
#include "qgsnewhttpconnection.h"
#include <QFileInfo>
// ---------------------------------------------------------------------------
QgsOWSConnectionItem::QgsOWSConnectionItem( QgsDataItem* parent, QString name, QString path )
: QgsDataCollectionItem( parent, name, path )
{
mIcon = QIcon( getThemePixmap( "mIconConnect.png" ) );
}
QgsOWSConnectionItem::~QgsOWSConnectionItem()
{
}
QVector<QgsDataItem*> QgsOWSConnectionItem::createChildren()
{
QgsDebugMsg( "Entered" );
QVector<QgsDataItem*> children;
QVector<QgsDataItem*> serviceItems;
int layerCount;
// Try to open with WMS,WFS,WCS
foreach( QString key, QStringList() << "wms" << "WFS" << "gdal" )
{
QgsDebugMsg( "Add connection for provider " + key );
QLibrary *library = QgsProviderRegistry::instance()->providerLibrary( key );
if ( !library ) continue;
dataItem_t * dItem = ( dataItem_t * ) cast_to_fptr( library->resolve( "dataItem" ) );
if ( !dItem )
{
QgsDebugMsg( library->fileName() + " does not have dataItem" );
continue;
}
QgsDataItem *item = dItem( mPath, this ); // empty path -> top level
if ( !item ) continue;
layerCount += item->rowCount();
if ( item->rowCount() > 0 )
{
QgsDebugMsg( "Add new item : " + item->name() );
serviceItems.append( item );
}
else
{
//delete item;
}
}
foreach( QgsDataItem* item, serviceItems )
{
QgsDebugMsg( QString( "serviceItems.size = %1 layerCount = %2 rowCount = %3" ).arg( serviceItems.size() ).arg( layerCount ).arg( item->rowCount() ) );
if ( serviceItems.size() == 1 || layerCount <= 30 || item->rowCount() <= 10 )
{
// Add layers directly to OWS connection
foreach( QgsDataItem* subItem, item->children() )
{
item->removeChildItem( subItem );
subItem->setParent( this );
children.append( subItem );
}
delete item;
}
else // Add service
{
children.append( item );
}
}
return children;
}
bool QgsOWSConnectionItem::equal( const QgsDataItem *other )
{
if ( type() != other->type() )
{
return false;
}
const QgsOWSConnectionItem *o = dynamic_cast<const QgsOWSConnectionItem *>( other );
return ( mPath == o->mPath && mName == o->mName );
}
QList<QAction*> QgsOWSConnectionItem::actions()
{
QList<QAction*> lst;
QAction* actionEdit = new QAction( tr( "Edit..." ), this );
connect( actionEdit, SIGNAL( triggered() ), this, SLOT( editConnection() ) );
lst.append( actionEdit );
QAction* actionDelete = new QAction( tr( "Delete" ), this );
connect( actionDelete, SIGNAL( triggered() ), this, SLOT( deleteConnection() ) );
lst.append( actionDelete );
return lst;
}
void QgsOWSConnectionItem::editConnection()
{
/*
QgsNewHttpConnection nc( 0, "/Qgis/connections-ows/", mName );
if ( nc.exec() )
{
// the parent should be updated
mParent->refresh();
}
*/
}
void QgsOWSConnectionItem::deleteConnection()
{
/*
QgsOWSConnection::deleteConnection( "OWS", mName );
// the parent should be updated
mParent->refresh();
*/
}
// ---------------------------------------------------------------------------
QgsOWSRootItem::QgsOWSRootItem( QgsDataItem* parent, QString name, QString path )
: QgsDataCollectionItem( parent, name, path )
{
mIcon = QIcon( getThemePixmap( "mIconOws.png" ) );
populate();
}
QgsOWSRootItem::~QgsOWSRootItem()
{
}
QVector<QgsDataItem*>QgsOWSRootItem::createChildren()
{
QgsDebugMsg( "Entered" );
QVector<QgsDataItem*> connections;
// Combine all WMS,WFS,WCS connections
QMap<QString, QStringList> uris;
foreach( QString service, QStringList() << "WMS" << "WFS" << "WCS" )
{
foreach( QString connName, QgsOWSConnection::connectionList( service ) )
{
QgsOWSConnection connection( service, connName );
QString encodedUri = connection.uri().encodedUri();
QStringList labels = uris.value( encodedUri );
if ( !labels.contains( connName ) )
{
labels << connName;
}
uris[encodedUri] = labels;
}
}
foreach( QString encodedUri, uris.keys() )
{
QgsDataItem * conn = new QgsOWSConnectionItem( this, uris.value( encodedUri ).join( " / " ), encodedUri );
connections.append( conn );
}
return connections;
}
QList<QAction*> QgsOWSRootItem::actions()
{
QList<QAction*> lst;
/*
QAction* actionNew = new QAction( tr( "New Connection..." ), this );
connect( actionNew, SIGNAL( triggered() ), this, SLOT( newConnection() ) );
lst.append( actionNew );
*/
return lst;
}
QWidget * QgsOWSRootItem::paramWidget()
{
/*
QgsOWSSourceSelect *select = new QgsOWSSourceSelect( 0, 0, true, true );
connect( select, SIGNAL( connectionsChanged() ), this, SLOT( connectionsChanged() ) );
return select;
*/
return 0;
}
void QgsOWSRootItem::connectionsChanged()
{
refresh();
}
void QgsOWSRootItem::newConnection()
{
/*
QgsNewHttpConnection nc( 0, "/Qgis/connections-ows/" );
if ( nc.exec() )
{
refresh();
}
*/
}
// ---------------------------------------------------------------------------
static QStringList extensions = QStringList();
static QStringList wildcards = QStringList();
QGISEXTERN int dataCapabilities()
{
return QgsDataProvider::Net;
}
QGISEXTERN QgsDataItem * dataItem( QString thePath, QgsDataItem* parentItem )
{
if ( thePath.isEmpty() )
{
return new QgsOWSRootItem( parentItem, "OWS", "ows:" );
}
}
//QGISEXTERN QgsOWSSourceSelect * selectWidget( QWidget * parent, Qt::WFlags fl )
QGISEXTERN QDialog * selectWidget( QWidget * parent, Qt::WFlags fl )
{
//return new QgsOWSSourceSelect( parent, fl );
return 0;
}

View File

@ -0,0 +1,42 @@
#ifndef QGSOWSDATAITEMS_H
#define QGSOWSDATAITEMS_H
#include "qgsdataitem.h"
#include "qgsdatasourceuri.h"
class QgsOWSConnectionItem : public QgsDataCollectionItem
{
Q_OBJECT
public:
QgsOWSConnectionItem( QgsDataItem* parent, QString name, QString path );
~QgsOWSConnectionItem();
QVector<QgsDataItem*> createChildren();
virtual bool equal( const QgsDataItem *other );
virtual QList<QAction*> actions();
public slots:
void editConnection();
void deleteConnection();
};
class QgsOWSRootItem : public QgsDataCollectionItem
{
Q_OBJECT
public:
QgsOWSRootItem( QgsDataItem* parent, QString name, QString path );
~QgsOWSRootItem();
QVector<QgsDataItem*> createChildren();
virtual QList<QAction*> actions();
virtual QWidget * paramWidget();
public slots:
void connectionsChanged();
void newConnection();
};
#endif // QGSOWSDATAITEMS_H

View File

@ -0,0 +1,65 @@
/***************************************************************************
qgsowsprovider.cpp - OWS meta provider for WMS,WFS,WCS in browser
-------------------
begin : 4/2012
copyright : (C) 2010 by Radim Blazek
email : radim dot blazek 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 "qgslogger.h"
#include "qgsowsprovider.h"
#include "qgsconfig.h"
#include <QString>
static QString PROVIDER_KEY = "ows";
static QString PROVIDER_DESCRIPTION = "OWS meta provider";
QgsOwsProvider::QgsOwsProvider( QString const & uri )
: QgsDataProvider( uri )
{
}
QgsOwsProvider::~QgsOwsProvider()
{
}
QGISEXTERN QgsOwsProvider * classFactory( const QString *uri )
{
return new QgsOwsProvider( *uri );
}
QString QgsOwsProvider::name() const
{
return PROVIDER_KEY;
}
QString QgsOwsProvider::description() const
{
return PROVIDER_DESCRIPTION;
}
QGISEXTERN QString providerKey()
{
return PROVIDER_KEY;
}
QGISEXTERN QString description()
{
return PROVIDER_DESCRIPTION;
}
QGISEXTERN bool isProvider()
{
return true;
}

View File

@ -0,0 +1,66 @@
/***************************************************************************
qgsowsprovider.h - OWS meta provider for WMS,WFS,WCS in browser
-------------------
begin : 4/2012
copyright : (C) 2012 by Radim Blazek
email : radim dot blazek 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 QGSOWSPROVIDER_H
#define QGSOWSPROVIDER_H
#include "qgsdataprovider.h"
#include "qgscoordinatereferencesystem.h"
#include "qgsdataitem.h"
#include "qgsrectangle.h"
#include <QString>
/**
\brief Data provider for GDAL layers.
This provider implements the interface defined in the QgsDataProvider class
to provide access to spatial data residing in a GDAL layers.
*/
class QgsOwsProvider : public QgsDataProvider
{
Q_OBJECT
public:
/**
* Constructor for the provider.
*
* \param uri HTTP URL of the Web Server. If needed a proxy will be used
* otherwise we contact the host directly.
*
*/
QgsOwsProvider( QString const & uri = 0 );
//! Destructor
~QgsOwsProvider();
/* Pure virtuals */
QString name() const;
QString description() const;
QgsCoordinateReferenceSystem crs() { return QgsCoordinateReferenceSystem(); }
QgsRectangle extent() { return QgsRectangle(); }
bool isValid() { return false; }
};
#endif // QGSOWSPROVIDER_H

View File

@ -4,7 +4,7 @@
SET(WFS_SRCS
qgswfsprovider.cpp
qgswfsconnection.cpp
qgswfscapabilities.cpp
qgswfsdataitems.cpp
qgswfsdata.cpp
qgswfssourceselect.cpp
@ -13,7 +13,7 @@ SET(WFS_SRCS
SET (WFS_MOC_HDRS
qgswfsdata.h
qgswfsconnection.h
qgswfscapabilities.h
qgswfsdataitems.h
qgswfsprovider.h
qgswfssourceselect.h

View File

@ -1,5 +1,5 @@
/***************************************************************************
qgswfsconnection.cpp
qgswfscapabilities.cpp
---------------------
begin : October 2011
copyright : (C) 2011 by Martin Dobias
@ -12,7 +12,7 @@
* (at your option) any later version. *
* *
***************************************************************************/
#include "qgswfsconnection.h"
#include "qgswfscapabilities.h"
#include "qgsexpression.h"
#include "qgslogger.h"
#include "qgsnetworkaccessmanager.h"
@ -25,18 +25,25 @@
static const QString WFS_NAMESPACE = "http://www.opengis.net/wfs";
QgsWFSConnection::QgsWFSConnection( QString connName, QObject *parent ) :
QObject( parent ),
mConnName( connName ),
QgsWFSCapabilities::QgsWFSCapabilities( QString theUri ) :
//QObject( parent ),
//mConnName( connName ),
mCapabilitiesReply( 0 ),
mErrorCode( QgsWFSConnection::NoError )
mErrorCode( QgsWFSCapabilities::NoError )
{
mUri.setEncodedUri( theUri ),
QgsDebugMsg ( "theUri = " + theUri );
mBaseUrl = prepareUri ( mUri.param("url") );
QgsDebugMsg ( "mBaseUrl = " + mBaseUrl );
//find out the server URL
/*
QSettings settings;
QString key = "/Qgis/connections-wfs/" + mConnName + "/url";
mUri = settings.value( key ).toString();
QgsDebugMsg( QString( "url is: %1" ).arg( mUri ) );
//make a GetCapabilities request
//modify mUri to add '?' or '&' at the end if it is not already there
if ( !( mUri.contains( "?" ) ) )
@ -47,19 +54,34 @@ QgsWFSConnection::QgsWFSConnection( QString connName, QObject *parent ) :
{
mUri.append( "&" );
}
*/
}
QString QgsWFSConnection::uriGetCapabilities() const
QString QgsWFSCapabilities::prepareUri( QString uri )
{
return mUri + "SERVICE=WFS&REQUEST=GetCapabilities&VERSION=1.0.0";
if ( !uri.contains( "?" ) )
{
uri.append( "?" );
}
else if ( uri.right( 1 ) != "?" && uri.right( 1 ) != "&" )
{
uri.append( "&" );
}
return uri;
}
QString QgsWFSConnection::uriDescribeFeatureType( const QString& typeName ) const
QString QgsWFSCapabilities::uriGetCapabilities() const
{
return mUri + "SERVICE=WFS&REQUEST=DescribeFeatureType&VERSION=1.0.0&TYPENAME=" + typeName;
return mBaseUrl + "SERVICE=WFS&REQUEST=GetCapabilities&VERSION=1.0.0";
}
QString QgsWFSConnection::uriGetFeature( QString typeName, QString crsString, QString filter, QgsRectangle bBox ) const
QString QgsWFSCapabilities::uriDescribeFeatureType( const QString& typeName ) const
{
return mBaseUrl + "SERVICE=WFS&REQUEST=DescribeFeatureType&VERSION=1.0.0&TYPENAME=" + typeName;
}
QString QgsWFSCapabilities::uriGetFeature( QString typeName, QString crsString, QString filter, QgsRectangle bBox ) const
{
//get CRS
if ( !crsString.isEmpty() )
@ -103,11 +125,7 @@ QString QgsWFSConnection::uriGetFeature( QString typeName, QString crsString, QS
.arg( bBox.yMaximum(), 0, 'f' );
}
QString uri = mUri;
if ( !( uri.contains( "?" ) ) )
{
uri.append( "?" );
}
QString uri = mBaseUrl;
//add a wfs layer to the map
uri += "SERVICE=WFS&VERSION=1.0.0&REQUEST=GetFeature&TYPENAME=" + typeName + crsString + bBoxString + filterString;
@ -116,9 +134,9 @@ QString QgsWFSConnection::uriGetFeature( QString typeName, QString crsString, QS
}
void QgsWFSConnection::requestCapabilities()
void QgsWFSCapabilities::requestCapabilities()
{
mErrorCode = QgsWFSConnection::NoError;
mErrorCode = QgsWFSCapabilities::NoError;
mErrorMessage.clear();
QNetworkRequest request( uriGetCapabilities() );
@ -127,12 +145,12 @@ void QgsWFSConnection::requestCapabilities()
connect( mCapabilitiesReply, SIGNAL( finished() ), this, SLOT( capabilitiesReplyFinished() ) );
}
void QgsWFSConnection::capabilitiesReplyFinished()
void QgsWFSCapabilities::capabilitiesReplyFinished()
{
// handle network errors
if ( mCapabilitiesReply->error() != QNetworkReply::NoError )
{
mErrorCode = QgsWFSConnection::NetworkError;
mErrorCode = QgsWFSCapabilities::NetworkError;
mErrorMessage = mCapabilitiesReply->errorString();
emit gotCapabilities();
return;
@ -163,7 +181,7 @@ void QgsWFSConnection::capabilitiesReplyFinished()
QDomDocument capabilitiesDocument;
if ( !capabilitiesDocument.setContent( buffer, true, &capabilitiesDocError ) )
{
mErrorCode = QgsWFSConnection::XmlError;
mErrorCode = QgsWFSCapabilities::XmlError;
mErrorMessage = capabilitiesDocError;
emit gotCapabilities();
return;
@ -177,7 +195,7 @@ void QgsWFSConnection::capabilitiesReplyFinished()
QDomNode ex = doc.firstChild();
QString exc = ex.toElement().attribute( "exceptionCode", "Exception" );
QDomElement ext = ex.firstChild().toElement();
mErrorCode = QgsWFSConnection::ServerExceptionError;
mErrorCode = QgsWFSCapabilities::ServerExceptionError;
mErrorMessage = exc + ": " + ext.firstChild().nodeValue();
emit gotCapabilities();
return;
@ -240,31 +258,3 @@ void QgsWFSConnection::capabilitiesReplyFinished()
emit gotCapabilities();
}
QStringList QgsWFSConnection::connectionList()
{
QSettings settings;
settings.beginGroup( "/Qgis/connections-wfs" );
return settings.childGroups();
}
QString QgsWFSConnection::selectedConnection()
{
QSettings settings;
return settings.value( "/Qgis/connections-wfs/selected" ).toString();
}
void QgsWFSConnection::setSelectedConnection( QString name )
{
QSettings settings;
settings.setValue( "/Qgis/connections-wfs/selected", name );
}
void QgsWFSConnection::deleteConnection( QString name )
{
QSettings settings;
settings.remove( "/Qgis/connections-wfs/" + name );
settings.remove( "/Qgis/WFS/" + name );
}

View File

@ -1,5 +1,5 @@
/***************************************************************************
qgswfsconnection.h
qgswfscapabilities.h
---------------------
begin : October 2011
copyright : (C) 2011 by Martin Dobias
@ -12,30 +12,28 @@
* (at your option) any later version. *
* *
***************************************************************************/
#ifndef QGSWFSCONNECTION_H
#define QGSWFSCONNECTION_H
#ifndef QGSWFSCAPABILITIES_H
#define QGSWFSCAPABILITIES_H
#include <QObject>
#include "qgsrectangle.h"
#include "qgsdatasourceuri.h"
class QNetworkReply;
class QgsWFSConnection : public QObject
class QgsWFSCapabilities : public QObject
{
Q_OBJECT
public:
explicit QgsWFSConnection( QString connName, QObject *parent = 0 );
//explicit QgsWFSCapabilities( QString connName, QObject *parent = 0 );
QgsWFSCapabilities( QString theUri );
static QStringList connectionList();
static void deleteConnection( QString name );
static QString selectedConnection();
static void setSelectedConnection( QString name );
//! Append ? or & if necessary
QString prepareUri( QString uri );
//! base service URI
QString uri() const { return mUri; }
QString uri() const { return mBaseUrl; }
//! URI to get capabilities
QString uriGetCapabilities() const;
//! URI to get schema of wfs layer
@ -81,8 +79,12 @@ class QgsWFSConnection : public QObject
void capabilitiesReplyFinished();
protected:
QString mConnName;
QString mUri;
//QString mConnName;
//QString mUri;
QgsDataSourceURI mUri;
QString mBaseUrl;
QNetworkReply *mCapabilitiesReply;
GetCapabilities mCaps;
@ -90,4 +92,4 @@ class QgsWFSConnection : public QObject
QString mErrorMessage;
};
#endif // QGSWFSCONNECTION_H
#endif // QGSWFSCAPABILITIES_H

View File

@ -12,23 +12,25 @@
* (at your option) any later version. *
* *
***************************************************************************/
#include "qgswfsdataitems.h"
#include "qgswfsprovider.h"
#include "qgswfsconnection.h"
#include "qgswfssourceselect.h"
#include "qgslogger.h"
#include "qgsnewhttpconnection.h"
#include "qgsowsconnection.h"
#include "qgswfscapabilities.h"
#include "qgswfsdataitems.h"
#include "qgswfsprovider.h"
#include "qgswfssourceselect.h"
#include <QSettings>
#include <QCoreApplication>
QgsWFSLayerItem::QgsWFSLayerItem( QgsDataItem* parent, QString connName, QString name, QString title )
QgsWFSLayerItem::QgsWFSLayerItem( QgsDataItem* parent, QString name, QgsDataSourceURI uri, QString featureType, QString title )
: QgsLayerItem( parent, title, parent->path() + "/" + name, QString(), QgsLayerItem::Vector, "WFS" )
{
mUri = QgsWFSConnection( connName ).uriGetFeature( name );
mUri = QgsWFSCapabilities( uri.encodedUri() ).uriGetFeature( featureType );
mPopulated = true;
//mIcon = QIcon( getThemePixmap( "mIconVectorLayer.png" ) );
mIcon = QIcon( getThemePixmap( "mIconWfs.png" ) );
}
QgsWFSLayerItem::~QgsWFSLayerItem()
@ -38,9 +40,9 @@ QgsWFSLayerItem::~QgsWFSLayerItem()
////
QgsWFSConnectionItem::QgsWFSConnectionItem( QgsDataItem* parent, QString name, QString path )
: QgsDataCollectionItem( parent, name, path ), mName( name ), mConn( NULL )
: QgsDataCollectionItem( parent, name, path ), mName( name ), mCapabilities( NULL )
{
mIcon = QIcon( getThemePixmap( "mIconConnect.png" ) );
mIcon = QIcon( getThemePixmap( "mIconWfs.png" ) );
}
QgsWFSConnectionItem::~QgsWFSConnectionItem()
@ -50,10 +52,16 @@ QgsWFSConnectionItem::~QgsWFSConnectionItem()
QVector<QgsDataItem*> QgsWFSConnectionItem::createChildren()
{
mGotCapabilities = false;
mConn = new QgsWFSConnection( mName, this );
connect( mConn, SIGNAL( gotCapabilities() ), this, SLOT( gotCapabilities() ) );
mConn->requestCapabilities();
QString encodedUri = mPath;
QgsDataSourceURI uri;
uri.setEncodedUri ( encodedUri );
QgsDebugMsg( "encodedUri = " + encodedUri );
mCapabilities = new QgsWFSCapabilities( encodedUri );
connect( mCapabilities, SIGNAL( gotCapabilities() ), this, SLOT( gotCapabilities() ) );
mCapabilities->requestCapabilities();
while ( !mGotCapabilities )
{
@ -61,22 +69,24 @@ QVector<QgsDataItem*> QgsWFSConnectionItem::createChildren()
}
QVector<QgsDataItem*> layers;
if ( mConn->errorCode() == QgsWFSConnection::NoError )
if ( mCapabilities->errorCode() == QgsWFSCapabilities::NoError )
{
QgsWFSConnection::GetCapabilities caps = mConn->capabilities();
foreach( const QgsWFSConnection::FeatureType& featureType, caps.featureTypes )
QgsWFSCapabilities::GetCapabilities caps = mCapabilities->capabilities();
foreach( const QgsWFSCapabilities::FeatureType& featureType, caps.featureTypes )
{
QgsWFSLayerItem* layer = new QgsWFSLayerItem( this, mName, featureType.name, featureType.title );
//QgsWFSLayerItem* layer = new QgsWFSLayerItem( this, mName, featureType.name, featureType.title );
QgsWFSLayerItem* layer = new QgsWFSLayerItem( this, mName, uri, featureType.name, featureType.title );
layers.append( layer );
}
}
else
{
layers.append( new QgsErrorItem( this, tr( "Failed to retrieve layers" ), mPath + "/error" ) );
//layers.append( new QgsErrorItem( this, tr( "Failed to retrieve layers" ), mPath + "/error" ) );
// TODO: show the error without adding child
}
mConn->deleteLater();
mConn = NULL;
mCapabilities->deleteLater();
mCapabilities = NULL;
return layers;
}
@ -115,7 +125,7 @@ void QgsWFSConnectionItem::editConnection()
void QgsWFSConnectionItem::deleteConnection()
{
QgsWFSConnection::deleteConnection( mName );
QgsOWSConnection::deleteConnection( "WFS", mName );
// the parent should be updated
mParent->refresh();
}
@ -141,9 +151,11 @@ QVector<QgsDataItem*> QgsWFSRootItem::createChildren()
{
QVector<QgsDataItem*> connections;
foreach( QString connName, QgsWFSConnection::connectionList() )
foreach( QString connName, QgsOWSConnection::connectionList( "WFS" ) )
{
QgsDataItem * conn = new QgsWFSConnectionItem( this, connName, mPath + "/" + connName );
QgsOWSConnection connection( "WF", connName );
QgsDataItem * conn = new QgsWFSConnectionItem( this, connName, connection.uri().encodedUri() );
conn->setIcon ( QIcon( getThemePixmap( "mIconConnect.png" ) ) );
connections.append( conn );
}
return connections;
@ -197,8 +209,12 @@ QGISEXTERN int dataCapabilities()
QGISEXTERN QgsDataItem * dataItem( QString thePath, QgsDataItem* parentItem )
{
Q_UNUSED( thePath );
QgsDebugMsg( "thePath = " + thePath );
if ( thePath.isEmpty() )
{
return new QgsWFSRootItem( parentItem, "WFS", "wfs:" );
}
return new QgsWFSRootItem( parentItem, "WFS", "wfs:" );
return new QgsWFSConnectionItem( parentItem, "WFS", thePath );
}

View File

@ -16,6 +16,8 @@
#define QGSWFSDATAITEMS_H
#include "qgsdataitem.h"
#include "qgsdatasourceuri.h"
#include "qgswfscapabilities.h"
class QgsWFSRootItem : public QgsDataCollectionItem
{
@ -59,7 +61,7 @@ class QgsWFSConnectionItem : public QgsDataCollectionItem
private:
QString mName;
QgsWFSConnection* mConn;
QgsWFSCapabilities* mCapabilities;
bool mGotCapabilities;
};
@ -67,7 +69,7 @@ class QgsWFSConnectionItem : public QgsDataCollectionItem
class QgsWFSLayerItem : public QgsLayerItem
{
public:
QgsWFSLayerItem( QgsDataItem* parent, QString connName, QString name, QString title );
QgsWFSLayerItem( QgsDataItem* parent, QString name, QgsDataSourceURI uri, QString featureType, QString title );
~QgsWFSLayerItem();
};

View File

@ -16,7 +16,8 @@
***************************************************************************/
#include "qgswfssourceselect.h"
#include "qgswfsconnection.h"
#include "qgsowsconnection.h"
#include "qgswfscapabilities.h"
#include "qgswfsprovider.h"
#include "qgsnewhttpconnection.h"
#include "qgsgenericprojectionselector.h"
@ -38,7 +39,7 @@
QgsWFSSourceSelect::QgsWFSSourceSelect( QWidget* parent, Qt::WFlags fl, bool embeddedMode )
: QDialog( parent, fl )
, mConn( NULL )
, mCapabilities( NULL )
{
setupUi( this );
@ -75,12 +76,12 @@ QgsWFSSourceSelect::~QgsWFSSourceSelect()
settings.setValue( "/Windows/WFSSourceSelect/geometry", saveGeometry() );
delete mProjectionSelector;
delete mConn;
delete mCapabilities;
}
void QgsWFSSourceSelect::populateConnectionList()
{
QStringList keys = QgsWFSConnection::connectionList();
QStringList keys = QgsOWSConnection::connectionList( "WFS" );
QStringList::Iterator it = keys.begin();
cmbConnections->clear();
@ -107,16 +108,17 @@ void QgsWFSSourceSelect::populateConnectionList()
}
//set last used connection
QString selectedConnection = QgsWFSConnection::selectedConnection();
QString selectedConnection = QgsOWSConnection::selectedConnection( "WFS" );
int index = cmbConnections->findText( selectedConnection );
if ( index != -1 )
{
cmbConnections->setCurrentIndex( index );
}
delete mConn;
mConn = new QgsWFSConnection( cmbConnections->currentText() );
connect( mConn, SIGNAL( gotCapabilities() ), this, SLOT( capabilitiesReplyFinished() ) );
QgsOWSConnection connection( "WFS", cmbConnections->currentText() );
delete mCapabilities;
mCapabilities = new QgsWFSCapabilities( connection.uri().encodedUri() );
connect( mCapabilities, SIGNAL( gotCapabilities() ), this, SLOT( capabilitiesReplyFinished() ) );
}
QString QgsWFSSourceSelect::getPreferredCrs( const QSet<QString>& crsSet ) const
@ -155,30 +157,30 @@ void QgsWFSSourceSelect::capabilitiesReplyFinished()
{
btnConnect->setEnabled( true );
if ( !mConn )
if ( !mCapabilities )
return;
QgsWFSConnection::ErrorCode err = mConn->errorCode();
if ( err != QgsWFSConnection::NoError )
QgsWFSCapabilities::ErrorCode err = mCapabilities->errorCode();
if ( err != QgsWFSCapabilities::NoError )
{
QString title;
switch ( err )
{
case QgsWFSConnection::NetworkError: title = tr( "Network Error" ); break;
case QgsWFSConnection::XmlError: title = tr( "Capabilities document is not valid" ); break;
case QgsWFSConnection::ServerExceptionError: title = tr( "Server Exception" ); break;
case QgsWFSCapabilities::NetworkError: title = tr( "Network Error" ); break;
case QgsWFSCapabilities::XmlError: title = tr( "Capabilities document is not valid" ); break;
case QgsWFSCapabilities::ServerExceptionError: title = tr( "Server Exception" ); break;
default: tr( "Error" ); break;
}
// handle errors
QMessageBox::critical( 0, title, mConn->errorMessage() );
QMessageBox::critical( 0, title, mCapabilities->errorMessage() );
btnAdd->setEnabled( false );
return;
}
QgsWFSConnection::GetCapabilities caps = mConn->capabilities();
QgsWFSCapabilities::GetCapabilities caps = mCapabilities->capabilities();
mAvailableCRS.clear();
foreach( QgsWFSConnection::FeatureType featureType, caps.featureTypes )
foreach( QgsWFSCapabilities::FeatureType featureType, caps.featureTypes )
{
// insert the typenames, titles and abstracts into the tree view
QTreeWidgetItem* newItem = new QTreeWidgetItem();
@ -242,7 +244,7 @@ void QgsWFSSourceSelect::deleteEntryOfServerList()
QMessageBox::StandardButton result = QMessageBox::information( this, tr( "Confirm Delete" ), msg, QMessageBox::Ok | QMessageBox::Cancel );
if ( result == QMessageBox::Ok )
{
QgsWFSConnection::deleteConnection( cmbConnections->currentText() );
QgsOWSConnection::deleteConnection( "WFS", cmbConnections->currentText() );
cmbConnections->removeItem( cmbConnections->currentIndex() );
emit connectionsChanged();
}
@ -253,9 +255,9 @@ void QgsWFSSourceSelect::connectToServer()
btnConnect->setEnabled( false );
treeWidget->clear();
if ( mConn )
if ( mCapabilities )
{
mConn->requestCapabilities();
mCapabilities->requestCapabilities();
}
}
@ -271,7 +273,10 @@ void QgsWFSSourceSelect::addLayer()
QList<QTreeWidgetItem*> selectedItems = treeWidget->selectedItems();
QList<QTreeWidgetItem*>::const_iterator sIt = selectedItems.constBegin();
QgsWFSConnection conn( cmbConnections->currentText() );
QgsOWSConnection connection( "WFS", cmbConnections->currentText() );
QgsWFSCapabilities conn( connection.uri().encodedUri() );
QString pCrsString( labelCoordRefSys->text() );
QgsCoordinateReferenceSystem pCrs( pCrsString );
//prepare canvas extent info for layers with "cache features" option not set
@ -375,11 +380,13 @@ void QgsWFSSourceSelect::changeCRSFilter()
void QgsWFSSourceSelect::on_cmbConnections_activated( int index )
{
Q_UNUSED( index );
QgsWFSConnection::setSelectedConnection( cmbConnections->currentText() );
QgsOWSConnection::setSelectedConnection( "WFS", cmbConnections->currentText() );
delete mConn;
mConn = new QgsWFSConnection( cmbConnections->currentText() );
connect( mConn, SIGNAL( gotCapabilities() ), this, SLOT( capabilitiesReplyFinished() ) );
QgsOWSConnection connection( "WFS", cmbConnections->currentText() );
delete mCapabilities;
mCapabilities = new QgsWFSCapabilities( connection.uri().encodedUri() );
connect( mCapabilities, SIGNAL( gotCapabilities() ), this, SLOT( capabilitiesReplyFinished() ) );
}
void QgsWFSSourceSelect::on_btnSave_clicked()
@ -409,7 +416,8 @@ void QgsWFSSourceSelect::on_treeWidget_itemDoubleClicked( QTreeWidgetItem* item,
{
//get available fields for wfs layer
QgsWFSProvider p( "" ); //bypasses most provider instantiation logic
QgsWFSConnection conn( cmbConnections->currentText() );
QgsOWSConnection connection( "WFS", cmbConnections->currentText() );
QgsWFSCapabilities conn( connection.uri().encodedUri() );
QString uri = conn.uriDescribeFeatureType( item->text( 1 ) );
QgsFieldMap fields;

View File

@ -22,7 +22,7 @@
#include "qgscontexthelp.h"
class QgsGenericProjectionSelector;
class QgsWFSConnection;
class QgsWFSCapabilities;
class QgsWFSSourceSelect: public QDialog, private Ui::QgsWFSSourceSelectBase
{
@ -45,7 +45,7 @@ class QgsWFSSourceSelect: public QDialog, private Ui::QgsWFSSourceSelectBase
stores the CRS for the typename in the form 'EPSG:XXXX'*/
std::map<QString, std::list<QString> > mAvailableCRS;
QAbstractButton* btnAdd;
QgsWFSConnection* mConn;
QgsWFSCapabilities* mCapabilities;
QString mUri; // data source URI
void populateConnectionList();

View File

@ -28,7 +28,7 @@
QgsWMSConnectionItem::QgsWMSConnectionItem( QgsDataItem* parent, QString name, QString path )
: QgsDataCollectionItem( parent, name, path )
{
mIcon = QIcon( getThemePixmap( "mIconConnect.png" ) );
mIcon = QIcon( getThemePixmap( "mIconWms.png" ) );
}
QgsWMSConnectionItem::~QgsWMSConnectionItem()
@ -39,18 +39,33 @@ QVector<QgsDataItem*> QgsWMSConnectionItem::createChildren()
{
QgsDebugMsg( "Entered" );
QVector<QgsDataItem*> children;
QgsWMSConnection connection( mName );
QgsWmsProvider *wmsProvider = connection.provider();
if ( !wmsProvider )
return children;
QgsDataSourceURI uri = connection.uri();
QgsDebugMsg( "uri = " + uri.encodedUri() );
QString encodedUri = mPath;
QgsDataSourceURI uri;
uri.setEncodedUri ( encodedUri );
/*
if ( mPath.contains ( "url=" ) )
{
encodedUri = mPath;
uri.setEncodedUri ( encodedUri );
}
else
{
QgsWMSConnection connection( mName );
uri = connection.uri();
encodedUri = uri.encodedUri();
}
*/
QgsDebugMsg( "encodedUri = " + encodedUri );
QgsWmsProvider *wmsProvider = new QgsWmsProvider ( encodedUri );
if ( !wmsProvider ) return children;
// Attention: supportedLayers() gives tree leafes, not top level
if ( !wmsProvider->supportedLayers( mLayerProperties ) )
{
children.append( new QgsErrorItem( this, tr( "Failed to retrieve layers" ), mPath + "/error" ) );
//children.append( new QgsErrorItem( this, tr( "Failed to retrieve layers" ), mPath + "/error" ) );
// TODO: show the error without adding child
return children;
}
@ -81,7 +96,12 @@ bool QgsWMSConnectionItem::equal( const QgsDataItem *other )
return false;
}
const QgsWMSConnectionItem *o = dynamic_cast<const QgsWMSConnectionItem *>( other );
return ( mPath == o->mPath && mName == o->mName && mConnInfo == o->mConnInfo );
if ( !o )
{
return false;
}
return ( mPath == o->mPath && mName == o->mName );
}
QList<QAction*> QgsWMSConnectionItem::actions()
@ -142,7 +162,8 @@ QgsWMSLayerItem::QgsWMSLayerItem( QgsDataItem* parent, QString name, QString pat
if ( mChildren.size() == 0 )
{
mIcon = iconRaster();
//mIcon = iconRaster();
mIcon = QIcon( getThemePixmap( "mIconWms.png" ) );
}
mPopulated = true;
}
@ -215,7 +236,11 @@ QVector<QgsDataItem*>QgsWMSRootItem::createChildren()
foreach( QString connName, QgsWMSConnection::connectionList() )
{
QgsDataItem * conn = new QgsWMSConnectionItem( this, connName, mPath + "/" + connName );
//QgsDataItem * conn = new QgsWMSConnectionItem( this, connName, mPath + "/" + connName );
QgsWMSConnection connection( connName );
QgsDataItem * conn = new QgsWMSConnectionItem( this, connName, connection.uri().encodedUri() );
conn->setIcon ( QIcon( getThemePixmap( "mIconConnect.png" ) ) );
connections.append( conn );
}
return connections;
@ -274,7 +299,11 @@ QGISEXTERN int dataCapabilities()
QGISEXTERN QgsDataItem * dataItem( QString thePath, QgsDataItem* parentItem )
{
Q_UNUSED( thePath );
if ( thePath.isEmpty() )
{
return new QgsWMSRootItem( parentItem, "WMS", "wms:" );
}
return new QgsWMSRootItem( parentItem, "WMS", "wms:" );
// The path should contain encoded connection URI
return new QgsWMSConnectionItem( parentItem, "WMS", thePath );
}

View File

@ -149,6 +149,7 @@
<addaction name="mActionAddMssqlLayer"/>
<addaction name="mActionAddWmsLayer"/>
<addaction name="mActionAddLayerSeparator"/>
<addaction name="mActionAddWcsLayer"/>
<addaction name="mActionAddWfsLayer"/>
<addaction name="separator"/>
<addaction name="mActionCopyStyle"/>
@ -255,6 +256,7 @@
<addaction name="mActionAddSpatiaLiteLayer"/>
<addaction name="mActionAddMssqlLayer"/>
<addaction name="mActionAddWmsLayer"/>
<addaction name="mActionAddWcsLayer"/>
<addaction name="mActionAddWfsLayer"/>
<addaction name="mActionNewVectorLayer"/>
<addaction name="mActionRemoveLayer"/>
@ -1670,6 +1672,15 @@
<string>Paste style</string>
</property>
</action>
<action name="mActionAddWcsLayer">
<property name="icon">
<iconset resource="../../images/images.qrc">
<normaloff>:/images/themes/default/mActionAddWcsLayer.png</normaloff>:/images/themes/default/mActionAddWcsLayer.png</iconset>
</property>
<property name="text">
<string>Add WCS Layer...</string>
</property>
</action>
</widget>
<resources>
<include location="../../images/images.qrc"/>

View File

@ -28,7 +28,7 @@
</widget>
</item>
<item row="0" column="0">
<widget class="QGroupBox" name="GroupBox1">
<widget class="QGroupBox" name="mGroupBox">
<property name="title">
<string>Connection details</string>
</property>

View File

@ -0,0 +1,502 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>QgsOWSSourceSelectBase</class>
<widget class="QDialog" name="QgsOWSSourceSelectBase">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>694</width>
<height>616</height>
</rect>
</property>
<property name="windowTitle">
<string>Add Layer(s) from a Server</string>
</property>
<property name="windowIcon">
<iconset>
<normaloff>../../../../.designer/backup</normaloff>../../../../.designer/backup</iconset>
</property>
<property name="sizeGripEnabled">
<bool>true</bool>
</property>
<property name="modal">
<bool>true</bool>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="3" column="0">
<widget class="QDialogButtonBox" name="mDialogButtonBox">
<property name="standardButtons">
<set>QDialogButtonBox::Apply|QDialogButtonBox::Close|QDialogButtonBox::Help</set>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="mStatusLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Ignored" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Ready</string>
</property>
<property name="wordWrap">
<bool>false</bool>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QTabWidget" name="mTabWidget">
<property name="enabled">
<bool>true</bool>
</property>
<property name="currentIndex">
<number>0</number>
</property>
<widget class="QWidget" name="mLayersTab">
<attribute name="title">
<string>Layers</string>
</attribute>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0" colspan="8">
<widget class="QComboBox" name="mConnectionsComboBox"/>
</item>
<item row="1" column="0">
<widget class="QPushButton" name="mConnectButton">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>C&amp;onnect</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QPushButton" name="mNewButton">
<property name="text">
<string>&amp;New</string>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QPushButton" name="mEditButton">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Edit</string>
</property>
</widget>
</item>
<item row="1" column="3">
<widget class="QPushButton" name="mDeleteButton">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Delete</string>
</property>
</widget>
</item>
<item row="1" column="4">
<spacer name="horizontalSpacer_1">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>8</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="1" column="5">
<widget class="QPushButton" name="mLoadButton">
<property name="toolTip">
<string>Load connections from file</string>
</property>
<property name="text">
<string>Load</string>
</property>
</widget>
</item>
<item row="1" column="6">
<widget class="QPushButton" name="mSaveButton">
<property name="toolTip">
<string>Save connections to file</string>
</property>
<property name="text">
<string>Save</string>
</property>
</widget>
</item>
<item row="1" column="7">
<widget class="QPushButton" name="mAddDefaultButton">
<property name="statusTip">
<string>Adds a few example WMS servers</string>
</property>
<property name="whatsThis">
<string comment="Adds several example WMS servers to the list"/>
</property>
<property name="text">
<string>Add default servers</string>
</property>
</widget>
</item>
<item row="2" column="0" colspan="8">
<widget class="QTreeWidget" name="mLayersTreeWidget">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="selectionMode">
<enum>QAbstractItemView::MultiSelection</enum>
</property>
<property name="allColumnsShowFocus">
<bool>true</bool>
</property>
<column>
<property name="text">
<string>ID</string>
</property>
</column>
<column>
<property name="text">
<string>Name</string>
</property>
</column>
<column>
<property name="text">
<string>Title</string>
</property>
</column>
<column>
<property name="text">
<string>Abstract</string>
</property>
</column>
</widget>
</item>
<item row="3" column="0" colspan="8">
<widget class="QGroupBox" name="mImageFormatsGroupBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>16</width>
<height>64</height>
</size>
</property>
<property name="title">
<string>Format</string>
</property>
</widget>
</item>
<item row="4" column="0" colspan="8">
<widget class="QGroupBox" name="mWMSGroupBox">
<property name="title">
<string>Options</string>
</property>
<layout class="QGridLayout">
<item row="0" column="0">
<widget class="QLabel" name="mLayerNameLabel">
<property name="text">
<string>Layer name</string>
</property>
<property name="buddy">
<cstring>mLayerNameLineEdit</cstring>
</property>
</widget>
</item>
<item row="0" column="1" colspan="2">
<widget class="QLineEdit" name="mLayerNameLineEdit"/>
</item>
<item row="1" column="1">
<widget class="QLineEdit" name="mTileWidthLineEdit"/>
</item>
<item row="1" column="0">
<widget class="QLabel" name="mTileSizeLabel">
<property name="text">
<string>Tile size</string>
</property>
<property name="buddy">
<cstring>mTileWidthLineEdit</cstring>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QLineEdit" name="mTileHeightLineEdit"/>
</item>
<item row="2" column="0" colspan="2">
<widget class="QLabel" name="mFeatureCountLabel">
<property name="text">
<string>Feature limit for GetFeatureInfo</string>
</property>
<property name="buddy">
<cstring>mFeatureCountLineEdit</cstring>
</property>
</widget>
</item>
<item row="2" column="2">
<widget class="QLineEdit" name="mFeatureCountLineEdit"/>
</item>
</layout>
</widget>
</item>
<item row="5" column="0" colspan="8">
<widget class="QGroupBox" name="mCRSGroupBox">
<property name="title">
<string>Coordinate Reference System</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="mSelectedCRSLabel">
<property name="text">
<string>Coordinate Reference System</string>
</property>
<property name="buddy">
<cstring>mChangeCRSButton</cstring>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="mChangeCRSButton">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Change ...</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="mLayerOrderTab">
<attribute name="title">
<string>Layer Order</string>
</attribute>
<layout class="QGridLayout">
<item row="0" column="0">
<widget class="QPushButton" name="mLayerUpButton">
<property name="toolTip">
<string>Move selected layer UP</string>
</property>
<property name="text">
<string>Up</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QPushButton" name="mLayerDownButton">
<property name="toolTip">
<string>Move selected layer DOWN</string>
</property>
<property name="text">
<string>Down</string>
</property>
</widget>
</item>
<item row="0" column="2">
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>391</width>
<height>30</height>
</size>
</property>
</spacer>
</item>
<item row="1" column="0" colspan="3">
<widget class="QTreeWidget" name="mLayerOrderTreeWidget">
<property name="columnCount">
<number>2</number>
</property>
<column>
<property name="text">
<string>Layer</string>
</property>
</column>
<column>
<property name="text">
<string>Style</string>
</property>
</column>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="mTilesetsTab">
<attribute name="title">
<string>Tilesets</string>
</attribute>
<layout class="QGridLayout" name="gridLayout_3">
<item row="0" column="0">
<widget class="QTableWidget" name="mTilesetsTableWidget">
<property name="alternatingRowColors">
<bool>true</bool>
</property>
<property name="selectionMode">
<enum>QAbstractItemView::SingleSelection</enum>
</property>
<property name="selectionBehavior">
<enum>QAbstractItemView::SelectRows</enum>
</property>
<property name="cornerButtonEnabled">
<bool>false</bool>
</property>
<attribute name="verticalHeaderVisible">
<bool>false</bool>
</attribute>
<attribute name="verticalHeaderVisible">
<bool>false</bool>
</attribute>
<column>
<property name="text">
<string>Layers</string>
</property>
</column>
<column>
<property name="text">
<string>Styles</string>
</property>
</column>
<column>
<property name="text">
<string>Size</string>
</property>
</column>
<column>
<property name="text">
<string>Format</string>
</property>
</column>
<column>
<property name="text">
<string>CRS</string>
</property>
</column>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="mSearchTab">
<attribute name="title">
<string>Server Search</string>
</attribute>
<layout class="QGridLayout">
<item row="0" column="0">
<widget class="QLineEdit" name="mSearchTermLineEdit"/>
</item>
<item row="0" column="1">
<widget class="QPushButton" name="mSearchButton">
<property name="text">
<string>Search</string>
</property>
<property name="default">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="0" colspan="2">
<widget class="QTableWidget" name="mSearchTableWidget">
<property name="selectionMode">
<enum>QAbstractItemView::SingleSelection</enum>
</property>
<property name="selectionBehavior">
<enum>QAbstractItemView::SelectRows</enum>
</property>
<property name="cornerButtonEnabled">
<bool>false</bool>
</property>
<attribute name="verticalHeaderVisible">
<bool>false</bool>
</attribute>
<attribute name="verticalHeaderVisible">
<bool>false</bool>
</attribute>
<column>
<property name="text">
<string>Title</string>
</property>
</column>
<column>
<property name="text">
<string>Description</string>
</property>
</column>
<column>
<property name="text">
<string>URL</string>
</property>
</column>
</widget>
</item>
<item row="2" column="0" colspan="2">
<widget class="QPushButton" name="mSearchAddButton">
<property name="text">
<string>Add selected row to WMS list</string>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
</widget>
<layoutdefault spacing="6" margin="11"/>
<tabstops>
<tabstop>mTabWidget</tabstop>
<tabstop>mConnectionsComboBox</tabstop>
<tabstop>mConnectButton</tabstop>
<tabstop>mNewButton</tabstop>
<tabstop>mEditButton</tabstop>
<tabstop>mDeleteButton</tabstop>
<tabstop>mAddDefaultButton</tabstop>
<tabstop>mLayersTreeWidget</tabstop>
<tabstop>mLayerNameLineEdit</tabstop>
<tabstop>mLayerUpButton</tabstop>
<tabstop>mLayerDownButton</tabstop>
<tabstop>mLayerOrderTreeWidget</tabstop>
<tabstop>mTilesetsTableWidget</tabstop>
<tabstop>mSearchTermLineEdit</tabstop>
<tabstop>mSearchButton</tabstop>
<tabstop>mSearchTableWidget</tabstop>
<tabstop>mSearchAddButton</tabstop>
<tabstop>mDialogButtonBox</tabstop>
</tabstops>
<resources/>
<connections>
<connection>
<sender>mDialogButtonBox</sender>
<signal>rejected()</signal>
<receiver>QgsOWSSourceSelectBase</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>518</x>
<y>510</y>
</hint>
<hint type="destinationlabel">
<x>551</x>
<y>370</y>
</hint>
</hints>
</connection>
</connections>
</ui>