Add relations capabilites and widgets

This commit is contained in:
Matthias Kuhn 2013-10-04 14:47:59 +02:00
parent fb32966932
commit dc3b56a13c
61 changed files with 4138 additions and 167 deletions

View File

@ -438,6 +438,10 @@
<file>flags/nb_NO.png</file>
<file>flags/gl.png</file>
<file>flags/hi.png</file>
<file>themes/default/relation.svg</file>
<file>themes/default/mActionLink.svg</file>
<file>themes/default/mActionUnlink.svg</file>
<file>themes/default/mActionRemove.svg</file>
</qresource>
<qresource prefix="/images/tips">
<file alias="symbol_levels.png">qgis_tips/symbol_levels.png</file>

View File

@ -14,7 +14,7 @@
id="svg5692"
version="1.1"
inkscape:version="0.48.4 r9939"
sodipodi:docname="mActionAddDelimitedTextLayer.svg"
sodipodi:docname="mActionAdd.svg"
inkscape:export-filename="/media/home1/robert/svn/graphics/trunk/toolbar-icons/32x32/layer-vector.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90">
@ -80,7 +80,7 @@
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="15.937501"
inkscape:cx="-5.5360852"
inkscape:cx="-5.410595"
inkscape:cy="11.532645"
inkscape:current-layer="layer2"
showgrid="true"
@ -90,7 +90,7 @@
inkscape:window-width="1231"
inkscape:window-height="858"
inkscape:window-x="683"
inkscape:window-y="115"
inkscape:window-y="867"
inkscape:window-maximized="0"
inkscape:snap-global="true"
showguides="true"
@ -162,7 +162,7 @@
transform="translate(0,-8)">
<g
id="g3772"
transform="matrix(1.8506786,0,0,1.8506786,-35.158971,-27.158972)">
transform="matrix(1.6141779,0,0,1.6141779,-29.159575,-21.159576)">
<rect
ry="2.6149368"
inkscape:export-ydpi="120"

Before

Width:  |  Height:  |  Size: 7.2 KiB

After

Width:  |  Height:  |  Size: 7.1 KiB

View File

@ -0,0 +1,74 @@
<?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="24"
height="24"
id="svg3072"
version="1.1"
inkscape:version="0.48.4 r9939"
sodipodi:docname="New document 1">
<defs
id="defs3074" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="22.4"
inkscape:cx="8.6107244"
inkscape:cy="15.703898"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-width="1920"
inkscape:window-height="1021"
inkscape:window-x="0"
inkscape:window-y="867"
inkscape:window-maximized="1" />
<metadata
id="metadata3077">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-1028.3622)">
<rect
style="color:#000000;fill:none;stroke:#c4a000;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"
id="rect2902"
width="10.839286"
height="4.098249"
x="2.4375007"
y="1038.1122"
rx="2.6428566"
ry="2.0491245" />
<rect
style="color:#000000;fill:none;stroke:#c4a000;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"
id="rect2902-3"
width="10.839286"
height="4.098249"
x="10.964286"
y="1038.1345"
rx="2.6428566"
ry="2.0491245" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

@ -0,0 +1,193 @@
<?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="24"
height="24"
id="svg5692"
version="1.1"
inkscape:version="0.48.4 r9939"
sodipodi:docname="mActionRemove.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.937501"
inkscape:cx="-5.410595"
inkscape:cy="11.532645"
inkscape:current-layer="layer2"
showgrid="true"
inkscape:grid-bbox="true"
inkscape:document-units="px"
borderlayer="false"
inkscape:window-width="1231"
inkscape:window-height="858"
inkscape:window-x="687"
inkscape:window-y="867"
inkscape:window-maximized="0"
inkscape:snap-global="true"
showguides="true"
inkscape:guide-bbox="true"
inkscape:snap-object-midpoints="true"
inkscape:snap-grids="false">
<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"
transform="translate(0,-8)">
<g
id="layer1"
transform="matrix(2.0979294,0,0,2.0979294,-27.846021,-36.723572)">
<g
id="g8247">
<path
style="opacity:0.9;fill:#cc0000;stroke:#cc0000;stroke-linecap:square;stroke-linejoin:round"
inkscape:connector-curvature="0"
d="m 15.143,22.5 h 7.715 c 0.354,0 0.643,0.288 0.643,0.643 v 7.715 c 0,0.354 -0.288,0.643 -0.643,0.643 h -7.715 c -0.354,0 -0.643,-0.288 -0.643,-0.643 v -7.715 c 0,-0.355 0.288,-0.643 0.643,-0.643 z"
enable-background="new "
id="rect10143-0-5" />
<path
style="opacity:0.3;fill:#fcffff"
inkscape:connector-curvature="0"
d="m 14.5,27 h 9 v -3 c 0,-1.5 0,-1.5 -2.25,-1.5 -0.523,0 -4.555,0 -5.25,0 -1.5,0 -1.5,0 -1.5,1.5 0,0.75 0,1.5 0,3 z"
enable-background="new "
id="path10149-9-8" />
<path
style="fill:#5c3566;stroke:#eeeeec;stroke-width:1.70560002;stroke-linecap:round"
inkscape:connector-curvature="0"
d="m 16,24 6.001,6"
id="path13835-7" />
<path
style="fill:#5c3566;stroke:#eeeeec;stroke-width:1.70560002;stroke-linecap:round"
inkscape:connector-curvature="0"
d="m 16,30 6.001,-6"
id="path8245" />
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 6.6 KiB

View File

@ -0,0 +1,122 @@
<?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="24"
height="24"
id="svg3072"
version="1.1"
inkscape:version="0.48.4 r9939"
sodipodi:docname="New document 1">
<defs
id="defs3074" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="15.839192"
inkscape:cx="8.1893275"
inkscape:cy="11.967963"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-width="1920"
inkscape:window-height="1021"
inkscape:window-x="0"
inkscape:window-y="867"
inkscape:window-maximized="1" />
<metadata
id="metadata3077">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-1028.3622)">
<rect
style="color:#000000;fill:none;stroke:#c4a000;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"
id="rect2902"
width="9.4553576"
height="4.0982666"
x="0.91964388"
y="1038.1122"
rx="2.6428566"
ry="2.0491245" />
<rect
ry="2.0491245"
rx="2.6428566"
y="1038.1122"
x="12.919643"
height="4.0982666"
width="9.4553576"
id="rect3910"
style="color:#000000;fill:none;stroke:#c4a000;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" />
<path
style="fill:none;stroke:#820521;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
d="m 11.72724,1041.8503 0,1.973"
id="path3963"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
<path
style="fill:none;stroke:#820521;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
d="m 8.8560596,1037.3242 1.3951174,1.3952"
id="path3978"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
<path
sodipodi:nodetypes="cc"
inkscape:connector-curvature="0"
id="path3980"
d="m 14.551073,1037.2136 -1.395122,1.3952"
style="fill:none;stroke:#820521;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1" />
<path
style="fill:none;stroke:#820521;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
d="m 10.235393,1041.6178 -1.395117,1.3952"
id="path3982"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
<path
sodipodi:nodetypes="cc"
inkscape:connector-curvature="0"
id="path3984"
d="m 13.029679,1041.602 1.395122,1.3952"
style="fill:none;stroke:#820521;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1" />
<path
style="fill:none;stroke:#820521;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
d="m 15.3451,1040.1482 -1.973,0"
id="path3986"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
<path
sodipodi:nodetypes="cc"
inkscape:connector-curvature="0"
id="path3988"
d="m 11.72724,1036.5771 0,1.973"
style="fill:none;stroke:#820521;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1" />
<path
sodipodi:nodetypes="cc"
inkscape:connector-curvature="0"
id="path3992"
d="m 9.8659588,1040.1482 -1.973,0"
style="fill:none;stroke:#820521;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 4.5 KiB

View File

@ -0,0 +1,605 @@
<?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"
id="svg3428"
height="32"
width="32"
version="1.0"
inkscape:version="0.48.4 r9939"
sodipodi:docname="relation.svg">
<metadata
id="metadata61">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1153"
inkscape:window-height="836"
id="namedview59"
showgrid="false"
inkscape:zoom="55.625732"
inkscape:cx="19.005713"
inkscape:cy="22.381052"
inkscape:window-x="148"
inkscape:window-y="915"
inkscape:window-maximized="0"
inkscape:current-layer="svg3428" />
<defs
id="defs3430">
<linearGradient
id="XMLID_5_"
y2="104.06"
gradientUnits="userSpaceOnUse"
x2="64"
y1="21.941"
x1="64">
<stop
id="stop24"
style="stop-color:#dadada"
offset="0" />
<stop
id="stop26"
style="stop-color:#ccc"
offset="1" />
</linearGradient>
<linearGradient
id="XMLID_6_"
y2="103.07"
xlink:href="#XMLID_5_"
gradientUnits="userSpaceOnUse"
x2="64"
y1="21.523001"
x1="64">
<stop
id="stop31"
style="stop-color:#d9d9d9"
offset="0" />
<stop
id="stop33"
style="stop-color:#ccc"
offset="1" />
</linearGradient>
<linearGradient
id="linearGradient3511"
y2="44.139999"
gradientUnits="userSpaceOnUse"
x2="-9.7747002"
gradientTransform="matrix(-0.50045,-0.49965,-0.84917,0.84785,49.112,-9.0091)"
y1="44.229"
x1="-6.3077998">
<stop
id="stop6223"
offset="0" />
<stop
id="stop6225"
style="stop-opacity:0"
offset="1" />
</linearGradient>
<linearGradient
id="linearGradient3514"
y2="35.078999"
gradientUnits="userSpaceOnUse"
x2="90.221001"
gradientTransform="matrix(-0.82274,-0.82219,-0.71961,0.71912,121.1,81.547)"
y1="35.152"
x1="97.442001">
<stop
id="stop4958"
style="stop-color:#f8b17e"
offset="0" />
<stop
id="stop4960"
style="stop-color:#e35d4f"
offset=".26238" />
<stop
id="stop4962"
style="stop-color:#c6262e"
offset=".66347" />
<stop
id="stop4964"
style="stop-color:#690b54"
offset="1" />
</linearGradient>
<linearGradient
id="linearGradient3516"
y2="27.273001"
gradientUnits="userSpaceOnUse"
x2="36.000999"
gradientTransform="matrix(-1,0,0,1,49.001,5.4986e-4)"
y1="34.022999"
x1="29.278">
<stop
id="stop2492"
style="stop-color:#791235"
offset="0" />
<stop
id="stop2494"
style="stop-color:#dd3b27"
offset="1" />
</linearGradient>
<linearGradient
id="linearGradient3533"
y2="88.005997"
gradientUnits="userSpaceOnUse"
x2="317.16"
gradientTransform="matrix(-1.363,0,0,1.3617,452.82,-67.958)"
y1="75.574997"
x1="326.60001">
<stop
id="stop7423-0"
style="stop-color:#fff"
offset="0" />
<stop
id="stop7425-2"
style="stop-color:#fff;stop-opacity:0"
offset="1" />
</linearGradient>
<linearGradient
id="linearGradient3536"
y2="60.768002"
gradientUnits="userSpaceOnUse"
x2="308.64999"
gradientTransform="matrix(-1.363,0,0,1.3617,452.82,-67.958)"
y1="58.443001"
x1="302.29001">
<stop
id="stop7383"
style="stop-color:#babdb6"
offset="0" />
<stop
id="stop7385"
style="stop-color:#fff"
offset="1" />
</linearGradient>
<linearGradient
id="linearGradient3539"
y2="81.926003"
gradientUnits="userSpaceOnUse"
x2="335.29999"
gradientTransform="matrix(-1.363,0,0,1.3617,452.82,-67.958)"
y1="64.294998"
x1="304.76001">
<stop
id="stop4436"
style="stop-color:#d3d7cf"
offset="0" />
<stop
id="stop4438"
style="stop-color:#babdb6"
offset=".18304" />
<stop
id="stop4440"
style="stop-color:#fff"
offset=".31893" />
<stop
id="stop4442"
style="stop-color:#babdb6"
offset=".87644" />
<stop
id="stop4444"
style="stop-color:#eeeeec"
offset="1" />
</linearGradient>
<linearGradient
id="linearGradient3541"
y2="58.612"
gradientUnits="userSpaceOnUse"
x2="305.67001"
gradientTransform="matrix(-1.363,0,0,1.3617,452.82,-67.958)"
y1="52.786999"
x1="301.32001">
<stop
id="stop7446"
style="stop-color:#888a85"
offset="0" />
<stop
id="stop7448"
style="stop-color:#555753"
offset="1" />
</linearGradient>
<linearGradient
id="linearGradient3591"
y2="103.07"
xlink:href="#XMLID_6_"
gradientUnits="userSpaceOnUse"
x2="64"
gradientTransform="matrix(0.37137,0,0,0.37075,0.23836,-0.35744)"
y1="21.523001"
x1="64" />
<linearGradient
id="linearGradient3593"
y2="102.05"
xlink:href="#XMLID_6_"
gradientUnits="userSpaceOnUse"
x2="49.374001"
gradientTransform="matrix(0.37137,0,0,0.37075,0.23836,-0.35744)"
y1="22.275"
x1="49.272999" />
<linearGradient
id="linearGradient3596"
y2="104.06"
xlink:href="#XMLID_5_"
gradientUnits="userSpaceOnUse"
x2="64"
gradientTransform="matrix(0.32178,0,0,0.32124,3.4122,3.0428)"
y1="21.941"
x1="64" />
<linearGradient
id="linearGradient3598"
y2="20.895"
gradientUnits="userSpaceOnUse"
x2="84.639"
gradientTransform="matrix(0.32178,0,0,0.32124,3.4122,3.0428)"
y1="105.1"
x1="86.133003">
<stop
id="stop5130"
style="stop-color:#fff"
offset="0" />
<stop
id="stop5132"
style="stop-color:#959595"
offset="1" />
</linearGradient>
<linearGradient
id="linearGradient3601"
y2="117.23"
gradientUnits="userSpaceOnUse"
x2="64"
gradientTransform="scale(0.375,0.375)"
y1="6.8743"
x1="64">
<stop
id="stop11"
style="stop-color:#f2f2f2"
offset="0" />
<stop
id="stop13"
style="stop-color:#d8d8d8"
offset="1" />
</linearGradient>
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3184"
id="radialGradient6101"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.9739412,0,0,0.9750591,-92.994702,1.6957237)"
cx="255"
cy="63.005722"
fx="262.43524"
fy="71.574997"
r="23.279442" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3184"
id="radialGradient6107"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.9739412,0,0,0.9750591,-44.261685,1.6957237)"
cx="255"
cy="63.005722"
fx="262.43524"
fy="71.574997"
r="23.279442" />
<radialGradient
id="radialGradient3605"
gradientUnits="userSpaceOnUse"
cy="73.615997"
cx="6.7027001"
gradientTransform="matrix(3.0435,0,0,0.96975,3.6,-30.399)"
r="7.2284002">
<stop
id="stop10693"
offset="0" />
<stop
id="stop10695"
style="stop-opacity:0"
offset="1" />
</radialGradient>
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient2990"
id="radialGradient6367"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.9679843,-0.1075536,0.2763828,2.487449,-167.98216,-101.63236)"
cx="267.42477"
cy="81.257088"
fx="267.42477"
fy="81.257088"
r="23.279442" />
<linearGradient
id="linearGradient2990">
<stop
id="stop2992"
offset="0"
style="stop-color:#d7d7d7;stop-opacity:1;" />
<stop
id="stop2994"
offset="1"
style="stop-color:#ffffff;stop-opacity:1;" />
</linearGradient>
<clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath6103">
<path
inkscape:connector-curvature="0"
id="path6105"
d="m 200.1619,45.294924 c -5.42224,0.212474 -9.70739,4.671813 -9.70376,10.098216 l 0,25.245539 c 0.0171,3.487235 1.83207,6.718917 4.80092,8.54838 2.96888,1.829463 6.67151,1.997824 9.79416,0.445344 l 25.24554,-12.62277 c 3.37866,-1.725896 5.50499,-5.199776 5.50499,-8.993723 0,-3.793948 -2.12633,-7.267827 -5.50499,-8.993724 l -25.24554,-12.62277 c -1.51165,-0.77352 -3.19397,-1.153395 -4.89132,-1.104492 z"
style="fill:url(#radialGradient6107);fill-opacity:1;fill-rule:evenodd;stroke:none" />
</clipPath>
<clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath6097">
<path
inkscape:connector-curvature="0"
style="fill:url(#radialGradient6101);fill-opacity:1;fill-rule:evenodd;stroke:none"
d="m 151.42888,45.294924 c -5.42224,0.212474 -9.70739,4.671813 -9.70376,10.098216 l 0,25.245539 c 0.0171,3.487235 1.83207,6.718917 4.80092,8.54838 2.96888,1.829463 6.67151,1.997824 9.79416,0.445344 l 25.24554,-12.62277 c 3.37866,-1.725896 5.50499,-5.199776 5.50499,-8.993723 0,-3.793948 -2.12633,-7.267827 -5.50499,-8.993724 L 156.3202,46.399416 c -1.51165,-0.77352 -3.19397,-1.153395 -4.89132,-1.104492 z"
id="path6099" />
</clipPath>
<radialGradient
inkscape:collect="always"
xlink:href="#radialGradient3605"
id="radialGradient4175"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(3.0435,0,0,0.96975,3.6,-30.399)"
cx="6.7027001"
cy="73.615997"
r="7.2284002" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3601"
id="linearGradient4177"
gradientUnits="userSpaceOnUse"
gradientTransform="scale(0.375,0.375)"
x1="64"
y1="6.8743"
x2="64"
y2="117.23" />
<linearGradient
inkscape:collect="always"
xlink:href="#XMLID_5_"
id="linearGradient4179"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.32178,0,0,0.32124,3.4122,3.0428)"
x1="64"
y1="21.941"
x2="64"
y2="104.06" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3598"
id="linearGradient4181"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.32178,0,0,0.32124,3.4122,3.0428)"
x1="86.133003"
y1="105.1"
x2="84.639"
y2="20.895" />
<linearGradient
inkscape:collect="always"
xlink:href="#XMLID_6_"
id="linearGradient4183"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.37137,0,0,0.37075,0.23836,-0.35744)"
x1="64"
y1="21.523001"
x2="64"
y2="103.07" />
<linearGradient
inkscape:collect="always"
xlink:href="#XMLID_6_"
id="linearGradient4185"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.37137,0,0,0.37075,0.23836,-0.35744)"
x1="49.272999"
y1="22.275"
x2="49.374001"
y2="102.05" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient2990"
id="radialGradient4187"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.9679843,-0.1075536,0.2763828,2.487449,-167.98216,-101.63236)"
cx="267.42477"
cy="81.257088"
fx="267.42477"
fy="81.257088"
r="23.279442" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3923"
id="linearGradient3929"
x1="4.5"
y1="2.5"
x2="9.5"
y2="14.5"
gradientUnits="userSpaceOnUse" />
<linearGradient
id="linearGradient3923">
<stop
style="stop-color:#f1f1f1;stop-opacity:1;"
offset="0"
id="stop3925" />
<stop
style="stop-color:#d6d6d6;stop-opacity:1;"
offset="1"
id="stop3927" />
</linearGradient>
<linearGradient
gradientTransform="translate(1.1324644,1.2047943)"
y2="14.5"
x2="9.5"
y1="2.5"
x1="4.5"
gradientUnits="userSpaceOnUse"
id="linearGradient3082"
xlink:href="#linearGradient3923"
inkscape:collect="always" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3923"
id="linearGradient4095"
gradientUnits="userSpaceOnUse"
gradientTransform="translate(1.1324644,1.2047943)"
x1="4.5"
y1="2.5"
x2="9.5"
y2="14.5" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3923"
id="linearGradient4097"
gradientUnits="userSpaceOnUse"
gradientTransform="translate(1.1324644,1.2047943)"
x1="4.5"
y1="2.5"
x2="9.5"
y2="14.5" />
</defs>
<path
style="fill:#000073;fill-opacity:0;stroke:#2b3b4d;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 10.283011,8.3578359 10.139192,0.00203 0,7.8920306"
id="path3974"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccc" />
<g
id="g4061"
transform="translate(-0.431455,-0.14381833)">
<rect
ry="1"
rx="1"
y="1.7047944"
x="2.6324642"
height="15"
width="13"
id="rect3921"
style="color:#000000;fill:url(#linearGradient4097);fill-opacity:1;fill-rule:evenodd;stroke:#888a85;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" />
<path
id="path3931"
d="m 2.6324644,5.7047943 12.9999996,0"
style="color:#000000;fill:#eeeeec;fill-opacity:1;fill-rule:evenodd;stroke:#888a85;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"
inkscape:connector-curvature="0" />
<path
id="path3933"
d="m 4.6324644,8.7047943 2,0"
style="color:#000000;fill:#eeeeec;fill-opacity:1;fill-rule:evenodd;stroke:#888a85;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"
inkscape:connector-curvature="0" />
<path
id="path3935"
d="m 4.6324644,11.704794 2,0"
style="color:#000000;fill:#eeeeec;fill-opacity:1;fill-rule:evenodd;stroke:#888a85;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"
inkscape:connector-curvature="0" />
<path
id="path3937"
d="m 4.6324644,14.704795 2,0"
style="color:#000000;fill:#eeeeec;fill-opacity:1;fill-rule:evenodd;stroke:#888a85;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"
inkscape:connector-curvature="0" />
<path
id="path3939"
d="m 9.6324641,8.7047943 3.9999999,0"
style="color:#000000;fill:#eeeeec;fill-opacity:1;fill-rule:evenodd;stroke:#888a85;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"
inkscape:connector-curvature="0" />
<path
id="path3941"
d="m 9.5703417,11.663069 4.0621223,0.04172"
style="color:#000000;fill:#eeeeec;fill-opacity:1;fill-rule:evenodd;stroke:#888a85;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"
inkscape:connector-curvature="0" />
<path
id="path3943"
d="m 9.6324641,14.704795 3.9999999,0"
style="color:#000000;fill:#eeeeec;fill-opacity:1;fill-rule:evenodd;stroke:#888a85;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"
inkscape:connector-curvature="0" />
<path
id="path3945"
d="m 4.7035514,3.7105107 1.928913,-0.00572"
style="color:#000000;fill:#eeeeec;fill-opacity:1;fill-rule:evenodd;stroke:#888a85;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"
inkscape:connector-curvature="0" />
<path
id="path3947"
d="m 9.6324641,3.7047943 3.9999999,0"
style="color:#000000;fill:#eeeeec;fill-opacity:1;fill-rule:evenodd;stroke:#888a85;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"
inkscape:connector-curvature="0" />
</g>
<g
id="g4073"
transform="translate(14.885197,13.80656)">
<rect
style="color:#000000;fill:url(#linearGradient4095);fill-opacity:1;fill-rule:evenodd;stroke:#888a85;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"
id="rect4075"
width="13"
height="15"
x="2.6324642"
y="1.7047944"
rx="1"
ry="1" />
<path
inkscape:connector-curvature="0"
style="color:#000000;fill:#eeeeec;fill-opacity:1;fill-rule:evenodd;stroke:#888a85;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 2.6324644,5.7047943 12.9999996,0"
id="path4077" />
<path
inkscape:connector-curvature="0"
style="color:#000000;fill:#eeeeec;fill-opacity:1;fill-rule:evenodd;stroke:#888a85;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 4.6324644,8.7047943 2,0"
id="path4079" />
<path
inkscape:connector-curvature="0"
style="color:#000000;fill:#eeeeec;fill-opacity:1;fill-rule:evenodd;stroke:#888a85;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 4.6324644,11.704794 2,0"
id="path4081" />
<path
inkscape:connector-curvature="0"
style="color:#000000;fill:#eeeeec;fill-opacity:1;fill-rule:evenodd;stroke:#888a85;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 4.6324644,14.704795 2,0"
id="path4083" />
<path
inkscape:connector-curvature="0"
style="color:#000000;fill:#eeeeec;fill-opacity:1;fill-rule:evenodd;stroke:#888a85;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 9.6324641,8.7047943 3.9999999,0"
id="path4085" />
<path
inkscape:connector-curvature="0"
style="color:#000000;fill:#eeeeec;fill-opacity:1;fill-rule:evenodd;stroke:#888a85;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 9.5703417,11.663069 4.0621223,0.04172"
id="path4087" />
<path
inkscape:connector-curvature="0"
style="color:#000000;fill:#eeeeec;fill-opacity:1;fill-rule:evenodd;stroke:#888a85;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 9.6324641,14.704795 3.9999999,0"
id="path4089" />
<path
inkscape:connector-curvature="0"
style="color:#000000;fill:#eeeeec;fill-opacity:1;fill-rule:evenodd;stroke:#888a85;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 4.7035514,3.7105107 1.928913,-0.00572"
id="path4091" />
<path
inkscape:connector-curvature="0"
style="color:#000000;fill:#eeeeec;fill-opacity:1;fill-rule:evenodd;stroke:#888a85;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 9.6324641,3.7047943 3.9999999,0"
id="path4093" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 23 KiB

View File

@ -27,9 +27,9 @@
%Include qgsdatasourceuri.sip
%Include qgsdbfilterproxymodel.sip
%Include qgsdistancearea.sip
%Include qgseditorwidgetconfig.sip
%Include qgserror.sip
%Include qgsexpression.sip
%Include qgseditorwidgetconfig.sip
%Include qgsfeature.sip
%Include qgsfeatureiterator.sip
%Include qgsfeaturerequest.sip
@ -68,6 +68,7 @@
%Include qgsproviderregistry.sip
%Include qgspythonrunner.sip
%Include qgsrectangle.sip
%Include qgsrelation.sip
%Include qgsrenderchecker.sip
%Include qgsrendercontext.sip
%Include qgsrunprocess.sip

171
python/core/qgsrelation.sip Normal file
View File

@ -0,0 +1,171 @@
/***************************************************************************
qgsrelation.sip
--------------------------------------
Date : 29.4.2013
Copyright : (C) 2013 Matthias Kuhn
Email : matthias dot kuhn at gmx dot ch
***************************************************************************
* *
* 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. *
* *
***************************************************************************/
class QgsRelation
{
%TypeHeaderCode
#include <qgsrelation.h>
%End
public:
/**
* Defines a relation between matchin fields of the two involved tables of a relation.
* Often, a relation is only defined by just one FieldPair with the name of the foreign key
* column of the referencing table as first element and the name of the primkary key column
* of the referenced table as the second element.
*
*/
typedef QPair< QString, QString > FieldPair;
/**
* Default constructor. Creates an invalid relation.
*/
QgsRelation();
/**
* Creates a relation from an XML structure. Used for reading .qgs projects.
*
* @param node The dom node containing the relation information
*
* @return A relation
*/
static QgsRelation createFromXML( const QDomNode& node );
/**
* Writes a relation to an XML structure. Used for saving .qgs projects
*
* @param node The parent node in which the relation will be created
* @param doc The document in which the relation will be saved
*/
void writeXML( QDomNode& node, QDomDocument& doc ) const;
/**
* Set a name for this relation
*
* @param id
*/
void setRelationId( QString id );
/**
* Set a name for this relation
*
* @param name
*/
void setRelationName( QString name );
/**
* Set the referencing layer id. This layer will be searched in the registry.
*
* @param id
*/
void setReferencingLayer( QString id );
/**
* Set the referenced layer id. This layer will be searched in the registry.
*
* @param id
*/
void setReferencedLayer( QString id );
/**
* Add a field pairs which is part of this relation
* The first element of each pair are the field names fo the foreign key.
* The second element of each pair are the field names of the matching primary key.
*
* @param referencingField The field name on the referencing layer (FK)
* @param referencedField The field name on the referenced layer (PK)
*/
void addFieldPair( QString referencingField, QString referencedField );
/**
* Creates an iterator which returns all the features on the referencing (child) layer
* which have a foreign key pointing to the provided feature.
*
* @param feature A feature from the referenced (parent) layer
*
* @return An iterator with all the referenced features
*/
QgsFeatureIterator getRelatedFeatures( const QgsFeature& feature ) const;
/**
* Creates a request to return all the features on the referencing (child) layer
* which have a foreign key pointing to the provided feature.
*
* @param feature A feature from the referenced (parent) layer
*
* @return An request for all the referenced features
*/
QgsFeatureRequest getRelatedFeaturesRequest( const QgsFeature& feature ) const;
const QString name() const;
/**
* The id
* @return
*/
const QString& id() const;
/**
* Access the referencing (child) layer's id
* This is the layer which has the field(s) which point to another layer
*
* @return The id of the referencing layer
*/
QString referencingLayerId() const;
/**
* Access the referencing (child) layer
* This is the layer which has the field(s) which point to another layer
*
* @return The referencing layer
*/
QgsVectorLayer* referencingLayer() const;
/**
* Access the referenced (parent) layer's id
*
* @return The id of the referenced layer
*/
QString referencedLayerId() const;
/**
* Access the referenced (parent) layer
*
* @return referenced layer
*/
QgsVectorLayer* referencedLayer() const;
/**
* Returns the field pairs which form this relation
* The first element of each pair are the field names fo the foreign key.
* The second element of each pair are the field names of the matching primary key.
*
* @return The fields forming the relation
*/
QMap< QString, QString > fieldPairs() const;
%MethodCode
QList< QgsRelation::FieldPair > pairs = sipCpp->fieldPairs();
Q_FOREACH( const QgsRelation::FieldPair& pair, pairs )
{
sipRes->insert( pair.first, pair.second );
}
%End
/**
* Returns the validity of this relation. Don't use the information if it's not valid.
*
* @return true if the relation is valid
*/
bool isValid() const;
};

View File

@ -5,11 +5,12 @@ class QgsAttributeDialog : QObject
%End
public:
QgsAttributeDialog( QgsVectorLayer *vl, QgsFeature *thepFeature, bool featureOwner, QgsDistanceArea myDa, QWidget* parent = 0, bool showDialogButtons = true );
QgsAttributeDialog( QgsVectorLayer *vl, QgsFeature *thepFeature, bool featureOwner, QgsDistanceArea myDa, QWidget* parent = 0, bool showDialogButtons = true ) /Deprecated/;
QgsAttributeDialog( QgsVectorLayer *vl, QgsFeature *thepFeature, bool featureOwner, QWidget* parent = 0, bool showDialogButtons = true );
void saveGeometry();
void restoreGeometry();
QDialog *dialog();
QgsFeature* feature();
const QgsFeature* feature();
public slots:
void accept();

View File

@ -260,6 +260,10 @@
#include "nodetool/qgsmaptoolnodetool.h"
// Editor widgets
#include "qgseditorwidgetregistry.h"
#include "qgsrelationreferencefactory.h"
//
// Conditional Includes
//
@ -577,6 +581,13 @@ QgisApp::QgisApp( QSplashScreen *splash, bool restorePlugins, QWidget * parent,
mVectorLayerTools = new QgsGuiVectorLayerTools();
// Init the editor widget types
QgsEditorWidgetRegistry* editorWidgetRegistry = QgsEditorWidgetRegistry::instance();
QgsAttributeEditorContext context;
context.setVectorLayerTools( vectorLayerTools() );
editorWidgetRegistry->registerWidget( "RelationReference", new QgsRelationReferenceFactory( context, tr( "Relation Reference" ) ) );
mInternalClipboard = new QgsClipboard; // create clipboard
connect( mInternalClipboard, SIGNAL( changed() ), this, SLOT( clipboardChanged() ) );
mQgisInterface = new QgisAppInterface( this ); // create the interfce

View File

@ -609,7 +609,7 @@ void QgisAppInterface::cacheloadForm( QString uifile )
}
}
QDialog* QgisAppInterface::getFeatureForm( QgsVectorLayer *l, QgsFeature &f )
QDialog* QgisAppInterface::getFeatureForm( QgsVectorLayer *l, QgsFeature &feature )
{
QgsDistanceArea myDa;
@ -617,10 +617,15 @@ QDialog* QgisAppInterface::getFeatureForm( QgsVectorLayer *l, QgsFeature &f )
myDa.setEllipsoidalMode( QgisApp::instance()->mapCanvas()->mapRenderer()->hasCrsTransformEnabled() );
myDa.setEllipsoid( QgsProject::instance()->readEntry( "Measure", "/Ellipsoid", GEO_NONE ) );
QgsAttributeDialog *dialog = new QgsAttributeDialog( l, &f, false, myDa );
QgsAttributeDialog *dialog = new QgsAttributeDialog( l, &feature, false, NULL, true );
return dialog->dialog();
}
QgsVectorLayerTools* QgisAppInterface::vectorLayerTools()
{
return qgis->vectorLayerTools();
}
QList<QgsMapLayer *> QgisAppInterface::editableLayers( bool modified ) const
{
return qgis->editableLayers( modified );

View File

@ -423,15 +423,34 @@ class APP_EXPORT QgisAppInterface : public QgisInterface
virtual QAction *actionCheckQgisVersion();
virtual QAction *actionAbout();
//! open feature form
// returns true when dialog was accepted
// @param l vector layer
// @param f feature to show/modify
// @param updateFeatureOnly only update the feature update (don't change any attributes of the layer)
// @added in 1.6
/**
* Open feature form
* returns true when dialog was accepted
* @param l vector layer
* @param f feature to show/modify
* @param updateFeatureOnly only update the feature update (don't change any attributes of the layer)
* @note added in 1.6
*/
virtual bool openFeatureForm( QgsVectorLayer *l, QgsFeature &f, bool updateFeatureOnly = false );
virtual QDialog* getFeatureForm( QgsVectorLayer *l, QgsFeature &f );
/**
* Returns a feature form for a given feature
*
* @param layer The layer for which the dialog will be created
* @param feature The feature for which the dialog will be created
*
* @return A feature form
*/
virtual QDialog* getFeatureForm( QgsVectorLayer *layer, QgsFeature &feature );
/**
* Access the vector layer tools instance.
* With the help of this you can access methods like addFeature, startEditing
* or stopEditing while giving the user the appropriate dialogs.
*
* @return An instance of the vector layer tools
*/
virtual QgsVectorLayerTools* vectorLayerTools();
/** This method is only needed when using a UI form with a custom widget plugin and calling
* openFeatureForm or getFeatureForm from Python (PyQt4) and you havn't used the info tool first.
@ -449,11 +468,13 @@ class APP_EXPORT QgisAppInterface : public QgisInterface
/** Return vector layers in edit mode
* @param modified whether to return only layers that have been modified
* @returns list of layers in legend order, or empty list
* @note added in 1.9 */
* @note added in 1.9
*/
virtual QList<QgsMapLayer *> editableLayers( bool modified = false ) const;
/** Get timeout for timed messages: default of 5 seconds
* @note added in 1.9 */
* @note added in 1.9
*/
virtual int messageTimeout();
signals:

View File

@ -24,6 +24,7 @@
#include "qgslogger.h"
#include "qgsmaplayerregistry.h"
#include "qgsproject.h"
#include "qgsrelationmanager.h"
#include "qgsvectordataprovider.h"
#include "qgsvectorlayer.h"
@ -96,9 +97,23 @@ QgsFieldsProperties::QgsFieldsProperties( QgsVectorLayer *layer, QWidget* parent
connect( mDesignerTree, SIGNAL( itemSelectionChanged() ), this, SLOT( onAttributeSelectionChanged() ) );
connect( mFieldsList, SIGNAL( itemSelectionChanged() ), this, SLOT( onAttributeSelectionChanged() ) );
mRelationsList = new DragList( mRelationsFrame );
mRelationsFrameLayout->addWidget( mRelationsList );
mRelationsList->setColumnCount( RelColCount );
mRelationsList->setDragDropMode( QAbstractItemView::DragOnly );
mRelationsList->setSelectionMode( QAbstractItemView::SingleSelection );
mRelationsList->setSelectionBehavior( QAbstractItemView::SelectRows );
mRelationsList->setHorizontalHeaderItem( RelIdCol, new QTableWidgetItem( tr( "Id" ) ) );
mRelationsList->setHorizontalHeaderItem( RelNameCol, new QTableWidgetItem( tr( "Name" ) ) );
mRelationsList->setHorizontalHeaderItem( RelLayerCol, new QTableWidgetItem( tr( "Layer" ) ) );
mRelationsList->setHorizontalHeaderItem( RelFieldCol, new QTableWidgetItem( tr( "Field" ) ) );
mRelationsList->verticalHeader()->hide();
leEditForm->setText( layer->editForm() );
leEditFormInit->setText( layer->editFormInit() );
loadRelations();
updateButtons();
}
@ -135,6 +150,10 @@ QTreeWidgetItem *QgsFieldsProperties::loadAttributeEditorTreeItem( QgsAttributeE
newWidget = mDesignerTree->addItem( parent, DesignerTreeItemData( DesignerTreeItemData::Field, widgetDef->name() ) );
break;
case QgsAttributeEditorElement::AeTypeRelation:
newWidget = mDesignerTree->addItem( parent, DesignerTreeItemData( DesignerTreeItemData::Field, widgetDef->name() ) );
break;
case QgsAttributeEditorElement::AeTypeContainer:
{
newWidget = mDesignerTree->addItem( parent, DesignerTreeItemData( DesignerTreeItemData::Container, widgetDef->name() ) );
@ -235,6 +254,40 @@ void QgsFieldsProperties::setRow( int row, int idx, const QgsField &field )
mFieldsList->setItem( row, attrWFSCol, wfsAttrItem );
}
void QgsFieldsProperties::loadRelations()
{
mRelationsList->setRowCount( 0 );
QList<QgsRelation> relations = QgsProject::instance()->relationManager()->referencedRelations( mLayer );
int idx = 0;
Q_FOREACH( const QgsRelation& relation, relations )
{
mRelationsList->insertRow( idx );
QTableWidgetItem* item = new QTableWidgetItem( relation.name() );
item->setFlags( Qt::ItemIsDragEnabled | Qt::ItemIsEnabled | Qt::ItemIsSelectable );
DesignerTreeItemData itemData( DesignerTreeItemData::Relation, QString( "%1" ).arg( relation.id() ) );
item->setData( DesignerTreeRole, itemData.asQVariant() );
mRelationsList->setItem( idx, RelNameCol, item );
item = new QTableWidgetItem( relation.referencingLayer()->name() );
item->setFlags( Qt::ItemIsDragEnabled | Qt::ItemIsEnabled | Qt::ItemIsSelectable );
mRelationsList->setItem( idx, RelLayerCol, item );
item = new QTableWidgetItem( relation.fieldPairs().first().referencingField() );
item->setFlags( Qt::ItemIsDragEnabled | Qt::ItemIsEnabled | Qt::ItemIsSelectable );
mRelationsList->setItem( idx, RelFieldCol, item );
item = new QTableWidgetItem( relation.id() );
item->setFlags( Qt::ItemIsDragEnabled | Qt::ItemIsEnabled | Qt::ItemIsSelectable );
mRelationsList->setItem( idx, RelIdCol, item );
++idx;
}
}
void QgsFieldsProperties::on_mAddItemButton_clicked()
{
QList<QTableWidgetItem*> listItems = mFieldsList->selectedItems();
@ -693,6 +746,13 @@ QgsAttributeEditorElement* QgsFieldsProperties::createAttributeEditorWidget( QTr
break;
}
case DesignerTreeItemData::Relation:
{
QgsRelation relation = QgsProject::instance()->relationManager()->relation( itemData.name() );
widgetDef = new QgsAttributeEditorRelation( itemData.name(), relation, parent );
break;
}
case DesignerTreeItemData::Container:
{
QgsAttributeEditorContainer* container = new QgsAttributeEditorContainer( itemData.name(), parent );

View File

@ -43,6 +43,7 @@ class APP_EXPORT QgsFieldsProperties : public QWidget, private Ui_QgsFieldsPrope
enum Type
{
Field,
Relation,
Container
};
@ -159,6 +160,8 @@ class APP_EXPORT QgsFieldsProperties : public QWidget, private Ui_QgsFieldsPrope
void loadRows();
void setRow( int row, int idx, const QgsField &field );
void loadRelations();
void loadAttributeEditorTree();
QTreeWidgetItem *loadAttributeEditorTreeItem( QgsAttributeEditorElement* const widgetDef, QTreeWidgetItem* parent );
@ -197,6 +200,7 @@ class APP_EXPORT QgsFieldsProperties : public QWidget, private Ui_QgsFieldsPrope
QgsVectorLayer* mLayer;
DesignerTree* mDesignerTree;
DragList* mFieldsList;
DragList* mRelationsList;
// Holds all the first column items (header: id) of the table.
// The index in the list is the fieldIdx, and therefore acts as a mapping
@ -219,6 +223,15 @@ class APP_EXPORT QgsFieldsProperties : public QWidget, private Ui_QgsFieldsPrope
attrColCount,
};
enum relationColumns
{
RelNameCol = 0,
RelLayerCol,
RelFieldCol,
RelIdCol,
RelColCount
};
static QMap< QgsVectorLayer::EditType, QString > editTypeMap;
static void setupEditTypes();
static QString editTypeButtonText( QgsVectorLayer::EditType type );

View File

@ -43,6 +43,9 @@
#include "qgsstylev2managerdialog.h"
#include "qgsvectorcolorrampv2.h"
#include "qgssymbolv2selectordialog.h"
#include "qgsrelationmanagerdialog.h"
#include "qgsrelationmanager.h"
#include "qgisapp.h"
//qt includes
#include <QColorDialog>
@ -442,6 +445,20 @@ QgsProjectProperties::QgsProjectProperties( QgsMapCanvas* mapCanvas, QWidget *pa
resetPythonMacros();
}
// Initialize relation manager
mRelationManagerDlg = new QgsRelationManagerDialog( QgsProject::instance()->relationManager(), mTabRelations );
mTabRelations->layout()->addWidget( mRelationManagerDlg );
QList<QgsVectorLayer*> vectorLayers;
foreach ( QgsMapLayer* mapLayer, mapLayers.values() )
{
if ( QgsMapLayer::VectorLayer == mapLayer->type() )
{
vectorLayers.append( qobject_cast<QgsVectorLayer*> ( mapLayer ) );
}
}
mRelationManagerDlg->setLayers( vectorLayers );
// Update projection selector (after mLayerSrsId is set)
bool myProjectionEnabled = myRenderer->hasCrsTransformEnabled();
bool onFlyChecked = cbxProjectionEnabled->isChecked();
@ -794,6 +811,8 @@ void QgsProjectProperties::apply()
}
QgsProject::instance()->writeEntry( "Macros", "/pythonCode", pythonMacros );
QgsProject::instance()->relationManager()->setRelations( mRelationManagerDlg->relations() );
//todo XXX set canvas color
emit refresh();
}

View File

@ -24,6 +24,7 @@
#include "qgscontexthelp.h"
class QgsMapCanvas;
class QgsRelationManagerDialog;
class QgsStyleV2;
/*! Dialog to set project level properties
@ -162,6 +163,7 @@ class APP_EXPORT QgsProjectProperties : public QgsOptionsDialogBase, private Ui:
void refresh();
private:
QgsRelationManagerDialog *mRelationManagerDlg;
QgsMapCanvas* mMapCanvas;
QgsStyleV2* mStyle;

View File

@ -106,6 +106,8 @@ SET(QGIS_CORE_SRCS
qgsprovidermetadata.cpp
qgsproviderregistry.cpp
qgspythonrunner.cpp
qgsrelation.cpp
qgsrelationmanager.cpp
qgsrendercontext.cpp
qgsrenderchecker.cpp
qgsrectangle.cpp
@ -311,6 +313,7 @@ SET(QGIS_CORE_MOC_HDRS
qgspluginlayer.h
qgsproject.h
qgsrunprocess.h
qgsrelationmanager.h
qgsvectorlayer.h
qgsvectorlayereditbuffer.h
qgsnetworkaccessmanager.h
@ -429,6 +432,8 @@ SET(QGIS_CORE_HDRS
qgsrectangle.h
qgsrendercontext.h
qgsrenderchecker.h
qgsrelation.h
qgsrelationmanager.h
qgsrunprocess.h
qgsscalecalculator.h
qgssnapper.h

View File

@ -56,7 +56,7 @@ QgsFeatureRequest& QgsFeatureRequest::operator=( const QgsFeatureRequest & rh )
mFilterFids = rh.mFilterFids;
if ( rh.mFilterExpression )
{
mFilterExpression = new QgsExpression( rh.mFilterExpression->expression() );
mFilterExpression = new QgsExpression( rh.mFilterExpression->dump() );
}
else
{
@ -144,7 +144,7 @@ bool QgsFeatureRequest::acceptFeature( const QgsFeature& feature )
break;
case QgsFeatureRequest::FilterFid:
if ( feature.id () == mFilterFid )
if ( feature.id() == mFilterFid )
return true;
else
return false;
@ -158,7 +158,7 @@ bool QgsFeatureRequest::acceptFeature( const QgsFeature& feature )
break;
case QgsFeatureRequest::FilterFids:
if ( mFilterFids.contains ( feature.id () ) )
if ( mFilterFids.contains( feature.id() ) )
return true;
else
return false;

View File

@ -130,7 +130,6 @@ class CORE_EXPORT QgsFeatureRequest
bool acceptFeature( const QgsFeature& feature );
// TODO: in future
// void setFilterExpression(const QString& expression); // using QgsExpression
// void setFilterNativeExpression(con QString& expr); // using provider's SQL (if supported)
// void setLimit(int limit);

View File

@ -20,18 +20,19 @@
#include <deque>
#include <memory>
#include "qgslogger.h"
#include "qgsrectangle.h"
#include "qgsvectorlayer.h"
#include "qgsrasterlayer.h"
#include "qgsmaplayerregistry.h"
#include "qgsdatasourceuri.h"
#include "qgsexception.h"
#include "qgsprojectproperty.h"
#include "qgsprojectfiletransform.h"
#include "qgsprojectversion.h"
#include "qgslogger.h"
#include "qgsmaplayerregistry.h"
#include "qgspluginlayer.h"
#include "qgspluginlayerregistry.h"
#include "qgsdatasourceuri.h"
#include "qgsprojectfiletransform.h"
#include "qgsprojectproperty.h"
#include "qgsprojectversion.h"
#include "qgsrasterlayer.h"
#include "qgsrectangle.h"
#include "qgsrelationmanager.h"
#include "qgsvectorlayer.h"
#include <QApplication>
#include <QFileInfo>
@ -332,7 +333,9 @@ struct QgsProject::Imp
QgsProject::QgsProject()
: imp_( new QgsProject::Imp ), mBadLayerHandler( new QgsProjectBadLayerDefaultHandler() )
: imp_( new QgsProject::Imp )
, mBadLayerHandler( new QgsProjectBadLayerDefaultHandler() )
, mRelationManager( new QgsRelationManager( this ) )
{
// Set some default project properties
// XXX THESE SHOULD BE MOVED TO STATUSBAR RELATED SOURCE
@ -349,6 +352,7 @@ QgsProject::QgsProject()
QgsProject::~QgsProject()
{
delete mBadLayerHandler;
delete mRelationManager;
// note that std::auto_ptr automatically deletes imp_ when it's destroyed
} // QgsProject dtor
@ -717,7 +721,6 @@ QPair< bool, QList<QDomNode> > QgsProject::_getMapLayers( QDomDocument const &do
} // _getMapLayers
bool QgsProject::addLayer( const QDomElement& layerElem, QList<QDomNode>& brokenNodes, QList< QPair< QgsVectorLayer*, QDomElement > >& vectorLayerList )
{
QString type = layerElem.attribute( "type" );
@ -865,6 +868,7 @@ bool QgsProject::read()
imp_->clear();
mEmbeddedLayers.clear();
mRelationManager->clear();
// now get any properties
_getProperties( *doc, imp_->properties_ );
@ -1801,3 +1805,8 @@ QString QgsProject::homePath() const
return pfi.canonicalPath();
}
QgsRelationManager* QgsProject::relationManager() const
{
return mRelationManager;
}

View File

@ -41,6 +41,7 @@ class QDomNode;
class QgsMapLayer;
class QgsProjectBadLayerHandler;
class QgsRelationManager;
class QgsVectorLayer;
/** \ingroup core
@ -281,10 +282,10 @@ class CORE_EXPORT QgsProject : public QObject
@note added in 1.4 */
void setBadLayerHandler( QgsProjectBadLayerHandler* handler );
/**Returns project file path if layer is embedded from other project file. Returns empty string if layer is not embedded*/
/** Returns project file path if layer is embedded from other project file. Returns empty string if layer is not embedded*/
QString layerIsEmbedded( const QString& id ) const;
/**Creates a maplayer instance defined in an arbitrary project file. Caller takes ownership
/** Creates a maplayer instance defined in an arbitrary project file. Caller takes ownership
@return the layer or 0 in case of error
@note: added in version 1.8
@note not available in python bindings
@ -292,21 +293,21 @@ class CORE_EXPORT QgsProject : public QObject
bool createEmbeddedLayer( const QString& layerId, const QString& projectFilePath, QList<QDomNode>& brokenNodes,
QList< QPair< QgsVectorLayer*, QDomElement > >& vectorLayerList, bool saveFlag = true );
/**Convenience function to set snap settings per layer
/** Convenience function to set snap settings per layer
@note added in version 1.9*/
void setSnapSettingsForLayer( const QString& layerId, bool enabled, QgsSnapper::SnappingType type, QgsTolerance::UnitType unit, double tolerance,
bool avoidIntersection );
/**Convenience function to query snap settings of a layer
/** Convenience function to query snap settings of a layer
@note added in version 1.9*/
bool snapSettingsForLayer( const QString& layerId, bool& enabled, QgsSnapper::SnappingType& type, QgsTolerance::UnitType& units, double& tolerance,
bool& avoidIntersection ) const;
/**Convenience function to set topological editing
/** Convenience function to set topological editing
@note added in version 1.9*/
void setTopologicalEditing( bool enabled );
/**Convenience function to query topological editing status
/** Convenience function to query topological editing status
@note added in version 1.9*/
bool topologicalEditing() const;
@ -315,6 +316,8 @@ class CORE_EXPORT QgsProject : public QObject
@note added in version 2.0 */
QString homePath() const;
QgsRelationManager* relationManager() const;
protected:
/** Set error message from read/write operation
@ -398,6 +401,8 @@ class CORE_EXPORT QgsProject : public QObject
void snapSettings( QStringList& layerIdList, QStringList& enabledList, QStringList& snapTypeList, QStringList& snapUnitList, QStringList& toleranceUnitList,
QStringList& avoidIntersectionList ) const;
QgsRelationManager* mRelationManager;
}; // QgsProject

258
src/core/qgsrelation.cpp Normal file
View File

@ -0,0 +1,258 @@
/***************************************************************************
qgsrelation.cpp
--------------------------------------
Date : 29.4.2013
Copyright : (C) 2013 Matthias Kuhn
Email : matthias dot kuhn at gmx dot ch
***************************************************************************
* *
* 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 "qgsrelation.h"
#include "qgsapplication.h"
#include "qgslogger.h"
#include "qgsmaplayerregistry.h"
#include "qgsvectorlayer.h"
QgsRelation::QgsRelation()
: mReferencingLayer( NULL )
, mReferencedLayer( NULL )
, mValid( false )
{
}
QgsRelation QgsRelation::createFromXML( const QDomNode &node )
{
QDomElement elem = node.toElement();
if ( elem.tagName() != "relation" )
{
QgsLogger::warning( QApplication::translate( "QgsRelation", "Cannot create relation. Unexpected tag '%1'" ).arg( elem.tagName() ) );
}
QgsRelation relation;
QString referencingLayerId = elem.attribute( "referencingLayer" );
QString referencedLayerId = elem.attribute( "referencedLayer" );
QString id = elem.attribute( "id" );
QString name = elem.attribute( "name" );
const QMap<QString, QgsMapLayer*>& mapLayers = QgsMapLayerRegistry::instance()->mapLayers();
QgsMapLayer* referencingLayer = mapLayers[referencingLayerId];
QgsMapLayer* referencedLayer = mapLayers[referencedLayerId];;
if ( NULL == referencingLayer )
{
QgsLogger::warning( QApplication::translate( "QgsRelation", "Relation defined for layer '%1' which does not exist." ).arg( referencingLayerId ) );
}
else if ( QgsMapLayer::VectorLayer != referencingLayer->type() )
{
QgsLogger::warning( QApplication::translate( "QgsRelation", "Relation defined for layer '%1' which is not of type VectorLayer." ).arg( referencingLayerId ) );
}
if ( NULL == referencedLayer )
{
QgsLogger::warning( QApplication::translate( "QgsRelation", "Relation defined for layer '%1' which does not exist." ).arg( referencedLayerId ) );
}
else if ( QgsMapLayer::VectorLayer != referencedLayer->type() )
{
QgsLogger::warning( QApplication::translate( "QgsRelation", "Relation defined for layer '%1' which is not of type VectorLayer." ).arg( referencedLayerId ) );
}
relation.mReferencingLayerId = referencingLayerId;
relation.mReferencingLayer = qobject_cast<QgsVectorLayer*>( referencingLayer );
relation.mReferencedLayerId = referencedLayerId;
relation.mReferencedLayer = qobject_cast<QgsVectorLayer*>( referencedLayer );
relation.mRelationId = id;
relation.mRelationName = name;
QDomNodeList references = elem.elementsByTagName( "fieldRef" );
for ( int i = 0; i < references.size(); ++i )
{
QDomElement refEl = references.at( i ).toElement();
QString referencingField = refEl.attribute( "referencingField" );
QString referencedField = refEl.attribute( "referencedField" );
relation.addFieldPair( referencingField, referencedField );
}
relation.mValid = true;
return relation;
}
void QgsRelation::writeXML( QDomNode &node, QDomDocument &doc ) const
{
QDomElement elem = doc.createElement( "relation" );
elem.setAttribute( "id", mRelationId );
elem.setAttribute( "name", mRelationName );
elem.setAttribute( "referencingLayer", mReferencingLayerId );
elem.setAttribute( "referencedLayer", mReferencedLayerId );
foreach ( FieldPair fields, mFieldPairs )
{
QDomElement referenceElem = doc.createElement( "fieldRef" );
referenceElem.setAttribute( "referencingField", fields.first );
referenceElem.setAttribute( "referencedField", fields.second );
elem.appendChild( referenceElem );
}
node.appendChild( elem );
}
void QgsRelation::setRelationId( QString id )
{
mRelationId = id;
}
void QgsRelation::setRelationName( QString name )
{
mRelationName = name;
}
void QgsRelation::setReferencingLayer( QString id )
{
mReferencingLayerId = id;
updateRelationStatus();
}
void QgsRelation::setReferencedLayer( QString id )
{
mReferencedLayerId = id;
updateRelationStatus();
}
void QgsRelation::addFieldPair( QString referencingField, QString referencedField )
{
mFieldPairs << FieldPair( referencingField, referencedField );
updateRelationStatus();
}
void QgsRelation::addFieldPair( QgsRelation::FieldPair fieldPair )
{
mFieldPairs << fieldPair;
updateRelationStatus();
}
QgsFeatureIterator QgsRelation::getRelatedFeatures( const QgsFeature& feature ) const
{
return referencingLayer()->getFeatures( getRelatedFeaturesRequest( feature ) );
}
QgsFeatureRequest QgsRelation::getRelatedFeaturesRequest( const QgsFeature& feature ) const
{
QStringList conditions;
foreach ( const QgsRelation::FieldPair& fieldPair, mFieldPairs )
{
int referencingIdx = referencingLayer()->pendingFields().indexFromName( fieldPair.referencingField() );
QgsField referencingField = referencingLayer()->pendingFields().at( referencingIdx );
switch ( referencingField.type() )
{
case QVariant::String:
// Use quotes
conditions << QString( "\"%1\" = '%2'" ).arg( fieldPair.referencingField(), feature.attribute( fieldPair.referencedField() ).toString() );
break;
default:
// No quotes
conditions << QString( "\"%1\" = %2" ).arg( fieldPair.referencingField(), feature.attribute( fieldPair.referencedField() ).toString() );
break;
}
}
QgsFeatureRequest myRequest;
QgsDebugMsg( QString( "Filter conditions: '%1'" ).arg( conditions.join( " AND " ) ) );
myRequest.setFilterExpression( conditions.join( " AND " ) );
return myRequest;
}
const QString QgsRelation::name() const
{
return mRelationName;
}
const QString& QgsRelation::id() const
{
return mRelationId;
}
QString QgsRelation::referencingLayerId() const
{
return mReferencingLayerId;
}
QgsVectorLayer* QgsRelation::referencingLayer() const
{
return mReferencingLayer;
}
QString QgsRelation::referencedLayerId() const
{
return mReferencedLayerId;
}
QgsVectorLayer* QgsRelation::referencedLayer() const
{
return mReferencedLayer;
}
QList<QgsRelation::FieldPair> QgsRelation::fieldPairs() const
{
return mFieldPairs;
}
bool QgsRelation::isValid() const
{
return mValid;
}
void QgsRelation::updateRelationStatus()
{
const QMap<QString, QgsMapLayer*>& mapLayers = QgsMapLayerRegistry::instance()->mapLayers();
mReferencingLayer = qobject_cast<QgsVectorLayer*>( mapLayers[mReferencingLayerId] );
mReferencedLayer = qobject_cast<QgsVectorLayer*>( mapLayers[mReferencedLayerId] );
mValid = true;
if ( !mReferencedLayer || !mReferencingLayer )
{
mValid = false;
}
else
{
if ( mFieldPairs.count() < 1 )
{
mValid = false;
}
Q_FOREACH( const FieldPair& fieldPair, mFieldPairs )
{
if ( -1 == mReferencingLayer->fieldNameIndex( fieldPair.first )
|| -1 == mReferencedLayer->fieldNameIndex( fieldPair.second ) )
{
mValid = false;
}
}
}
}
void QgsRelation::runChecks()
{
}

227
src/core/qgsrelation.h Normal file
View File

@ -0,0 +1,227 @@
/***************************************************************************
qgsrelation.h
--------------------------------------
Date : 29.4.2013
Copyright : (C) 2013 Matthias Kuhn
Email : matthias dot kuhn at gmx dot ch
***************************************************************************
* *
* 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 QGSRELATION_H
#define QGSRELATION_H
#include <QList>
#include <QDomNode>
#include <QPair>
#include "qgsfield.h"
#include "qgsfeatureiterator.h"
class QgsVectorLayer;
class CORE_EXPORT QgsRelation
{
public:
/**
* Defines a relation between matchin fields of the two involved tables of a relation.
* Often, a relation is only defined by just one FieldPair with the name of the foreign key
* column of the referencing table as first element and the name of the primkary key column
* of the referenced table as the second element.
*
*/
class FieldPair : public QPair< QString, QString >
{
public:
//! Default constructor: NULL strings
FieldPair()
: QPair< QString, QString >() {}
//! Constructor which takes two fields
FieldPair( QString referencingField, QString referencedField )
: QPair< QString, QString >( referencingField, referencedField ) {}
//! Get the name of the referencing field
const QString& referencingField() const { return first; }
//! Get the name of the referenced field
const QString& referencedField() const { return second; }
};
/**
* Default constructor. Creates an invalid relation.
*/
QgsRelation();
/**
* Creates a relation from an XML structure. Used for reading .qgs projects.
*
* @param node The dom node containing the relation information
*
* @return A relation
*/
static QgsRelation createFromXML( const QDomNode& node );
/**
* Writes a relation to an XML structure. Used for saving .qgs projects
*
* @param node The parent node in which the relation will be created
* @param doc The document in which the relation will be saved
*/
void writeXML( QDomNode& node, QDomDocument& doc ) const;
/**
* Set a name for this relation
*
* @param id
*/
void setRelationId( QString id );
/**
* Set a name for this relation
*
* @param name
*/
void setRelationName( QString name );
/**
* Set the referencing layer id. This layer will be searched in the registry.
*
* @param id
*/
void setReferencingLayer( QString id );
/**
* Set the referenced layer id. This layer will be searched in the registry.
*
* @param id
*/
void setReferencedLayer( QString id );
/**
* Add a field pairs which is part of this relation
* The first element of each pair are the field names fo the foreign key.
* The second element of each pair are the field names of the matching primary key.
*
* @param referencingField The field name on the referencing layer (FK)
* @param referencedField The field name on the referenced layer (PK)
*/
void addFieldPair( QString referencingField, QString referencedField );
/**
* Add a field pairs which is part of this relation
* The first element of each pair are the field names fo the foreign key.
* The second element of each pair are the field names of the matching primary key.
*
* @param fieldPair A pair of two strings
*/
void addFieldPair( FieldPair fieldPair );
/**
* Creates an iterator which returns all the features on the referencing (child) layer
* which have a foreign key pointing to the provided feature.
*
* @param feature A feature from the referenced (parent) layer
*
* @return An iterator with all the referenced features
*/
QgsFeatureIterator getRelatedFeatures( const QgsFeature& feature ) const;
/**
* Creates a request to return all the features on the referencing (child) layer
* which have a foreign key pointing to the provided feature.
*
* @param feature A feature from the referenced (parent) layer
*
* @return An request for all the referenced features
*/
QgsFeatureRequest getRelatedFeaturesRequest( const QgsFeature& feature ) const;
const QString name() const;
/**
* The id
* @return
*/
const QString& id() const;
/**
* Access the referencing (child) layer's id
* This is the layer which has the field(s) which point to another layer
*
* @return The id of the referencing layer
*/
QString referencingLayerId() const;
/**
* Access the referencing (child) layer
* This is the layer which has the field(s) which point to another layer
*
* @return The referencing layer
*/
QgsVectorLayer* referencingLayer() const;
/**
* Access the referenced (parent) layer's id
*
* @return The id of the referenced layer
*/
QString referencedLayerId() const;
/**
* Access the referenced (parent) layer
*
* @return referenced layer
*/
QgsVectorLayer* referencedLayer() const;
/**
* Returns the field pairs which form this relation
* The first element of each pair are the field names fo the foreign key.
* The second element of each pair are the field names of the matching primary key.
*
* @return The fields forming the relation
*/
QList< FieldPair > fieldPairs() const;
/**
* Returns the validity of this relation. Don't use the information if it's not valid.
*
* @return true if the relation is valid
*/
bool isValid() const;
protected:
void updateRelationStatus();
void runChecks();
private:
/** Unique Id */
QString mRelationId;
/** Human redable name*/
QString mRelationName;
/** The child layer */
QString mReferencingLayerId;
/** The child layer */
QgsVectorLayer* mReferencingLayer;
/** The parent layer id */
QString mReferencedLayerId;
/** The parent layer */
QgsVectorLayer* mReferencedLayer;
/** A list of fields which define the relation.
* In most cases there will be only one value, but multiple values
* are supported for composited foreign keys.
* The first field is on the referencing layer, the second on the referenced */
QList< FieldPair > mFieldPairs;
bool mValid;
};
// Register QgsRelation for usage with QVariant
Q_DECLARE_METATYPE( QgsRelation )
#endif // QGSRELATION_H

View File

@ -0,0 +1,172 @@
/***************************************************************************
qgsrelationmanager.cpp
--------------------------------------
Date : 1.3.2013
Copyright : (C) 2013 Matthias Kuhn
Email : matthias dot kuhn at gmx dot ch
***************************************************************************
* *
* 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 "qgsrelationmanager.h"
#include "qgsapplication.h"
#include "qgslogger.h"
#include "qgsproject.h"
#include "qgsvectorlayer.h"
QgsRelationManager::QgsRelationManager( QgsProject* project )
: QObject( project )
, mProject( project )
{
connect( project, SIGNAL( readProject( const QDomDocument& ) ), SLOT( readProject( const QDomDocument& ) ) );
connect( project, SIGNAL( writeProject( QDomDocument& ) ), SLOT( writeProject( QDomDocument& ) ) );
}
void QgsRelationManager::setRelations( const QList<QgsRelation>& relations )
{
mRelations.clear();
foreach ( const QgsRelation& rel, relations )
{
addRelation( rel );
}
}
const QMap<QString, QgsRelation>& QgsRelationManager::relations() const
{
return mRelations;
}
void QgsRelationManager::addRelation( const QgsRelation& relation )
{
if ( !relation.isValid() )
return;
mRelations.insert( relation.id(), relation );
mProject->dirty( true );
}
void QgsRelationManager::removeRelation( const QString& name )
{
mRelations.remove( name );
}
void QgsRelationManager::removeRelation( const QgsRelation& relation )
{
mRelations.remove( relation.id() );
}
QgsRelation QgsRelationManager::relation( const QString& id ) const
{
return mRelations.value( id );
}
void QgsRelationManager::clear()
{
mRelations.clear();
}
QList<QgsRelation> QgsRelationManager::referencingRelations( QgsVectorLayer* layer, int fieldIdx ) const
{
if ( !layer )
{
return mRelations.values();
}
QList<QgsRelation> relations;
foreach ( const QgsRelation& rel, mRelations )
{
if ( rel.referencingLayer() == layer )
{
if ( fieldIdx != -2 )
{
bool containsField = false;
foreach ( const QgsRelation::FieldPair& fp, rel.fieldPairs() )
{
if ( fieldIdx == layer->fieldNameIndex( fp.referencingField() ) )
{
containsField = true;
break;
}
}
if ( !containsField )
{
continue;
}
}
relations.append( rel );
}
}
return relations;
}
QList<QgsRelation> QgsRelationManager::referencedRelations( QgsVectorLayer* layer ) const
{
if ( !layer )
{
return mRelations.values();
}
QList<QgsRelation> relations;
foreach ( const QgsRelation& rel, mRelations )
{
if ( rel.referencedLayer() == layer )
{
relations.append( rel );
}
}
return relations;
}
void QgsRelationManager::readProject( const QDomDocument & doc )
{
mRelations.clear();
QDomNodeList nodes = doc.elementsByTagName( "relations" );
if ( nodes.count() )
{
QDomNode node = nodes.item( 0 );
QDomNodeList relationNodes = node.childNodes();
int relCount = relationNodes.count();
for ( int i = 0; i < relCount; ++i )
{
addRelation( QgsRelation::createFromXML( relationNodes.at( i ) ) );
}
}
else
{
QgsDebugMsg( "No relations data present in this document" );
}
emit( relationsLoaded() );
}
void QgsRelationManager::writeProject( QDomDocument & doc )
{
QDomNodeList nl = doc.elementsByTagName( "qgis" );
if ( !nl.count() )
{
QgsDebugMsg( "Unable to find qgis element in project file" );
return;
}
QDomNode qgisNode = nl.item( 0 ); // there should only be one
QDomElement relationsNode = doc.createElement( "relations" );
qgisNode.appendChild( relationsNode );
foreach ( const QgsRelation& relation, mRelations )
{
relation.writeXML( relationsNode, doc );
}
}

View File

@ -0,0 +1,66 @@
/***************************************************************************
qgsrelationmanager.h
--------------------------------------
Date : 1.3.2013
Copyright : (C) 2013 Matthias Kuhn
Email : matthias dot kuhn at gmx dot ch
***************************************************************************
* *
* 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 QGSRELATIONMANAGER_H
#define QGSRELATIONMANAGER_H
#include <QObject>
#include <QPair>
#include <QDomNode>
#include <QDomDocument>
#include "qgsrelation.h"
class QgsProject;
class QgsVectorLayer;
/**
* This class manages a set of relations between layers.
*/
class CORE_EXPORT QgsRelationManager : public QObject
{
Q_OBJECT
public:
explicit QgsRelationManager( QgsProject* project );
void setRelations( const QList<QgsRelation>& relations );
const QMap<QString, QgsRelation>& relations() const;
void addRelation( const QgsRelation& relation );
void removeRelation( const QString& name );
void removeRelation( const QgsRelation& relation );
QgsRelation relation( const QString& id ) const;
void clear();
QList<QgsRelation> referencingRelations( QgsVectorLayer* layer = NULL, int fieldIdx = -2 ) const;
QList<QgsRelation> referencedRelations( QgsVectorLayer* layer = NULL ) const;
signals:
void relationsLoaded();
public slots:
private slots:
void readProject( const QDomDocument &doc );
void writeProject( QDomDocument &doc );
private:
/** The references */
QMap<QString, QgsRelation> mRelations;
QgsProject* mProject;
};
#endif // QGSRELATIONMANAGER_H

View File

@ -168,11 +168,13 @@ class CORE_EXPORT QgsVectorDataProvider : public QgsDataProvider
*/
virtual void uniqueValues( int index, QList<QVariant> &uniqueValues, int limit = -1 );
/**Returns the possible enum values of an attribute. Returns an empty stringlist if a provider does not support enum types
or if the given attribute is not an enum type.
/**
* Returns the possible enum values of an attribute. Returns an empty stringlist if a provider does not support enum types
* or if the given attribute is not an enum type.
* @param index the index of the attribute
* @param enumList reference to the list to fill
@note: added in version 1.2*/
* @note: added in version 1.2
*/
virtual void enumValues( int index, QStringList& enumList ) { Q_UNUSED( index ); enumList.clear(); }
/**
@ -260,7 +262,9 @@ class CORE_EXPORT QgsVectorDataProvider : public QgsDataProvider
*/
int fieldNameIndex( const QString& fieldName ) const;
/**Return a map where the key is the name of the field and the value is its index*/
/**
* Return a map where the key is the name of the field and the value is its index
*/
QMap<QString, int> fieldNameMap() const;
/**
@ -313,17 +317,20 @@ class CORE_EXPORT QgsVectorDataProvider : public QgsDataProvider
/** Returns a list of available encodings */
static const QStringList &availableEncodings();
/* provider has errors to report
/**
* Provider has errors to report
* @note added in 1.7
*/
bool hasErrors();
/* clear recorded errors
/**
* Clear recorded errors
* @note added in 1.7
*/
void clearErrors();
/* get recorded errors
/**
* Get recorded errors
* @note added in 1.7
*/
QStringList errors();
@ -350,13 +357,13 @@ class CORE_EXPORT QgsVectorDataProvider : public QgsDataProvider
/** should provider fetch also features that don't have geometry? */
bool mFetchFeaturesWithoutGeom;
/**True if geometry should be added to the features in nextFeature calls*/
/** True if geometry should be added to the features in nextFeature calls*/
bool mFetchGeom;
/**List of attribute indices to fetch with nextFeature calls*/
/** List of attribute indices to fetch with nextFeature calls*/
QgsAttributeList mAttributesToFetch;
/**The names of the providers native types*/
/** The names of the providers native types*/
QList< NativeType > mNativeTypes;
void pushError( QString msg );
@ -368,7 +375,7 @@ class CORE_EXPORT QgsVectorDataProvider : public QgsDataProvider
/** old notation **/
QMap<QString, QVariant::Type> mOldTypeList;
// list of errors
/** list of errors */
QStringList mErrors;
static QStringList smEncodings;

View File

@ -52,6 +52,7 @@
#include "qgspoint.h"
#include "qgsproviderregistry.h"
#include "qgsrectangle.h"
#include "qgsrelationmanager.h"
#include "qgsrendercontext.h"
#include "qgscoordinatereferencesystem.h"
#include "qgsvectordataprovider.h"
@ -176,6 +177,8 @@ QgsVectorLayer::QgsVectorLayer( QString vectorLayerPath,
}
connect( this, SIGNAL( selectionChanged( QgsFeatureIds, QgsFeatureIds, bool ) ), this, SIGNAL( selectionChanged() ) );
connect( QgsProject::instance()->relationManager(), SIGNAL( relationsLoaded() ), this, SLOT( onRelationsLoaded() ) );
} // QgsVectorLayer ctor
@ -2117,6 +2120,13 @@ QgsAttributeEditorElement* QgsVectorLayer::attributeEditorElementFromDomElement(
int idx = *( dataProvider()->fieldNameMap() ).find( name );
newElement = new QgsAttributeEditorField( name, idx, parent );
}
else if ( elem.tagName() == "attributeEditorRelation" )
{
// At this time, the relations are not loaded
// So we only grab the id and delegate the rest to onRelationsLoaded()
QString name = elem.attribute( "name" );
newElement = new QgsAttributeEditorRelation( name, elem.attribute( "relation", "[None]" ), parent );
}
return newElement;
}
@ -3834,6 +3844,23 @@ void QgsVectorLayer::invalidateSymbolCountedFlag()
mSymbolFeatureCounted = false;
}
void QgsVectorLayer::onRelationsLoaded()
{
Q_FOREACH( QgsAttributeEditorElement* elem, mAttributeEditorElements )
{
if ( elem->type() == QgsAttributeEditorElement::AeTypeContainer )
{
QgsAttributeEditorContainer* cont = dynamic_cast< QgsAttributeEditorContainer* >( elem );
QList<QgsAttributeEditorElement*> relations = cont->findElements( QgsAttributeEditorElement::AeTypeRelation );
Q_FOREACH( QgsAttributeEditorElement* relElem, relations )
{
QgsAttributeEditorRelation* rel = dynamic_cast< QgsAttributeEditorRelation* >( relElem );
rel->init( QgsProject::instance()->relationManager() );
}
}
}
}
QgsVectorLayer::ValueRelationData &QgsVectorLayer::valueRelation( int idx )
{
const QgsFields &fields = pendingFields();
@ -3855,6 +3882,11 @@ QgsVectorLayer::ValueRelationData &QgsVectorLayer::valueRelation( int idx )
return mValueRelations[fieldName];
}
QList<QgsRelation> QgsVectorLayer::referencingRelations( int idx )
{
return QgsProject::instance()->relationManager()->referencingRelations( this, idx );
}
QList<QgsAttributeEditorElement*> &QgsVectorLayer::attributeEditorElements()
{
return mAttributeEditorElements;
@ -4057,3 +4089,18 @@ bool QgsVectorLayer::applyNamedStyle( QString namedStyle, QString errorMsg )
return readSymbology( myRoot, errorMsg );
}
QDomElement QgsAttributeEditorRelation::toDomElement( QDomDocument& doc ) const
{
QDomElement elem = doc.createElement( "attributeEditorRelation" );
elem.setAttribute( "name", mName );
elem.setAttribute( "relation", mRelation.id() );
return elem;
}
bool QgsAttributeEditorRelation::init( QgsRelationManager* relationManager )
{
mRelation = relationManager->relation( mRelationId );
return mRelation.isValid();
}

View File

@ -31,6 +31,7 @@
#include "qgsfield.h"
#include "qgssnapper.h"
#include "qgsfield.h"
#include "qgsrelation.h"
class QPainter;
class QImage;
@ -44,6 +45,8 @@ class QgsGeometryVertexIndex;
class QgsLabel;
class QgsMapToPixel;
class QgsRectangle;
class QgsRelation;
class QgsRelationManager;
class QgsVectorDataProvider;
class QgsSingleSymbolRendererV2;
class QgsRectangle;
@ -68,6 +71,7 @@ class CORE_EXPORT QgsAttributeEditorElement : public QObject
{
AeTypeContainer,
AeTypeField,
AeTypeRelation,
AeTypeInvalid
};
@ -121,6 +125,37 @@ class CORE_EXPORT QgsAttributeEditorField : public QgsAttributeEditorElement
int mIdx;
};
/** @note Added in 2.1 */
class CORE_EXPORT QgsAttributeEditorRelation : public QgsAttributeEditorElement
{
public:
QgsAttributeEditorRelation( QString name , const QString relationId, QObject *parent )
: QgsAttributeEditorElement( AeTypeRelation, name, parent )
, mRelationId( relationId ) {}
QgsAttributeEditorRelation( QString name , const QgsRelation& relation, QObject *parent )
: QgsAttributeEditorElement( AeTypeRelation, name, parent )
, mRelationId( relation.id() )
, mRelation( relation ) {}
~QgsAttributeEditorRelation() {}
virtual QDomElement toDomElement( QDomDocument& doc ) const;
const QgsRelation& relation() const { return mRelation; }
/**
* Initializes the relation from the id
*
* @param relManager The relation manager to use for the initialization
* @return true if the relation was found in the relationmanager
*/
bool init( QgsRelationManager* relManager );
private:
QString mRelationId;
QgsRelation mRelation;
};
/** @note added in 1.7 */
struct CORE_EXPORT QgsVectorJoinInfo
{
@ -1202,6 +1237,22 @@ class CORE_EXPORT QgsVectorLayer : public QgsMapLayer
**/
ValueRelationData &valueRelation( int idx );
/**
* Get relations, where the foreign key is on this layer
*
* @param idx Only get relations, where idx forms part of the foreign key
* @return A list of relations
*/
QList<QgsRelation> referencingRelations( int idx );
/**
* Get relations, where the foreign key is on another layer, referencing this layer
*
* @param idx Only get relations, where idx forms part of the referenced key
* @return A list of relations
*/
QList<QgsRelation> referencedRelations( int idx );
/**access date format
* @note added in 1.9
*/
@ -1446,6 +1497,8 @@ class CORE_EXPORT QgsVectorLayer : public QgsMapLayer
void committedAttributeValuesChanges( const QString& layerId, const QgsChangedAttributesMap& changedAttributesValues );
void committedGeometriesChanges( const QString& layerId, const QgsGeometryMap& changedGeometries );
void saveLayerToProject();
/** Emitted when the font family defined for labeling layer is not found on system
* @note added in 1.9
*/
@ -1460,6 +1513,9 @@ class CORE_EXPORT QgsVectorLayer : public QgsMapLayer
/** Signal emitted when setLayerTransparency() is called */
void layerTransparencyChanged( int layerTransparency );
private slots:
void onRelationsLoaded();
protected:
/** Set the extent */
void setExtent( const QgsRectangle &rect );

View File

@ -26,7 +26,7 @@ QgsVectorLayerCache::QgsVectorLayerCache( QgsVectorLayer* layer, int cacheSize,
mCache.setMaxCost( cacheSize );
connect( mLayer, SIGNAL( featureDeleted( QgsFeatureId ) ), SLOT( featureDeleted( QgsFeatureId ) ) );
connect( mLayer, SIGNAL( featureAdded( QgsFeatureId ) ), SLOT( featureAdded( QgsFeatureId ) ) );
connect( mLayer, SIGNAL( featureAdded( QgsFeatureId ) ), SLOT( onFeatureAdded( QgsFeatureId ) ) );
connect( mLayer, SIGNAL( layerDeleted() ), SLOT( layerDeleted() ) );
setCacheGeometry( true );
@ -200,7 +200,7 @@ void QgsVectorLayerCache::featureDeleted( QgsFeatureId fid )
mCache.remove( fid );
}
void QgsVectorLayerCache::featureAdded( QgsFeatureId fid )
void QgsVectorLayerCache::onFeatureAdded( QgsFeatureId fid )
{
if ( mFullCache )
{
@ -212,6 +212,7 @@ void QgsVectorLayerCache::featureAdded( QgsFeatureId fid )
QgsFeature feat;
featureAtId( fid, feat );
}
emit( featureAdded( fid ) );
}
void QgsVectorLayerCache::attributeAdded( int field )

View File

@ -242,10 +242,19 @@ class CORE_EXPORT QgsVectorLayerCache : public QObject
*/
void attributeValueChanged( const QgsFeatureId& fid, const int& field, const QVariant &value );
/**
* Is emitted, when a new feature has been added to the layer and this cache.
* You should connect to this signal instead of the layers', if you want to be sure
* that this cache has updated information for the new feature
*
* @param fid The featureid of the changed feature
*/
void featureAdded( QgsFeatureId fid );
private slots:
void onAttributeValueChanged( QgsFeatureId fid, int field, const QVariant& value );
void featureDeleted( QgsFeatureId fid );
void featureAdded( QgsFeatureId fid );
void onFeatureAdded( QgsFeatureId fid );
void attributeAdded( int field );
void attributeDeleted( int field );
void geometryChanged( QgsFeatureId fid, QgsGeometry& geom );

View File

@ -54,35 +54,47 @@ editorwidgets/core/qgseditorconfigwidget.cpp
editorwidgets/core/qgseditorwidgetfactory.cpp
editorwidgets/core/qgseditorwidgetregistry.cpp
editorwidgets/core/qgseditorwidgetwrapper.cpp
editorwidgets/qgsrelationreferencewidget.cpp
editorwidgets/qgsrelationreferencefactory.cpp
editorwidgets/qgsrelreferenceconfigdlg.cpp
qgisgui.cpp
qgisinterface.cpp
qgsannotationitem.cpp
qgsattributeeditor.cpp
qgsattributedialog.cpp
qgsbusyindicatordialog.cpp
qgslegendinterface.cpp
qgspluginmanagerinterface.cpp
qgsattributeeditor.cpp
qgsattributeeditorcontext.cpp
qgsblendmodecombobox.cpp
qgsbusyindicatordialog.cpp
qgscharacterselectdialog.cpp
qgscollapsiblegroupbox.cpp
qgscolorbutton.cpp
qgscolordialog.cpp
qgscomposerview.cpp
qgscomposerruler.cpp
qgscomposerview.cpp
qgscredentialdialog.cpp
qgscursors.cpp
qgsdatadefinedbutton.cpp
qgsdetaileditemdata.cpp
qgsdetaileditemdelegate.cpp
qgsdetaileditemwidget.cpp
qgsdetaileditemdata.cpp
qgsdialog.cpp
qgsencodingfiledialog.cpp
qgserrordialog.cpp
qgsfiledropedit.cpp
qgsexpressionbuilderdialog.cpp
qgsexpressionbuilderwidget.cpp
qgsexpressionhighlighter.cpp
qgsexpressionselectiondialog.cpp
qgsfeatureselectiondlg.cpp
qgsfieldvalidator.cpp
qgsfiledropedit.cpp
qgsfilterlineedit.cpp
qgsformannotationitem.cpp
qgshtmlannotationitem.cpp
qgshighlight.cpp
qgsgenericprojectionselector.cpp
qgshighlight.cpp
qgshtmlannotationitem.cpp
qgslegendinterface.cpp
qgsludialog.cpp
qgsmanageconnectionsdialog.cpp
qgsmapcanvas.cpp
qgsmapcanvasitem.cpp
@ -99,6 +111,7 @@ qgsmessagebar.cpp
qgsmessagebaritem.cpp
qgsmessageviewer.cpp
qgsmessagelogviewer.cpp
qgsmessageviewer.cpp
qgsnewhttpconnection.cpp
qgsnewvectorlayerdialog.cpp
qgsnumericsortlistviewitem.cpp
@ -106,26 +119,23 @@ qgsoptionsdialogbase.cpp
qgscredentialdialog.cpp
qgsattributeeditorcontext.cpp
qgsowssourceselect.cpp
qgspluginmanagerinterface.cpp
qgsprojectbadlayerguihandler.cpp
qgsprojectionselector.cpp
qgsrasterlayersaveasdialog.cpp
qgsquerybuilder.cpp
qgsrasterformatsaveoptionswidget.cpp
qgsrasterlayersaveasdialog.cpp
qgsrasterpyramidsoptionswidget.cpp
qgsrelationadddlg.cpp
qgsrelationeditor.cpp
qgsrelationmanagerdialog.cpp
qgsrubberband.cpp
qgsscalecombobox.cpp
qgssearchquerybuilder.cpp
qgssublayersdialog.cpp
qgssvgannotationitem.cpp
qgstextannotationitem.cpp
qgsvertexmarker.cpp
qgsludialog.cpp
qgssearchquerybuilder.cpp
qgsexpressionbuilderwidget.cpp
qgsexpressionbuilderdialog.cpp
qgsexpressionselectiondialog.cpp
qgsexpressionhighlighter.cpp
qgsquerybuilder.cpp
qgscollapsiblegroupbox.cpp
qgsfilterlineedit.cpp
qgssublayersdialog.cpp
)
IF (WITH_TOUCH)
@ -191,27 +201,37 @@ attributetable/qgsvectorlayerselectionmanager.h
editorwidgets/core/qgseditorconfigwidget.h
editorwidgets/core/qgseditorwidgetregistry.h
editorwidgets/core/qgseditorwidgetwrapper.h
editorwidgets/qgsrelationreferencewidget.h
editorwidgets/qgsrelreferenceconfigdlg.h
qgisinterface.h
qgsattributedialog.h
qgsattributeeditor.h
qgsblendmodecombobox.h
qgsbusyindicatordialog.h
qgscharacterselectdialog.h
qgscollapsiblegroupbox.h
qgscolordialog.h
qgscomposerview.h
qgscredentialdialog.h
qgsdatadefinedbutton.h
qgsdetaileditemdelegate.h
qgsdetaileditemwidget.h
qgsdialog.h
qgslegendinterface.h
qgspluginmanagerinterface.h
qgisinterface.h
qgsencodingfiledialog.h
qgserrordialog.h
qgsexpressionbuilderwidget.h
qgsexpressionhighlighter.h
qgsexpressionselectiondialog.h
qgsfeatureselectiondlg.h
qgsfieldvalidator.h
qgsfilterlineedit.h
qgsformannotationitem.h
qgshtmlannotationitem.h
qgsgenericprojectionselector.h
qgshtmlannotationitem.h
qgslegendinterface.h
qgslonglongvalidator.h
qgsludialog.h
qgsmanageconnectionsdialog.h
qgsmapcanvas.h
qgsmapoverviewcanvas.h
@ -219,28 +239,24 @@ qgsmaptoolemitpoint.h
qgsmaptoolidentify.h
qgsmessagebaritem.h
qgsmessagebar.h
qgsmessageviewer.h
qgsmessagelogviewer.h
qgsmessageviewer.h
qgsnewhttpconnection.h
qgsnewvectorlayerdialog.h
qgsoptionsdialogbase.h
qgscredentialdialog.h
qgsowssourceselect.h
qgsprojectionselector.h
qgsrasterlayersaveasdialog.h
qgsrasterformatsaveoptionswidget.h
qgsrasterpyramidsoptionswidget.h
qgsludialog.h
qgspluginmanagerinterface.h
qgsprojectbadlayerguihandler.h
qgslonglongvalidator.h
qgssearchquerybuilder.h
qgsscalecombobox.h
qgsexpressionbuilderwidget.h
qgsexpressionhighlighter.h
qgsexpressionselectiondialog.h
qgsprojectionselector.h
qgsquerybuilder.h
qgscollapsiblegroupbox.h
qgsfilterlineedit.h
qgsrasterformatsaveoptionswidget.h
qgsrasterlayersaveasdialog.h
qgsrasterpyramidsoptionswidget.h
qgsrelationadddlg.h
qgsrelationeditor.h
qgsrelationmanagerdialog.h
qgsscalecombobox.h
qgssearchquerybuilder.h
qgssublayersdialog.h
)
@ -251,14 +267,25 @@ QT4_WRAP_CPP(QGIS_GUI_MOC_SRCS ${QGIS_GUI_MOC_HDRS})
SET(QGIS_GUI_HDRS
qgisgui.h
qgisinterface.h
qgsattributeeditor.h
qgsattributedialog.h
qgsattributeeditorcontext.h
qgsbusyindicatordialog.h
qgscharacterselectdialog.h
qgscollapsiblegroupbox.h
qgscolordialog.h
qgscredentialdialog.h
qgscursors.h
qgsdatadefinedbutton.h
qgsencodingfiledialog.h
qgsexpressionbuilderdialog.h
qgsexpressionbuilderwidget.h
qgsexpressionhighlighter.h
qgsexpressionselectiondialog.h
qgsfeatureselectiondlg.h
qgsfieldvalidator.h
qgsfiledropedit.h
qgsfilterlineedit.h
qgsgenericprojectionselector.h
qgshighlight.h
qgsmapcanvas.h
@ -266,6 +293,7 @@ qgsmapcanvasitem.h
qgsmapcanvasmap.h
qgsmapcanvassnapper.h
qgsmapoverviewcanvas.h
qgsmaptip.h
qgsmaptool.h
qgsmaptoolemitpoint.h
qgsmaptoolidentify.h
@ -275,25 +303,15 @@ qgsmessagebaritem.h
qgsmessagebar.h
qgsmessageviewer.h
qgsoptionsdialogbase.h
qgscredentialdialog.h
qgsowssourceselect.h
qgsprojectionselector.h
qgsrelationeditor.h
qgsrubberband.h
qgsvertexmarker.h
qgsmaptip.h
qgsscalecombobox.h
qgsblendmodecombobox.h
qgssearchquerybuilder.h
qgsattributeeditor.h
qgsattributedialog.h
qgsfieldvalidator.h
qgsexpressionbuilderwidget.h
qgsexpressionbuilderdialog.h
qgsexpressionselectiondialog.h
qgsexpressionhighlighter.h
qgscollapsiblegroupbox.h
qgsfilterlineedit.h
qgssublayersdialog.h
qgsvectorlayertools.h
qgsvertexmarker.h
qgsnumericsortlistviewitem.h
qgsannotationitem.h
qgstextannotationitem.h
@ -319,6 +337,9 @@ editorwidgets/core/qgseditorconfigwidget.h
editorwidgets/core/qgseditorwidgetfactory.h
editorwidgets/core/qgseditorwidgetregistry.h
editorwidgets/core/qgseditorwidgetwrapper.h
editorwidgets/qgsrelationreferencefactory.h
editorwidgets/qgsrelationreferencewidget.h
editorwidgets/qgsrelreferenceconfigdlg.h
raster/qgsrasterrendererwidget.h
)

View File

@ -21,13 +21,11 @@
#include "qgsmessagelog.h"
QgsEditorWidgetRegistry *QgsEditorWidgetRegistry::sInstance = 0;
QgsEditorWidgetRegistry QgsEditorWidgetRegistry::sInstance;
QgsEditorWidgetRegistry* QgsEditorWidgetRegistry::instance()
{
if( !sInstance )
sInstance = new QgsEditorWidgetRegistry();
return sInstance;
return &sInstance;
}
QgsEditorWidgetRegistry::QgsEditorWidgetRegistry()

View File

@ -112,7 +112,7 @@ class GUI_EXPORT QgsEditorWidgetRegistry : public QObject
private:
QMap<QString, QgsEditorWidgetFactory*> mWidgetFactories;
static QgsEditorWidgetRegistry *sInstance;
static QgsEditorWidgetRegistry sInstance;
};

View File

@ -0,0 +1,59 @@
/***************************************************************************
qgsrelationreferencefactory.cpp
--------------------------------------
Date : 29.5.2013
Copyright : (C) 2013 Matthias Kuhn
Email : matthias dot kuhn at gmx dot ch
***************************************************************************
* *
* 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 "qgsrelationreferencefactory.h"
#include "qgsrelationreferencewidget.h"
#include "qgsrelreferenceconfigdlg.h"
QgsRelationReferenceFactory::QgsRelationReferenceFactory( QgsAttributeEditorContext context, QString name )
: QgsEditorWidgetFactory( name )
, mEditorContext( context )
{
}
QgsEditorWidgetWrapper* QgsRelationReferenceFactory::create( QgsVectorLayer* vl, int fieldIdx, QWidget* editor, QWidget* parent ) const
{
return new QgsRelationReferenceWidget( vl, fieldIdx, editor, mEditorContext, parent );
}
QgsEditorConfigWidget* QgsRelationReferenceFactory::configWidget( QgsVectorLayer* vl, int fieldIdx, QWidget* parent ) const
{
return new QgsRelReferenceConfigDlg( vl, fieldIdx, parent );
}
QgsEditorWidgetConfig QgsRelationReferenceFactory::readConfig( const QDomElement& configElement, QgsVectorLayer* layer, int fieldIdx )
{
Q_UNUSED( layer );
Q_UNUSED( fieldIdx );
QMap<QString, QVariant> cfg;
cfg.insert( "AllowNULL", configElement.attribute( "AllowNULL" ) == "1" );
cfg.insert( "ShowForm", configElement.attribute( "ShowForm" ) == "1" );
cfg.insert( "Relation", configElement.attribute( "Relation" ) );
return cfg;
}
void QgsRelationReferenceFactory::writeConfig( const QgsEditorWidgetConfig& config, QDomElement& configElement, const QDomDocument& doc, const QgsVectorLayer* layer, int fieldIdx )
{
Q_UNUSED( doc );
Q_UNUSED( layer );
Q_UNUSED( fieldIdx );
configElement.setAttribute( "AllowNULL", config["AllowNULL"].toBool() );
configElement.setAttribute( "ShowForm", config["ShowForm"].toBool() );
configElement.setAttribute( "Relation", config["Relation"].toString() );
}

View File

@ -0,0 +1,79 @@
/***************************************************************************
qgsrelationreferencefactory.h
--------------------------------------
Date : 29.5.2013
Copyright : (C) 2013 Matthias Kuhn
Email : matthias dot kuhn at gmx dot ch
***************************************************************************
* *
* 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 QGSRELATIONREFERENCEFACTORY_H
#define QGSRELATIONREFERENCEFACTORY_H
#include "qgsattributeeditorcontext.h"
#include "qgseditorwidgetfactory.h"
class GUI_EXPORT QgsRelationReferenceFactory : public QgsEditorWidgetFactory
{
public:
QgsRelationReferenceFactory( QgsAttributeEditorContext context, QString name );
/**
* Override this in your implementation.
* Create a new editor widget wrapper. Call {@link QgsEditorWidgetRegistry::create()}
* instead of calling this method directly.
*
* @param vl The vector layer on which this widget will act
* @param fieldIdx The field index on which this widget will act
* @param editor An editor widget if already existent. If NULL is provided, a new widget will be created.
* @param parent The parent for the wrapper class and any created widget.
*
* @return A new widget wrapper
*/
virtual QgsEditorWidgetWrapper* create( QgsVectorLayer* vl, int fieldIdx, QWidget* editor, QWidget* parent ) const;
/**
* Override this in your implementation.
* Create a new configuration widget for this widget type.
*
* @param vl The layer for which the widget will be created
* @param fieldIdx The field index for which the widget will be created
* @param parent The parent widget of the created config widget
*
* @return A configuration widget
*/
virtual QgsEditorConfigWidget* configWidget( QgsVectorLayer* vl, int fieldIdx, QWidget* parent ) const;
/**
* Read the config from an XML file and map it to a proper {@link QgsEditorWidgetConfig}.
*
* @param configElement The configuration element from the project file
* @param layer The layer for which this configuration applies
* @param fieldIdx The field on the layer for which this configuration applies
*
* @return A configuration object. This will be passed to your widget wrapper later on
*/
virtual QgsEditorWidgetConfig readConfig( const QDomElement& configElement, QgsVectorLayer* layer, int fieldIdx );
/**
* Serialize your configuration and save it in a xml doc.
*
* @param config The configuration to serialize
* @param configElement The element, where you can write your configuration into
* @param doc The document. You can use this to create new nodes
* @param layer The layer for which this configuration applies
* @param fieldIdx The field on the layer for which this configuration applies
*/
virtual void writeConfig( const QgsEditorWidgetConfig& config, QDomElement& configElement, const QDomDocument& doc, const QgsVectorLayer* layer, int fieldIdx );
private:
QgsAttributeEditorContext mEditorContext;
};
#endif // QGSRELATIONREFERENCEFACTORY_H

View File

@ -0,0 +1,202 @@
/***************************************************************************
qgsrelationreferencewidget.cpp
--------------------------------------
Date : 20.4.2013
Copyright : (C) 2013 Matthias Kuhn
Email : matthias dot kuhn at gmx dot ch
***************************************************************************
* *
* 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 "qgsrelationreferencewidget.h"
#include <QPushButton>
#include <QDialog>
#include "qgsattributedialog.h"
#include "qgscollapsiblegroupbox.h"
#include "qgseditorwidgetfactory.h"
#include "qgsexpression.h"
#include "qgsfield.h"
#include "qgsproject.h"
#include "qgsrelreferenceconfigdlg.h"
#include "qgsrelationmanager.h"
#include "qgsvectorlayer.h"
QgsRelationReferenceWidget::QgsRelationReferenceWidget( QgsVectorLayer* vl, int fieldIdx, QWidget* editor, QgsAttributeEditorContext context, QWidget* parent )
: QgsEditorWidgetWrapper( vl, fieldIdx, editor, parent )
, mInitialValueAssigned( false )
, mComboBox( NULL )
, mAttributeEditorFrame( NULL )
, mAttributeEditorLayout( NULL )
, mAttributeEditorButton( NULL )
, mReferencedLayer( NULL )
, mAttributeDialog( NULL )
, mEditorContext( context )
{
}
QWidget* QgsRelationReferenceWidget::createWidget( QWidget* parent )
{
return new QWidget( parent );
}
void QgsRelationReferenceWidget::initWidget( QWidget* editor )
{
QGridLayout* layout = new QGridLayout( editor );
editor->setLayout( layout );
mComboBox = new QComboBox( editor );
layout->addWidget( mComboBox, 0, 0, 1, 1 );
if ( config( "ShowForm", true ).toBool() )
{
mAttributeEditorFrame = new QgsCollapsibleGroupBox( editor );
mAttributeEditorLayout = new QVBoxLayout( mAttributeEditorFrame );
mAttributeEditorFrame->setLayout( mAttributeEditorLayout );
layout->addWidget( mAttributeEditorFrame, 1, 0, 1, 3 );
}
else
{
mAttributeEditorButton = new QPushButton( tr( "Open Form" ) );
layout->addWidget( mAttributeEditorButton, 0, 1, 1, 1 );
connect( mAttributeEditorButton, SIGNAL( clicked() ), this, SLOT( openForm() ) );
}
layout->addItem( new QSpacerItem( 0, 0, QSizePolicy::Expanding ), 0, 2, 1, 1 );
QgsRelation relation = QgsProject::instance()->relationManager()->relation( config( "Relation" ).toString() );
if ( relation.isValid() )
{
mReferencedLayer = relation.referencedLayer();
int refFieldIdx = mReferencedLayer->fieldNameIndex( relation.fieldPairs().first().second );
QgsFeatureIterator fit = mReferencedLayer->getFeatures( QgsFeatureRequest() );
QgsExpression exp( mReferencedLayer->displayExpression() );
exp.prepare( mReferencedLayer->pendingFields() );
QgsFeature f;
while ( fit.nextFeature( f ) )
{
QString txt = exp.evaluate( &f ).toString();
mComboBox->addItem( txt, f.id() );
mFidFkMap.insert( f.id(), f.attribute( refFieldIdx ) );
}
if ( config( "AllowNULL" ).toBool() )
{
mComboBox->addItem( "[NULL]" );
}
// Only connect after iterating, to have only one iterator on the referenced table at once
connect( mComboBox, SIGNAL( currentIndexChanged( int ) ), this, SLOT( referenceChanged( int ) ) );
}
else
{
QLabel* lbl = new QLabel( tr( "The relation is not valid. Please make sure your relation definitions are ok." ) );
QFont font = lbl->font();
font.setItalic( true );
lbl->setStyleSheet( "QLabel { color: red; } " );
lbl->setFont( font );
layout->addWidget( lbl, 1, 0, 1, 3 );
}
}
QVariant QgsRelationReferenceWidget::value()
{
QVariant varFid = mComboBox->itemData( mComboBox->currentIndex() );
if ( varFid.isNull() )
{
return QVariant();
}
else
{
return mFidFkMap.value( varFid.value<QgsFeatureId>() );
}
}
void QgsRelationReferenceWidget::setValue( const QVariant& value )
{
QgsFeatureId fid = mFidFkMap.key( value );
int oldIdx = mComboBox->currentIndex();
mComboBox->setCurrentIndex( mComboBox->findData( fid ) );
if ( !mInitialValueAssigned )
{
// In case the default-selected item (first) is the actual item
// then no referenceChanged event was triggered automatically:
// Do it!
if ( oldIdx == mComboBox->currentIndex() )
referenceChanged( mComboBox->currentIndex() );
mInitialValueAssigned = true;
}
}
void QgsRelationReferenceWidget::setEnabled( bool enabled )
{
mComboBox->setEnabled( enabled );
}
void QgsRelationReferenceWidget::referenceChanged( int index )
{
QgsFeatureId fid = mComboBox->itemData( index ).value<QgsFeatureId>();
emit valueChanged( mFidFkMap.value( fid ) );
// Check if we're running with an embedded frame we need to update
if ( mAttributeEditorFrame )
{
QgsFeature feat;
mReferencedLayer->getFeatures( QgsFeatureRequest().setFilterFid( fid ) ).nextFeature( feat );
if ( feat.isValid() )
{
// Backup old dialog and delete only after creating the new dialog, so we can "hot-swap" the contained QgsFeature
QgsAttributeDialog* oldDialog = mAttributeDialog;
if ( mAttributeDialog && mAttributeDialog->dialog() )
{
mAttributeEditorLayout->removeWidget( mAttributeDialog->dialog() );
}
// TODO: Get a proper QgsDistanceArea thingie
mAttributeDialog = new QgsAttributeDialog( mReferencedLayer, new QgsFeature( feat ), true, mAttributeEditorFrame, false, mEditorContext );
QWidget* attrDialog = mAttributeDialog->dialog();
attrDialog->setWindowFlags( Qt::Widget ); // Embed instead of opening as window
mAttributeEditorLayout->addWidget( attrDialog );
attrDialog->show();
delete oldDialog;
}
}
}
void QgsRelationReferenceWidget::openForm()
{
QgsFeatureId fid = mComboBox->itemData( mComboBox->currentIndex() ).value<QgsFeatureId>();
QgsFeature feat;
mReferencedLayer->getFeatures( QgsFeatureRequest().setFilterFid( fid ) ).nextFeature( feat );
if ( !feat.isValid() )
return;
// TODO: Get a proper QgsDistanceArea thingie
mAttributeDialog = new QgsAttributeDialog( mReferencedLayer, new QgsFeature( feat ), true, widget(), true, mEditorContext );
mAttributeDialog->exec();
delete mAttributeDialog;
}

View File

@ -0,0 +1,63 @@
/***************************************************************************
qgsrelationreferencewidget.h
--------------------------------------
Date : 20.4.2013
Copyright : (C) 2013 Matthias Kuhn
Email : matthias dot kuhn at gmx dot ch
***************************************************************************
* *
* 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 QGSRELATIONREFERENCEWIDGET_H
#define QGSRELATIONREFERENCEWIDGET_H
#include "qgsattributeeditorcontext.h"
#include "qgseditorwidgetwrapper.h"
#include "qgsfeature.h"
#include <QComboBox>
#include <QPushButton>
#include <QVBoxLayout>
class QgsAttributeDialog;
class QgsVectorLayerTools;
class GUI_EXPORT QgsRelationReferenceWidget : public QgsEditorWidgetWrapper
{
Q_OBJECT
public:
explicit QgsRelationReferenceWidget( QgsVectorLayer* vl, int fieldIdx, QWidget* editor, QgsAttributeEditorContext context, QWidget* parent = 0 );
virtual QWidget* createWidget( QWidget* parent );
virtual void initWidget( QWidget* editor );
virtual QVariant value();
signals:
void valueChanged( const QVariant& value );
public slots:
virtual void setValue( const QVariant& value );
virtual void setEnabled( bool enabled );
private slots:
void referenceChanged( int index );
void openForm();
private:
bool mInitialValueAssigned;
QComboBox* mComboBox;
QWidget* mAttributeEditorFrame;
QVBoxLayout* mAttributeEditorLayout;
QPushButton* mAttributeEditorButton;
QgsVectorLayer* mReferencedLayer;
QVariant mCurrentValue;
QgsAttributeDialog* mAttributeDialog;
QHash<QgsFeatureId, QVariant> mFidFkMap; // Mapping from feature id => foreign key
QgsAttributeEditorContext mEditorContext;
};
#endif // QGSRELATIONREFERENCEWIDGET_H

View File

@ -0,0 +1,78 @@
/***************************************************************************
qgsrelreferenceconfigdlg.cpp
--------------------------------------
Date : 21.4.2013
Copyright : (C) 2013 Matthias Kuhn
Email : matthias dot kuhn at gmx dot ch
***************************************************************************
* *
* 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 "qgsrelreferenceconfigdlg.h"
#include "qgseditorwidgetfactory.h"
#include "qgsfield.h"
#include "qgsproject.h"
#include "qgsrelationmanager.h"
#include "qgsvectorlayer.h"
QgsRelReferenceConfigDlg::QgsRelReferenceConfigDlg( QgsVectorLayer* vl, int fieldIdx, QWidget* parent )
: QgsEditorConfigWidget( vl, fieldIdx, parent )
{
setupUi( this );
foreach ( const QgsRelation& relation, vl->referencingRelations( fieldIdx ) )
{
QgsField fld = relation.fieldPairs().first().second;
mComboRelation->addItem( QString( "%1 (%2)" ).arg( relation.id(), relation.referencedLayerId() ), relation.id() );
if ( relation.referencedLayer() )
{
mTxtDisplayExpression->setText( relation.referencedLayer()->displayExpression() );
}
}
}
void QgsRelReferenceConfigDlg::setConfig( const QMap<QString, QVariant>& config )
{
if ( config.contains( "AllowNULL" ) )
{
mCbxAllowNull->setChecked( config[ "AllowNULL" ].toBool() );
}
if ( config.contains( "ShowForm" ) )
{
mCbxShowForm->setChecked( config[ "ShowForm" ].toBool() );
}
if ( config.contains( "Relation" ) )
{
mComboRelation->setCurrentIndex( mComboRelation->findData( config[ "Relation" ].toString() ) );
}
}
void QgsRelReferenceConfigDlg::on_mComboRelation_indexChanged( int idx )
{
QString relName = mComboRelation->itemData( idx ).toString();
QgsRelation rel = QgsProject::instance()->relationManager()->relation( relName );
QgsVectorLayer* referencedLayer = rel.referencedLayer();
if ( referencedLayer )
{
mTxtDisplayExpression->setText( referencedLayer->displayExpression() );
}
}
QgsEditorWidgetConfig QgsRelReferenceConfigDlg::config()
{
QgsEditorWidgetConfig myConfig;
myConfig.insert( "AllowNULL", mCbxAllowNull->isChecked() );
myConfig.insert( "ShowForm", mCbxShowForm->isChecked() );
myConfig.insert( "Relation", mComboRelation->itemData( mComboRelation->currentIndex() ) );
return myConfig;
}

View File

@ -0,0 +1,35 @@
/***************************************************************************
qgsrelreferenceconfigdlgbase.h
--------------------------------------
Date : 21.4.2013
Copyright : (C) 2013 Matthias Kuhn
Email : matthias dot kuhn at gmx dot ch
***************************************************************************
* *
* 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 QGSRELREFERENCECONFIGDLGBASE_H
#define QGSRELREFERENCECONFIGDLGBASE_H
#include "ui_qgsrelreferenceconfigdlgbase.h"
#include "qgseditorconfigwidget.h"
class GUI_EXPORT QgsRelReferenceConfigDlg : public QgsEditorConfigWidget, private Ui::QgsRelReferenceConfigDlgBase
{
Q_OBJECT
public:
explicit QgsRelReferenceConfigDlg( QgsVectorLayer* vl, int fieldIdx, QWidget* parent );
virtual QgsEditorWidgetConfig config();
virtual void setConfig( const QgsEditorWidgetConfig& config );
private slots:
void on_mComboRelation_indexChanged( int idx );
};
#endif // QGSRELREFERENCECONFIGDLGBASE_H

View File

@ -34,6 +34,7 @@ class QgsLegendInterface;
class QgsPluginManagerInterface;
class QgsFeature;
class QgsMessageBar;
class QgsVectorLayerTools;
#include <QObject>
#include <QFont>
@ -217,7 +218,7 @@ class GUI_EXPORT QgisInterface : public QObject
/** Return the message bar of the main app */
virtual QgsMessageBar * messageBar() = 0;
/**Return mainwindows / composer views of running composer instances (currently only one)*/
/** Return mainwindows / composer views of running composer instances (currently only one) */
virtual QList<QgsComposerView*> activeComposers() = 0;
/** Create a new composer
@ -530,13 +531,17 @@ class GUI_EXPORT QgisInterface : public QObject
virtual QAction *actionCheckQgisVersion() = 0;
virtual QAction *actionAbout() = 0;
//! Open feature form
// returns true when dialog was accepted
// @added in 1.6
/**
* Open feature form
* @return true when dialog was accepted
* @note added in 1.6
*/
virtual bool openFeatureForm( QgsVectorLayer *l, QgsFeature &f, bool updateFeatureOnly = false ) = 0;
virtual QDialog* getFeatureForm( QgsVectorLayer *l, QgsFeature &f ) = 0;
virtual QgsVectorLayerTools* vectorLayerTools() = 0;
virtual void preloadForm( QString uifile ) = 0;
/** Return vector layers in edit mode
@ -555,18 +560,21 @@ class GUI_EXPORT QgisInterface : public QObject
*/
void currentLayerChanged( QgsMapLayer * layer );
/**This signal is emitted when a new composer instance has been created
/**
* This signal is emitted when a new composer instance has been created
* @note added in 1.4
*/
void composerAdded( QgsComposerView* v );
/**This signal is emitted before a new composer instance is going to be removed
/**
* This signal is emitted before a new composer instance is going to be removed
* @note added in 1.4
*/
void composerWillBeRemoved( QgsComposerView* v );
/**This signal is emitted when the initialization is complete
* @note added in version 1.6
*/
/**
* This signal is emitted when the initialization is complete
* @note added in 1.6
*/
void initializationCompleted();
/** emitted when a project file is successfully read
@note
@ -574,7 +582,7 @@ class GUI_EXPORT QgisInterface : public QObject
plug-in can connect to this signal. When it is emitted, the plug-in
knows to then check the project properties for any relevant state.
Added in v1.6
Added in 1.6
*/
void projectRead();
/** emitted when starting an entirely new project
@ -585,7 +593,7 @@ class GUI_EXPORT QgisInterface : public QObject
it's probably more semantically correct to have an entirely separate
signal for when this happens.
Added in v1.6
Added in 1.6
*/
void newProjectCreated();
};

View File

@ -20,8 +20,9 @@
#include "qgslogger.h"
#include "qgsmapcanvas.h"
#include "qgsproject.h"
#include "qgsvectorlayer.h"
#include "qgsrelationeditor.h"
#include "qgsvectordataprovider.h"
#include "qgsvectorlayer.h"
#include "qgsattributeeditor.h"
#include "qgshighlight.h"
#include "qgsexpression.h"
@ -266,6 +267,22 @@ void QgsAttributeDialog::init()
}
}
QList<QgsRelation> relations = QgsProject::instance()->relationManager()->referencedRelations( mLayer );
foreach ( const QgsRelation& relation, relations )
{
relation.id();
QWidget *myWidget = QgsRelationEditorWidget::createRelationEditor( relation, *mFeature, mContext );
myWidget->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding );
if ( !myWidget )
continue;
mypInnerLayout->addWidget( myWidget, index, 0, 1, 2 );
mypInnerLayout->setRowStretch( index, 1 );
++index;
}
// Set focus to first widget in list, to help entering data without moving the mouse.
if ( mypInnerLayout->rowCount() > 0 )
{
@ -274,7 +291,7 @@ void QgsAttributeDialog::init()
widget->setFocus( Qt::OtherFocusReason );
}
QSpacerItem *mypSpacer = new QSpacerItem( 10, 10, QSizePolicy::Fixed, QSizePolicy::Expanding );
QSpacerItem *mypSpacer = new QSpacerItem( 0, 0, QSizePolicy::Fixed, QSizePolicy::MinimumExpanding );
mypInnerLayout->addItem( mypSpacer, mypInnerLayout->rowCount() + 1, 0 );
}
else

View File

@ -28,6 +28,7 @@ class QgsFeature;
class QgsField;
class QgsHighlight;
class QgsVectorLayer;
class QgsVectorLayerTools;
class GUI_EXPORT QgsAttributeDialog : public QObject
{
@ -35,24 +36,36 @@ class GUI_EXPORT QgsAttributeDialog : public QObject
public:
/**
* @brief QgsAttributeDialog
* @param vl
* @param thepFeature
* @param featureOwner
* @param myDa
* @param parent
* @param showDialogButtons
* Create an attribute dialog for a given layer and feature
*
* @param vl The layer for which the dialog will be generated
* @param thepFeature A feature for which the dialog will be generated
* @param featureOwner Set to true, if the dialog should take ownership of the feature
* @param myDa A QgsDistanceArea which will be used for expressions
* @param parent A parent widget for the dialog
* @param showDialogButtons True: Show the dialog buttons accept/cancel
*
* @deprecated
*/
QgsAttributeDialog( QgsVectorLayer *vl, QgsFeature *thepFeature, bool featureOwner, QgsDistanceArea myDa, QWidget* parent = 0, bool showDialogButtons = true );
/**
* Create an attribute dialog for a given layer and feature
*
* @param vl The layer for which the dialog will be generated
* @param thepFeature A feature for which the dialog will be generated
* @param featureOwner Set to true, if the dialog should take ownership of the feature
* @param parent A parent widget for the dialog
* @param showDialogButtons True: Show the dialog buttons accept/cancel
* @param context The context in which this dialog is created
*
*/
QgsAttributeDialog( QgsVectorLayer *vl, QgsFeature *thepFeature, bool featureOwner, QWidget* parent = 0, bool showDialogButtons = true, QgsAttributeEditorContext context = QgsAttributeEditorContext() );
~QgsAttributeDialog();
/** Saves the size and position for the next time
* this dialog box was used.
* this dialog box will be used.
*/
void saveGeometry();

View File

@ -21,8 +21,8 @@
#include "qgseditorwidgetwrapper.h"
#include "qgsattributedialog.h"
#include "qgsattributeeditorcontext.h"
#include "qgsattributeeditor.h"
#include "qgsattributeeditorcontext.h"
#include "qgscategorizedsymbolrendererv2.h"
#include "qgscolorbutton.h"
#include "qgsexpression.h"
@ -32,6 +32,8 @@
#include "qgslonglongvalidator.h"
#include "qgsmaplayerregistry.h"
#include "qgsnetworkaccessmanager.h"
#include "qgsrelationeditor.h"
#include "qgsrelationmanager.h"
#include "qgsvectordataprovider.h"
#include "qgsvectorlayer.h"
@ -1430,6 +1432,16 @@ QWidget* QgsAttributeEditor::createWidgetFromDef( const QgsAttributeEditorElemen
break;
}
case QgsAttributeEditorElement::AeTypeRelation:
{
const QgsAttributeEditorRelation* relDef = dynamic_cast<const QgsAttributeEditorRelation*>( widgetDef );
newWidget = QgsRelationEditorWidget::createRelationEditor( relDef->relation(), feat, context );
labelText = QString::null;
labelOnTop = true;
break;
}
case QgsAttributeEditorElement::AeTypeContainer:
{
const QgsAttributeEditorContainer* container = dynamic_cast<const QgsAttributeEditorContainer*>( widgetDef );

View File

@ -22,6 +22,7 @@
#include <QGridLayout>
#include "qgsfeature.h"
#include "qgsrelationmanager.h"
class QObject;
class QWidget;
@ -31,6 +32,7 @@ class QListWidget;
class QgsAttributeEditorContext;
class QgsAttributeEditorElement;
class QgsDualView;
class QgsRelationManager;
class QgsVectorLayer;
/* \brief create attribute widget for editing */
@ -67,7 +69,6 @@ class GUI_EXPORT QgsAttributeEditor : public QObject
*
*/
static QWidget* createAttributeEditor( QWidget* parent, QWidget* editor, QgsVectorLayer* vl, int idx, const QVariant& value );
/**
* Creates or prepares a attributre editor widget
* @param parent The parent object

View File

@ -0,0 +1,40 @@
/***************************************************************************
qgsfeatureselectiondlg.cpp
--------------------------------------
Date : 11.6.2013
Copyright : (C) 2013 Matthias Kuhn
Email : matthias dot kuhn at gmx dot ch
***************************************************************************
* *
* 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 "qgsfeatureselectiondlg.h"
#include "qgsgenericfeatureselectionmanager.h"
#include "qgsdistancearea.h"
QgsFeatureSelectionDlg::QgsFeatureSelectionDlg( QgsVectorLayer* vl, QWidget *parent )
: QDialog( parent )
, mVectorLayer( vl )
{
setupUi( this );
mFeatureSelection = new QgsGenericFeatureSelectionManager( mDualView );
mDualView->setFeatureSelectionManager( mFeatureSelection );
// TODO: Proper QgsDistanceArea, proper mapcanvas
mDualView->init( mVectorLayer, NULL );
}
const QgsFeatureIds& QgsFeatureSelectionDlg::selectedFeatures()
{
return mFeatureSelection->selectedFeaturesIds();
}

View File

@ -0,0 +1,37 @@
/***************************************************************************
qgsfeatureselectiondlg.h
--------------------------------------
Date : 11.6.2013
Copyright : (C) 2013 Matthias Kuhn
Email : matthias dot kuhn at gmx dot ch
***************************************************************************
* *
* 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 QGSFEATURESELECTIONDLG_H
#define QGSFEATURESELECTIONDLG_H
class QgsGenericFeatureSelectionManager;
#include "ui_qgsfeatureselectiondlg.h"
class QgsFeatureSelectionDlg : public QDialog, private Ui::QgsFeatureSelectionDlg
{
Q_OBJECT
public:
explicit QgsFeatureSelectionDlg( QgsVectorLayer* vl, QWidget *parent = 0 );
const QgsFeatureIds& selectedFeatures();
private:
QgsGenericFeatureSelectionManager* mFeatureSelection;
QgsVectorLayer* mVectorLayer;
};
#endif // QGSFEATURESELECTIONDLG_H

View File

@ -0,0 +1,79 @@
#include "qgsrelationadddlg.h"
#include "qgsvectorlayer.h"
QgsRelationAddDlg::QgsRelationAddDlg( QWidget *parent ) :
QDialog( parent )
{
setupUi( this );
}
void QgsRelationAddDlg::addLayers( QList< QgsVectorLayer* > layers )
{
mCbxReferencingLayer->addItem( "", "" );
mCbxReferencedLayer->addItem( "", "" );
foreach ( QgsVectorLayer* layer, layers )
{
mCbxReferencingLayer->addItem( layer->name(), layer->id() );
mCbxReferencedLayer->addItem( layer->name(), layer->id() );
mLayers.insert( layer->id(), layer );
}
}
QString QgsRelationAddDlg::referencingLayerId()
{
return mCbxReferencingLayer->itemData( mCbxReferencingLayer->currentIndex() ).toString();
}
QString QgsRelationAddDlg::referencedLayerId()
{
return mCbxReferencedLayer->itemData( mCbxReferencedLayer->currentIndex() ).toString();
}
QList< QPair< QString, QString > > QgsRelationAddDlg::references()
{
QList< QPair< QString, QString > > references;
QString referencingField = mCbxReferencingField->itemData( mCbxReferencingField->currentIndex() ).toString();
QString referencedField = mCbxReferencedField->itemData( mCbxReferencedField->currentIndex() ).toString();
references.append( QPair<QString, QString> ( referencingField, referencedField ) );
return references;
}
QString QgsRelationAddDlg::relationId()
{
return mTxtRelationId->text();
}
QString QgsRelationAddDlg::relationName()
{
return mTxtRelationName->text();
}
void QgsRelationAddDlg::on_mCbxReferencingLayer_currentIndexChanged( int index )
{
loadLayerAttributes( mCbxReferencingField, mLayers[mCbxReferencingLayer->itemData( index ).toString()] );
}
void QgsRelationAddDlg::on_mCbxReferencedLayer_currentIndexChanged( int index )
{
loadLayerAttributes( mCbxReferencedField, mLayers[mCbxReferencedLayer->itemData( index ).toString()] );
}
void QgsRelationAddDlg::loadLayerAttributes( QComboBox* cbx, QgsVectorLayer* layer )
{
cbx->clear();
if ( !layer )
{
return;
}
foreach ( QgsField fld, layer->pendingFields().toList() )
{
cbx->addItem( fld.name(), fld.name() );
}
}

View File

@ -0,0 +1,36 @@
#ifndef QGSRELATIONADDDLG_H
#define QGSRELATIONADDDLG_H
#include <QDialog>
#include "ui_qgsrelationadddlgbase.h"
class QgsVectorLayer;
class QgsRelationAddDlg : public QDialog, private Ui::QgsRelationAddDlgBase
{
Q_OBJECT
public:
explicit QgsRelationAddDlg( QWidget *parent = 0 );
void addLayers( QList<QgsVectorLayer* > layers );
QString referencingLayerId();
QString referencedLayerId();
QList< QPair< QString, QString > > references();
QString relationId();
QString relationName();
private slots:
void on_mCbxReferencingLayer_currentIndexChanged( int index );
void on_mCbxReferencedLayer_currentIndexChanged( int index );
private:
void loadLayerAttributes( QComboBox* cbx, QgsVectorLayer* layer );
QMap< QString, QgsVectorLayer* > mLayers;
};
#endif // QGSRELATIONADDDLG_H

View File

@ -0,0 +1,183 @@
/***************************************************************************
qgsrelationeditor.cpp
--------------------------------------
Date : 17.5.2013
Copyright : (C) 2013 Matthias Kuhn
Email : matthias dot kuhn at gmx dot ch
***************************************************************************
* *
* 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 "qgsrelationeditor.h"
#include "attributetable/qgsdualview.h"
#include "qgsdistancearea.h"
#include "qgsvectordataprovider.h"
#include "qgsexpression.h"
#include "qgsfeature.h"
#include "qgsfeatureselectiondlg.h"
#include "qgsgenericfeatureselectionmanager.h"
#include "qgsrelation.h"
#include "qgsvectorlayertools.h"
#include <QHBoxLayout>
#include <QLabel>
QgsRelationEditorWidget::QgsRelationEditorWidget( const QgsRelation& relation, const QgsFeature& feature, QgsAttributeEditorContext context, QWidget* parent )
: QgsCollapsibleGroupBox( relation.name(), parent )
, mDualView( NULL )
, mEditorContext( context )
, mRelation( relation )
, mFeature( feature )
{
setupUi( this );
connect( relation.referencingLayer(), SIGNAL( editingStarted() ), this, SLOT( referencingLayerEditingToggled() ) );
connect( relation.referencingLayer(), SIGNAL( editingStopped() ), this, SLOT( referencingLayerEditingToggled() ) );
connect( this, SIGNAL( collapsedStateChanged( bool ) ), this, SIGNAL( onCollapsedStateChanged( bool ) ) );
// Set initial state for add/remove etc. buttons
referencingLayerEditingToggled();
}
QgsRelationEditorWidget* QgsRelationEditorWidget::createRelationEditor( const QgsRelation& relation, const QgsFeature& feature, QgsAttributeEditorContext context, QWidget* parent )
{
QgsRelationEditorWidget* editor = new QgsRelationEditorWidget( relation, feature, context, parent );
QgsDualView* dualView = new QgsDualView( editor );
QgsVectorLayer* lyr = relation.referencingLayer();
bool canChangeAttributes = lyr->dataProvider()->capabilities() & QgsVectorDataProvider::ChangeAttributeValues;
editor->mToggleEditingButton->setEnabled( canChangeAttributes && !lyr->isReadOnly() );
editor->mFeatureSelectionMgr = new QgsGenericFeatureSelectionManager( dualView );
dualView->setFeatureSelectionManager( editor->mFeatureSelectionMgr );
editor->mBrowserWidget->layout()->addWidget( dualView );
QgsFeatureRequest myRequest = relation.getRelatedFeaturesRequest( feature );
dualView->init( relation.referencingLayer(), NULL, myRequest, context );
editor->mDualView = dualView;
editor->mViewModeButtonGroup->setId( editor->mTableViewButton, QgsDualView::AttributeTable );
editor->mViewModeButtonGroup->setId( editor->mFormViewButton, QgsDualView::AttributeEditor );
connect( editor->mViewModeButtonGroup, SIGNAL( buttonClicked( int ) ), dualView, SLOT( setCurrentIndex( int ) ) );
connect( dualView, SIGNAL( currentChanged( int ) ), editor, SLOT( viewModeChanged( int ) ) );
return editor;
}
void QgsRelationEditorWidget::onCollapsedStateChanged( bool state )
{
if ( state && !mDualView->masterModel() )
{
// TODO: Lazy init dual view if collapsed on init
}
}
void QgsRelationEditorWidget::referencingLayerEditingToggled()
{
bool editable = mRelation.referencingLayer()->isEditable();
mAddFeatureButton->setEnabled( editable );
mLinkFeatureButton->setEnabled( editable );
mDeleteFeatureButton->setEnabled( editable );
mUnlinkFeatureButton->setEnabled( editable );
mToggleEditingButton->setChecked( editable );
}
void QgsRelationEditorWidget::viewModeChanged( int mode )
{
mViewModeButtonGroup->button( mode )->click();
}
void QgsRelationEditorWidget::on_mAddFeatureButton_clicked()
{
QgsAttributeMap keyAttrs;
QgsFields fields = mRelation.referencingLayer()->pendingFields();
foreach ( QgsRelation::FieldPair fieldPair, mRelation.fieldPairs() )
{
keyAttrs.insert( fields.indexFromName( fieldPair.referencingField() ), mFeature.attribute( fieldPair.referencedField() ) );
}
mEditorContext.vectorLayerTools()->addFeature( mDualView->masterModel()->layer(), keyAttrs );
}
void QgsRelationEditorWidget::on_mLinkFeatureButton_clicked()
{
QgsFeatureSelectionDlg selectionDlg( mRelation.referencingLayer(), this );
if ( selectionDlg.exec() )
{
QMap<int, QVariant> keys;
foreach ( const QgsRelation::FieldPair fieldPair, mRelation.fieldPairs() )
{
int idx = mRelation.referencingLayer()->fieldNameIndex( fieldPair.referencingField() );
QVariant val = mFeature.attribute( fieldPair.referencedField() );
keys.insert( idx, val );
}
foreach ( QgsFeatureId fid, selectionDlg.selectedFeatures() )
{
QMapIterator<int, QVariant> it( keys );
while ( it.hasNext() )
{
it.next();
mRelation.referencingLayer()->changeAttributeValue( fid, it.key(), it.value() );
}
}
}
}
void QgsRelationEditorWidget::on_mDeleteFeatureButton_clicked()
{
foreach ( QgsFeatureId fid, mFeatureSelectionMgr->selectedFeaturesIds() )
{
mRelation.referencingLayer()->deleteFeature( fid );
}
}
void QgsRelationEditorWidget::on_mUnlinkFeatureButton_clicked()
{
QMap<int, QgsField> keyFields;
foreach ( const QgsRelation::FieldPair fieldPair, mRelation.fieldPairs() )
{
int idx = mRelation.referencingLayer()->fieldNameIndex( fieldPair.referencingField() );
QgsField fld = mRelation.referencingLayer()->pendingFields().at( idx );
keyFields.insert( idx, fld );
}
foreach ( QgsFeatureId fid, mFeatureSelectionMgr->selectedFeaturesIds() )
{
QMapIterator<int, QgsField> it( keyFields );
while ( it.hasNext() )
{
it.next();
mRelation.referencingLayer()->changeAttributeValue( fid, it.key(), QVariant( it.value().type() ) );
}
}
}
void QgsRelationEditorWidget::on_mToggleEditingButton_toggled( bool state )
{
if ( state )
{
mEditorContext.vectorLayerTools()->startEditing( mRelation.referencingLayer() );
}
else
{
mEditorContext.vectorLayerTools()->stopEditing( mRelation.referencingLayer() );
}
}

View File

@ -0,0 +1,60 @@
/***************************************************************************
qgsrelationeditor.h
--------------------------------------
Date : 17.5.2013
Copyright : (C) 2013 Matthias Kuhn
Email : matthias dot kuhn at gmx dot ch
***************************************************************************
* *
* 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 QGSRELATIONEDITOR_H
#define QGSRELATIONEDITOR_H
#include <QWidget>
#include "ui_qgsrelationeditorwidgetbase.h"
#include "qgsattributeeditorcontext.h"
#include "qgsrelation.h"
class QgsDualView;
class QgsFeature;
class QgsGenericFeatureSelectionManager;
class QgsVectorLayer;
class QgsVectorLayerTools;
class QgsRelationEditorWidget : public QgsCollapsibleGroupBox, private Ui::QgsRelationEditorWidgetBase
{
Q_OBJECT
public:
QgsRelationEditorWidget( const QgsRelation& relation, const QgsFeature& feature, QgsAttributeEditorContext context, QWidget* parent = NULL );
static QgsRelationEditorWidget* createRelationEditor( const QgsRelation& relation, const QgsFeature& feature, QgsAttributeEditorContext context, QWidget* parent = NULL );
private slots:
void onCollapsedStateChanged( bool state );
void referencingLayerEditingToggled();
void viewModeChanged( int mode );
void on_mAddFeatureButton_clicked();
void on_mLinkFeatureButton_clicked();
void on_mDeleteFeatureButton_clicked();
void on_mUnlinkFeatureButton_clicked();
void on_mToggleEditingButton_toggled( bool state );
private:
QgsDualView* mDualView;
QgsGenericFeatureSelectionManager* mFeatureSelectionMgr;
QgsAttributeEditorContext mEditorContext;
QgsRelation mRelation;
QgsFeature mFeature;
};
#endif // QGSRELATIONEDITOR_H

View File

@ -0,0 +1,154 @@
/***************************************************************************
qgsrelationmanagerdialog.cpp
--------------------------------------
Date : 23.2.2013
Copyright : (C) 2013 Matthias Kuhn
Email : matthias dot kuhn at gmx dot ch
***************************************************************************
* *
* 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 "qgsrelationadddlg.h"
#include "qgsrelationmanagerdialog.h"
#include "qgsrelationmanager.h"
#include "qgsvectorlayer.h"
QgsRelationManagerDialog::QgsRelationManagerDialog( QgsRelationManager* relationMgr, QWidget *parent ) :
QWidget( parent ),
Ui::QgsRelationManagerDialogBase(),
mRelationManager( relationMgr )
{
setupUi( this );
}
QgsRelationManagerDialog::~QgsRelationManagerDialog()
{
}
void QgsRelationManagerDialog::setLayers( QList< QgsVectorLayer* > layers )
{
mLayers = layers;
const QList<QgsRelation>& relations = mRelationManager->relations().values();
Q_FOREACH( const QgsRelation& rel, relations )
{
addRelation( rel );
}
}
void QgsRelationManagerDialog::addRelation( const QgsRelation &rel )
{
int row = mRelationsTable->rowCount();
mRelationsTable->insertRow( row );
QTableWidgetItem* item = new QTableWidgetItem( rel.name() );
// Save relation in first column's item
item->setData( Qt::UserRole, QVariant::fromValue<QgsRelation>( rel ) );
mRelationsTable->setItem( row, 0, item );
item = new QTableWidgetItem( rel.referencingLayer()->name() );
item->setFlags( Qt::ItemIsEditable );
mRelationsTable->setItem( row, 1, item );
item = new QTableWidgetItem( rel.fieldPairs().first().referencingField() );
item->setFlags( Qt::ItemIsEditable );
mRelationsTable->setItem( row, 2, item );
item = new QTableWidgetItem( rel.referencedLayer()->name() );
item->setFlags( Qt::ItemIsEditable );
mRelationsTable->setItem( row, 3, item );
item = new QTableWidgetItem( rel.fieldPairs().first().referencedField() );
item->setFlags( Qt::ItemIsEditable );
mRelationsTable->setItem( row, 4, item );
item = new QTableWidgetItem( rel.id() );
item->setFlags( Qt::ItemIsEditable );
mRelationsTable->setItem( row, 5, item );
}
void QgsRelationManagerDialog::on_mBtnAddRelation_clicked()
{
QgsRelationAddDlg addDlg;
addDlg.addLayers( mLayers );
if ( addDlg.exec() )
{
QgsRelation relation;
relation.setReferencingLayer( addDlg.referencingLayerId() );
relation.setReferencedLayer( addDlg.referencedLayerId() );
QString relationId = addDlg.relationId();
if ( addDlg.relationId() == "" )
relationId = QString( "%1_%2_%3_%4" )
.arg( addDlg.referencingLayerId() )
.arg( addDlg.references().first().first )
.arg( addDlg.referencedLayerId() )
.arg( addDlg.references().first().second );
QStringList existingNames;
Q_FOREACH( const QgsRelation& rel, relations() )
{
existingNames << rel.id();
}
QString tempId = relationId + "_%1";
int suffix = 1;
while ( existingNames.contains( relationId ) )
{
relationId = tempId.arg( suffix );
++suffix;
}
relation.setRelationId( relationId );
relation.addFieldPair( addDlg.references().first().first, addDlg.references().first().second );
addRelation( relation );
}
}
void QgsRelationManagerDialog::on_mBtnRemoveRelation_clicked()
{
mRelationsTable->removeRow( mRelationsTable->currentItem()->row() );
}
QList< QgsRelation > QgsRelationManagerDialog::relations()
{
QList< QgsRelation > relations;
for ( int i = 0; i < mRelationsTable->rowCount(); ++i )
{
QgsRelation relation = mRelationsTable->item( i, 0 )->data( Qt::UserRole ).value<QgsRelation>();
// The name can be editted in the table, so apply this one
relation.setRelationName( mRelationsTable->item( i, 0 )->data( Qt::DisplayRole ).toString() );
relations << relation;
}
return relations;
}
#if 0
QTreeWidgetItem* QgsRelationManagerDialog::findLayerItem( QString id )
{
int count = mRelationsTreeWdg->topLevelItemCount();
for ( int i = 0; i < count; ++i )
{
QTreeWidgetItem* item = mRelationsTreeWdg->topLevelItem( i );
if ( item->data( 0, Qt::UserRole ).toString() == id )
{
return item;
}
}
return NULL;
}
#endif

View File

@ -0,0 +1,50 @@
/***************************************************************************
qgsrelationmanagerdialog.h
--------------------------------------
Date : 23.2.2013
Copyright : (C) 2013 Matthias Kuhn
Email : matthias dot kuhn at gmx dot ch
***************************************************************************
* *
* 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 QGSRELATIONMANAGERDIALOG_H
#define QGSRELATIONMANAGERDIALOG_H
#include <QWidget>
#include "ui_qgsrelationmanagerdialogbase.h"
class QgsRelation;
class QgsRelationManager;
class QgsRelationManagerTreeModel;
class QgsVectorLayer;
class GUI_EXPORT QgsRelationManagerDialog : public QWidget, private Ui::QgsRelationManagerDialogBase
{
Q_OBJECT
public:
explicit QgsRelationManagerDialog( QgsRelationManager* relationMgr, QWidget *parent = 0 );
~QgsRelationManagerDialog();
void setLayers( QList< QgsVectorLayer* > );
void addRelation( const QgsRelation& rel );
QList< QgsRelation > relations();
public slots:
void on_mBtnAddRelation_clicked();
void on_mBtnRemoveRelation_clicked();
private:
QgsRelationManager* mRelationManager;
// QgsRelationManagerTreeModel* mRelationTreeModel;
QList< QgsVectorLayer* > mLayers;
};
#endif // QGSRELATIONMANAGERDIALOG_H

View File

@ -1,8 +1,9 @@
FILE(GLOB QGIS_UIS "${CMAKE_CURRENT_SOURCE_DIR}/*.ui")
FILE(GLOB SYMBOLLAYER_UIS "${CMAKE_CURRENT_SOURCE_DIR}/symbollayer/*.ui")
FILE(GLOB EDITORWIDGET_UIS "${CMAKE_CURRENT_SOURCE_DIR}/editorwidgets/*.ui")
QT4_WRAP_UI(QGIS_UIS_H ${QGIS_UIS} ${SYMBOLLAYER_UIS})
QT4_WRAP_UI(QGIS_UIS_H ${QGIS_UIS} ${SYMBOLLAYER_UIS} ${EDITORWIDGET_UIS})
ADD_CUSTOM_TARGET(ui ALL DEPENDS ${QGIS_UIS_H})

View File

@ -0,0 +1,55 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>QgsRelReferenceConfigDlgBase</class>
<widget class="QWidget" name="QgsRelReferenceConfigDlgBase">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>175</height>
</rect>
</property>
<property name="windowTitle">
<string>Dialog</string>
</property>
<layout class="QFormLayout" name="formLayout">
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Display expression</string>
</property>
</widget>
</item>
<item row="2" column="0" colspan="2">
<widget class="QCheckBox" name="mCbxAllowNull">
<property name="text">
<string>Allow NULL value</string>
</property>
</widget>
</item>
<item row="3" column="0" colspan="2">
<widget class="QCheckBox" name="mCbxShowForm">
<property name="text">
<string>Show embedded form</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Relation</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QComboBox" name="mComboRelation"/>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="mTxtDisplayExpression"/>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View File

@ -43,7 +43,7 @@
<string/>
</property>
<property name="icon">
<iconset resource="../../images/images.qrc">
<iconset>
<normaloff>:/images/themes/default/mActionToggleEditing.svg</normaloff>:/images/themes/default/mActionToggleEditing.svg</iconset>
</property>
<property name="iconSize">
@ -72,7 +72,7 @@
<string/>
</property>
<property name="icon">
<iconset resource="../../images/images.qrc">
<iconset>
<normaloff>:/images/themes/default/mActionSaveEdits.svg</normaloff>:/images/themes/default/mActionSaveEdits.svg</iconset>
</property>
<property name="iconSize">
@ -118,7 +118,7 @@
<string>...</string>
</property>
<property name="icon">
<iconset resource="../../images/images.qrc">
<iconset>
<normaloff>:/images/themes/default/mActionDeleteSelected.svg</normaloff>:/images/themes/default/mActionDeleteSelected.svg</iconset>
</property>
<property name="iconSize">
@ -148,7 +148,7 @@
<string>...</string>
</property>
<property name="icon">
<iconset resource="../../images/images.qrc">
<iconset>
<normaloff>:/images/themes/default/mIconExpressionSelect.svg</normaloff>:/images/themes/default/mIconExpressionSelect.svg</iconset>
</property>
<property name="iconSize">
@ -244,7 +244,7 @@
</property>
<property name="icon">
<iconset>
<normaloff>:/images/themes/default/mActionPanToSelected.svg</normaloff>../../images/themes/default/mActionPanToSelected.svg</iconset>
<normaloff>:/images/themes/default/mActionPanToSelected.svg</normaloff>:/images/themes/default/mActionPanToSelected.svg</iconset>
</property>
<property name="iconSize">
<size>
@ -269,7 +269,7 @@
<string/>
</property>
<property name="icon">
<iconset resource=":/imagesimages.qrc">
<iconset>
<normaloff>:/images/themes/default/mActionZoomToSelected.svg</normaloff>:/images/themes/default/mActionZoomToSelected.svg</iconset>
</property>
<property name="iconSize">
@ -497,7 +497,7 @@
<item>
<widget class="QToolButton" name="mAttributeViewButton">
<property name="text">
<string>Attribute View</string>
<string>Form View</string>
</property>
<property name="icon">
<iconset>
@ -553,7 +553,7 @@
</action>
<action name="mActionShowAllFilter">
<property name="icon">
<iconset resource="../../images/images.qrc">
<iconset>
<normaloff>:/images/themes/default/mActionFilter.png</normaloff>:/images/themes/default/mActionFilter.png</iconset>
</property>
<property name="text">
@ -562,7 +562,7 @@
</action>
<action name="mActionSelectedFilter">
<property name="icon">
<iconset resource="../../images/images.qrc">
<iconset>
<normaloff>:/images/themes/default/mActionFilter.png</normaloff>:/images/themes/default/mActionFilter.png</iconset>
</property>
<property name="text">
@ -571,7 +571,7 @@
</action>
<action name="mActionVisibleFilter">
<property name="icon">
<iconset resource="../../images/images.qrc">
<iconset>
<normaloff>:/images/themes/default/mActionFilter.png</normaloff>:/images/themes/default/mActionFilter.png</iconset>
</property>
<property name="text">
@ -585,7 +585,7 @@
</action>
<action name="mActionEditedFilter">
<property name="icon">
<iconset resource="../../images/images.qrc">
<iconset>
<normaloff>:/images/themes/default/mActionFilter.png</normaloff>:/images/themes/default/mActionFilter.png</iconset>
</property>
<property name="text">
@ -622,9 +622,7 @@
<tabstop>mRemoveAttribute</tabstop>
<tabstop>mOpenFieldCalculator</tabstop>
</tabstops>
<resources>
<include location="../../images/images.qrc"/>
</resources>
<resources/>
<connections>
<connection>
<sender>mToggleEditingButton</sender>

View File

@ -0,0 +1,78 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>QgsFeatureSelectionDlg</class>
<widget class="QDialog" name="QgsFeatureSelectionDlg">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>468</width>
<height>496</height>
</rect>
</property>
<property name="windowTitle">
<string>Dialog</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QgsDualView" name="mDualView">
<widget class="QWidget" name="page"/>
<widget class="QWidget" name="page_2"/>
</widget>
</item>
<item>
<widget class="QDialogButtonBox" name="mButtonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>QgsDualView</class>
<extends>QStackedWidget</extends>
<header>qgsdualview.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources/>
<connections>
<connection>
<sender>mButtonBox</sender>
<signal>accepted()</signal>
<receiver>QgsFeatureSelectionDlg</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>mButtonBox</sender>
<signal>rejected()</signal>
<receiver>QgsFeatureSelectionDlg</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@ -107,12 +107,20 @@
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<widget class="QWidget" name="mAttributesListFrame" native="true">
<layout class="QGridLayout" name="mAttributesListLayout">
<property name="margin">
<number>0</number>
</property>
</layout>
<widget class="QgsCollapsibleGroupBox" name="mAttributesListFrame">
<property name="title">
<string>Fields</string>
</property>
<layout class="QGridLayout" name="mAttributesListLayout"/>
</widget>
<widget class="QgsCollapsibleGroupBox" name="mRelationsFrame">
<property name="title">
<string>Relations</string>
</property>
<property name="collapsed" stdset="0">
<bool>true</bool>
</property>
<layout class="QGridLayout" name="mRelationsFrameLayout"/>
</widget>
</widget>
</item>
@ -430,6 +438,14 @@ MyForms.py must live on PYTHONPATH, .qgis/python, or inside the project folder.<
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>QgsCollapsibleGroupBox</class>
<extends>QGroupBox</extends>
<header>qgscollapsiblegroupbox.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources>
<include location="../../images/images.qrc"/>
</resources>

View File

@ -152,6 +152,15 @@
<normaloff>:/images/themes/default/propertyicons/action.svg</normaloff>:/images/themes/default/propertyicons/action.svg</iconset>
</property>
</item>
<item>
<property name="text">
<string>Relations</string>
</property>
<property name="icon">
<iconset resource="../../images/images.qrc">
<normaloff>:/images/themes/default/relation.svg</normaloff>:/images/themes/default/relation.svg</iconset>
</property>
</item>
</widget>
</item>
</layout>
@ -217,9 +226,9 @@
<property name="geometry">
<rect>
<x>0</x>
<y>-19</y>
<width>631</width>
<height>686</height>
<y>0</y>
<width>640</width>
<height>712</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_8">
@ -776,8 +785,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>646</width>
<height>667</height>
<width>323</width>
<height>46</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_7">
@ -836,8 +845,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>646</width>
<height>669</height>
<width>133</width>
<height>100</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_10">
@ -918,8 +927,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>646</width>
<height>669</height>
<width>371</width>
<height>336</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_12">
@ -1296,8 +1305,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>631</width>
<height>1254</height>
<width>491</width>
<height>1347</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_13">
@ -1928,8 +1937,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>646</width>
<height>669</height>
<width>163</width>
<height>111</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_17">
@ -1970,6 +1979,13 @@
</item>
</layout>
</widget>
<widget class="QWidget" name="mTabRelations">
<layout class="QGridLayout" name="gridLayout_16">
<property name="margin">
<number>0</number>
</property>
</layout>
</widget>
</widget>
</item>
</layout>

View File

@ -0,0 +1,128 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>QgsRelationAddDlgBase</class>
<widget class="QDialog" name="QgsRelationAddDlgBase">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>581</width>
<height>254</height>
</rect>
</property>
<property name="windowTitle">
<string>Dialog</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="4" column="1" colspan="2">
<widget class="QComboBox" name="mCbxReferencingField"/>
</item>
<item row="3" column="1" colspan="2">
<widget class="QComboBox" name="mCbxReferencingLayer"/>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Referencing Field</string>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Referenced Layer (Parent)</string>
</property>
</widget>
</item>
<item row="6" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Referenced Field</string>
</property>
</widget>
</item>
<item row="5" column="1" colspan="2">
<widget class="QComboBox" name="mCbxReferencedLayer"/>
</item>
<item row="6" column="1" colspan="2">
<widget class="QComboBox" name="mCbxReferencedField"/>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Referencing Layer (Child)</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_7">
<property name="text">
<string>Name</string>
</property>
</widget>
</item>
<item row="14" column="0" colspan="3">
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
<item row="8" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
<string>Id</string>
</property>
</widget>
</item>
<item row="8" column="1">
<widget class="QLineEdit" name="mTxtRelationId">
<property name="placeholderText">
<string>[Generated automatically]</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLineEdit" name="mTxtRelationName"/>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>QgsRelationAddDlgBase</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>QgsRelationAddDlgBase</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@ -0,0 +1,182 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>QgsRelationEditorWidgetBase</class>
<widget class="QgsCollapsibleGroupBox" name="QgsRelationEditorWidgetBase">
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QToolButton" name="mToggleEditingButton">
<property name="toolTip">
<string>Toggle editing</string>
</property>
<property name="text">
<string>Toggle editing</string>
</property>
<property name="icon">
<iconset resource="../../images/images.qrc">
<normaloff>:/images/themes/default/mActionToggleEditing.png</normaloff>:/images/themes/default/mActionToggleEditing.png</iconset>
</property>
<property name="iconSize">
<size>
<width>16</width>
<height>16</height>
</size>
</property>
<property name="checkable">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="mAddFeatureButton">
<property name="text">
<string>New</string>
</property>
<property name="icon">
<iconset resource="../../images/images.qrc">
<normaloff>:/images/themes/default/mActionAdd.svg</normaloff>:/images/themes/default/mActionAdd.svg</iconset>
</property>
<property name="iconSize">
<size>
<width>24</width>
<height>24</height>
</size>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="mDeleteFeatureButton">
<property name="text">
<string>Delete</string>
</property>
<property name="icon">
<iconset resource="../../images/images.qrc">
<normaloff>:/images/themes/default/mActionRemove.svg</normaloff>:/images/themes/default/mActionRemove.svg</iconset>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="mLinkFeatureButton">
<property name="text">
<string>Link</string>
</property>
<property name="icon">
<iconset resource="../../images/images.qrc">
<normaloff>:/images/themes/default/mActionLink.svg</normaloff>:/images/themes/default/mActionLink.svg</iconset>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="mUnlinkFeatureButton">
<property name="text">
<string>Unlink</string>
</property>
<property name="icon">
<iconset resource="../../images/images.qrc">
<normaloff>:/images/themes/default/mActionUnlink.svg</normaloff>:/images/themes/default/mActionUnlink.svg</iconset>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QToolButton" name="mFormViewButton">
<property name="text">
<string>Form View</string>
</property>
<property name="icon">
<iconset resource="../../images/images.qrc">
<normaloff>:/images/themes/default/mActionPropertyItem.png</normaloff>:/images/themes/default/mActionPropertyItem.png</iconset>
</property>
<property name="iconSize">
<size>
<width>24</width>
<height>24</height>
</size>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<attribute name="buttonGroup">
<string notr="true">mViewModeButtonGroup</string>
</attribute>
</widget>
</item>
<item>
<widget class="QToolButton" name="mTableViewButton">
<property name="text">
<string>Table View</string>
</property>
<property name="icon">
<iconset resource="../../images/images.qrc">
<normaloff>:/images/themes/default/mActionOpenTable.png</normaloff>:/images/themes/default/mActionOpenTable.png</iconset>
</property>
<property name="iconSize">
<size>
<width>24</width>
<height>24</height>
</size>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>true</bool>
</property>
<attribute name="buttonGroup">
<string notr="true">mViewModeButtonGroup</string>
</attribute>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QWidget" name="mBrowserWidget" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="autoFillBackground">
<bool>false</bool>
</property>
<property name="styleSheet">
<string notr="true"/>
</property>
<layout class="QGridLayout" name="gridLayout"/>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>QgsCollapsibleGroupBox</class>
<extends>QGroupBox</extends>
<header>qgscollapsiblegroupbox.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources>
<include location="../../images/images.qrc"/>
</resources>
<connections/>
<buttongroups>
<buttongroup name="mViewModeButtonGroup"/>
</buttongroups>
</ui>

View File

@ -0,0 +1,109 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>QgsRelationManagerDialogBase</class>
<widget class="QWidget" name="QgsRelationManagerDialogBase">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>713</width>
<height>427</height>
</rect>
</property>
<property name="windowTitle">
<string>Dialog</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QTableWidget" name="mRelationsTable">
<column>
<property name="text">
<string>Name</string>
</property>
</column>
<column>
<property name="text">
<string>Referencing Layer</string>
</property>
</column>
<column>
<property name="text">
<string>Referencing Field</string>
</property>
</column>
<column>
<property name="text">
<string>Referenced Layer</string>
</property>
</column>
<column>
<property name="text">
<string>Referenced Field</string>
</property>
</column>
<column>
<property name="text">
<string>Id</string>
</property>
</column>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="mBtnAddRelation">
<property name="text">
<string>Add Relation</string>
</property>
<property name="icon">
<iconset resource="../../images/images.qrc">
<normaloff>:/images/themes/default/mActionSignPlus.png</normaloff>:/images/themes/default/mActionSignPlus.png</iconset>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="mBtnRemoveRelation">
<property name="text">
<string>Remove Relation</string>
</property>
<property name="icon">
<iconset resource="../../images/images.qrc">
<normaloff>:/images/themes/default/mActionSignMinus.png</normaloff>:/images/themes/default/mActionSignMinus.png</iconset>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout>
</widget>
<resources>
<include location="../../images/images.qrc"/>
</resources>
<connections/>
</ui>