Skip to content

Commit

Permalink
Merge pull request #42 from opengisch/editNewLinkedFeature
Browse files Browse the repository at this point in the history
Allow editing of newly added join features
  • Loading branch information
domi4484 authored Jun 16, 2023
2 parents 1dbcb76 + 874c46e commit 7fcb02e
Show file tree
Hide file tree
Showing 16 changed files with 476 additions and 285 deletions.
25 changes: 22 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,31 @@
## Linking Relation Editor plugin for QGIS
Linking Relation Editor plugin for QGIS
=======================================

This plugin provides a relation editor widget with an alternative linking dialog that looks somewhat like a link manager dialog. features can be linked and unlinked by moving them left and right. The effective link is created or destroyed when the dialog is accepted.

![Peek 2022-11-24 15-48](https://user-images.githubusercontent.com/9881900/203868099-90d8ceae-cbb9-488b-9564-b60930e0f82e.gif)


### Configuration
# Configuration

In the attribute form configuration select `Linking relation editor widget` as widget type for a relation:
In the attribute form configuration select `Linking relation editor widget` as widget type for a relation. The most options are the same as for the stock QGIS Relation Editor Widget, see the related [documentation](https://docs.qgis.org/3.28/en/docs/user_manual/working_with_vector/vector_properties.html).

![image](https://user-images.githubusercontent.com/9881900/204229315-1f77d01f-1c00-4574-8ea5-0bcf0e804e6f.png)


## One to one relationship

Linking can be restricted to one linked feature per feature by setting the Cardinality combobox to `One to one relation`.

![Configuration cardinality one to one](documentation/ConfigurationCardinalityOneToOne.png)


## Show and edit join table attributes

![Configuration show and edit join table attributes](documentation/ConfigurationShowAndEditJoinTableAttributes.png)

When this option is enabled, the link manager dialog will show the linked features in a tree structure instead of a simple list. The tree elements can be expanded to show the attribute form of the join feature. The attribute form can be configured as usual in the layer properties of the join layer.

![Join feature editing](documentation/JoinFeatureEditing.gif)

**Note:** If a feature is not respecting the constraints, it will not be linked/modified when the dialog is accepted. Other features with valid attributes will still be linked.
Binary file modified demo_projects/bee_farming.gpkg
Binary file not shown.
31 changes: 16 additions & 15 deletions demo_projects/bee_farming.qgs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<qgis projectname="Simple Bee Farming Demo" saveDateTime="2023-04-09T22:20:09" saveUser="domi" saveUserFull="Damiano" version="3.30.0-'s-Hertogenbosch">
<qgis projectname="Simple Bee Farming Demo" saveDateTime="2023-06-16T08:13:46" saveUser="domi" saveUserFull="Damiano" version="3.30.2-'s-Hertogenbosch">
<homePath path=""></homePath>
<title>Simple Bee Farming Demo</title>
<transaction mode="AutomaticGroups"></transaction>
<transaction mode="BufferedGroups"></transaction>
<projectFlags set=""></projectFlags>
<projectCrs>
<spatialrefsys nativeFormat="Wkt">
Expand Down Expand Up @@ -115,10 +115,10 @@
<mapcanvas annotationsVisible="1" name="theMapCanvas">
<units>meters</units>
<extent>
<xmin>957929.63294554990716279</xmin>
<ymin>5862860.31842787750065327</ymin>
<xmax>958853.91945121390745044</xmax>
<ymax>5863280.68026205152273178</ymax>
<xmin>955230.50237378210294992</xmin>
<ymin>5863073.17550766747444868</ymin>
<xmax>961441.30490439583081752</xmax>
<ymax>5865897.82384689804166555</ymax>
</extent>
<rotation>0</rotation>
<destinationsrs>
Expand Down Expand Up @@ -2298,7 +2298,7 @@ def my_form_open(dialog, layer, feature):
<Option name="drawToAllParts" type="bool" value="false"></Option>
<Option name="enabled" type="QString" value="0"></Option>
<Option name="labelAnchorPoint" type="QString" value="point_on_exterior"></Option>
<Option name="lineSymbol" type="QString" value="&lt;symbol frame_rate=&quot;10&quot; name=&quot;symbol&quot; is_animated=&quot;0&quot; type=&quot;line&quot; force_rhr=&quot;0&quot; alpha=&quot;1&quot; clip_to_extent=&quot;1&quot;>&lt;data_defined_properties>&lt;Option type=&quot;Map&quot;>&lt;Option name=&quot;name&quot; type=&quot;QString&quot; value=&quot;&quot;/>&lt;Option name=&quot;properties&quot;/>&lt;Option name=&quot;type&quot; type=&quot;QString&quot; value=&quot;collection&quot;/>&lt;/Option>&lt;/data_defined_properties>&lt;layer id=&quot;{964837c1-1935-4d72-9c1c-6d7a0b982761}&quot; locked=&quot;0&quot; class=&quot;SimpleLine&quot; pass=&quot;0&quot; enabled=&quot;1&quot;>&lt;Option type=&quot;Map&quot;>&lt;Option name=&quot;align_dash_pattern&quot; type=&quot;QString&quot; value=&quot;0&quot;/>&lt;Option name=&quot;capstyle&quot; type=&quot;QString&quot; value=&quot;square&quot;/>&lt;Option name=&quot;customdash&quot; type=&quot;QString&quot; value=&quot;5;2&quot;/>&lt;Option name=&quot;customdash_map_unit_scale&quot; type=&quot;QString&quot; value=&quot;3x:0,0,0,0,0,0&quot;/>&lt;Option name=&quot;customdash_unit&quot; type=&quot;QString&quot; value=&quot;MM&quot;/>&lt;Option name=&quot;dash_pattern_offset&quot; type=&quot;QString&quot; value=&quot;0&quot;/>&lt;Option name=&quot;dash_pattern_offset_map_unit_scale&quot; type=&quot;QString&quot; value=&quot;3x:0,0,0,0,0,0&quot;/>&lt;Option name=&quot;dash_pattern_offset_unit&quot; type=&quot;QString&quot; value=&quot;MM&quot;/>&lt;Option name=&quot;draw_inside_polygon&quot; type=&quot;QString&quot; value=&quot;0&quot;/>&lt;Option name=&quot;joinstyle&quot; type=&quot;QString&quot; value=&quot;bevel&quot;/>&lt;Option name=&quot;line_color&quot; type=&quot;QString&quot; value=&quot;60,60,60,255&quot;/>&lt;Option name=&quot;line_style&quot; type=&quot;QString&quot; value=&quot;solid&quot;/>&lt;Option name=&quot;line_width&quot; type=&quot;QString&quot; value=&quot;0.3&quot;/>&lt;Option name=&quot;line_width_unit&quot; type=&quot;QString&quot; value=&quot;MM&quot;/>&lt;Option name=&quot;offset&quot; type=&quot;QString&quot; value=&quot;0&quot;/>&lt;Option name=&quot;offset_map_unit_scale&quot; type=&quot;QString&quot; value=&quot;3x:0,0,0,0,0,0&quot;/>&lt;Option name=&quot;offset_unit&quot; type=&quot;QString&quot; value=&quot;MM&quot;/>&lt;Option name=&quot;ring_filter&quot; type=&quot;QString&quot; value=&quot;0&quot;/>&lt;Option name=&quot;trim_distance_end&quot; type=&quot;QString&quot; value=&quot;0&quot;/>&lt;Option name=&quot;trim_distance_end_map_unit_scale&quot; type=&quot;QString&quot; value=&quot;3x:0,0,0,0,0,0&quot;/>&lt;Option name=&quot;trim_distance_end_unit&quot; type=&quot;QString&quot; value=&quot;MM&quot;/>&lt;Option name=&quot;trim_distance_start&quot; type=&quot;QString&quot; value=&quot;0&quot;/>&lt;Option name=&quot;trim_distance_start_map_unit_scale&quot; type=&quot;QString&quot; value=&quot;3x:0,0,0,0,0,0&quot;/>&lt;Option name=&quot;trim_distance_start_unit&quot; type=&quot;QString&quot; value=&quot;MM&quot;/>&lt;Option name=&quot;tweak_dash_pattern_on_corners&quot; type=&quot;QString&quot; value=&quot;0&quot;/>&lt;Option name=&quot;use_custom_dash&quot; type=&quot;QString&quot; value=&quot;0&quot;/>&lt;Option name=&quot;width_map_unit_scale&quot; type=&quot;QString&quot; value=&quot;3x:0,0,0,0,0,0&quot;/>&lt;/Option>&lt;data_defined_properties>&lt;Option type=&quot;Map&quot;>&lt;Option name=&quot;name&quot; type=&quot;QString&quot; value=&quot;&quot;/>&lt;Option name=&quot;properties&quot;/>&lt;Option name=&quot;type&quot; type=&quot;QString&quot; value=&quot;collection&quot;/>&lt;/Option>&lt;/data_defined_properties>&lt;/layer>&lt;/symbol>"></Option>
<Option name="lineSymbol" type="QString" value="&lt;symbol is_animated=&quot;0&quot; alpha=&quot;1&quot; force_rhr=&quot;0&quot; name=&quot;symbol&quot; clip_to_extent=&quot;1&quot; frame_rate=&quot;10&quot; type=&quot;line&quot;>&lt;data_defined_properties>&lt;Option type=&quot;Map&quot;>&lt;Option name=&quot;name&quot; type=&quot;QString&quot; value=&quot;&quot;/>&lt;Option name=&quot;properties&quot;/>&lt;Option name=&quot;type&quot; type=&quot;QString&quot; value=&quot;collection&quot;/>&lt;/Option>&lt;/data_defined_properties>&lt;layer locked=&quot;0&quot; enabled=&quot;1&quot; pass=&quot;0&quot; id=&quot;{964837c1-1935-4d72-9c1c-6d7a0b982761}&quot; class=&quot;SimpleLine&quot;>&lt;Option type=&quot;Map&quot;>&lt;Option name=&quot;align_dash_pattern&quot; type=&quot;QString&quot; value=&quot;0&quot;/>&lt;Option name=&quot;capstyle&quot; type=&quot;QString&quot; value=&quot;square&quot;/>&lt;Option name=&quot;customdash&quot; type=&quot;QString&quot; value=&quot;5;2&quot;/>&lt;Option name=&quot;customdash_map_unit_scale&quot; type=&quot;QString&quot; value=&quot;3x:0,0,0,0,0,0&quot;/>&lt;Option name=&quot;customdash_unit&quot; type=&quot;QString&quot; value=&quot;MM&quot;/>&lt;Option name=&quot;dash_pattern_offset&quot; type=&quot;QString&quot; value=&quot;0&quot;/>&lt;Option name=&quot;dash_pattern_offset_map_unit_scale&quot; type=&quot;QString&quot; value=&quot;3x:0,0,0,0,0,0&quot;/>&lt;Option name=&quot;dash_pattern_offset_unit&quot; type=&quot;QString&quot; value=&quot;MM&quot;/>&lt;Option name=&quot;draw_inside_polygon&quot; type=&quot;QString&quot; value=&quot;0&quot;/>&lt;Option name=&quot;joinstyle&quot; type=&quot;QString&quot; value=&quot;bevel&quot;/>&lt;Option name=&quot;line_color&quot; type=&quot;QString&quot; value=&quot;60,60,60,255&quot;/>&lt;Option name=&quot;line_style&quot; type=&quot;QString&quot; value=&quot;solid&quot;/>&lt;Option name=&quot;line_width&quot; type=&quot;QString&quot; value=&quot;0.3&quot;/>&lt;Option name=&quot;line_width_unit&quot; type=&quot;QString&quot; value=&quot;MM&quot;/>&lt;Option name=&quot;offset&quot; type=&quot;QString&quot; value=&quot;0&quot;/>&lt;Option name=&quot;offset_map_unit_scale&quot; type=&quot;QString&quot; value=&quot;3x:0,0,0,0,0,0&quot;/>&lt;Option name=&quot;offset_unit&quot; type=&quot;QString&quot; value=&quot;MM&quot;/>&lt;Option name=&quot;ring_filter&quot; type=&quot;QString&quot; value=&quot;0&quot;/>&lt;Option name=&quot;trim_distance_end&quot; type=&quot;QString&quot; value=&quot;0&quot;/>&lt;Option name=&quot;trim_distance_end_map_unit_scale&quot; type=&quot;QString&quot; value=&quot;3x:0,0,0,0,0,0&quot;/>&lt;Option name=&quot;trim_distance_end_unit&quot; type=&quot;QString&quot; value=&quot;MM&quot;/>&lt;Option name=&quot;trim_distance_start&quot; type=&quot;QString&quot; value=&quot;0&quot;/>&lt;Option name=&quot;trim_distance_start_map_unit_scale&quot; type=&quot;QString&quot; value=&quot;3x:0,0,0,0,0,0&quot;/>&lt;Option name=&quot;trim_distance_start_unit&quot; type=&quot;QString&quot; value=&quot;MM&quot;/>&lt;Option name=&quot;tweak_dash_pattern_on_corners&quot; type=&quot;QString&quot; value=&quot;0&quot;/>&lt;Option name=&quot;use_custom_dash&quot; type=&quot;QString&quot; value=&quot;0&quot;/>&lt;Option name=&quot;width_map_unit_scale&quot; type=&quot;QString&quot; value=&quot;3x:0,0,0,0,0,0&quot;/>&lt;/Option>&lt;data_defined_properties>&lt;Option type=&quot;Map&quot;>&lt;Option name=&quot;name&quot; type=&quot;QString&quot; value=&quot;&quot;/>&lt;Option name=&quot;properties&quot;/>&lt;Option name=&quot;type&quot; type=&quot;QString&quot; value=&quot;collection&quot;/>&lt;/Option>&lt;/data_defined_properties>&lt;/layer>&lt;/symbol>"></Option>
<Option name="minLength" type="double" value="0"></Option>
<Option name="minLengthMapUnitScale" type="QString" value="3x:0,0,0,0,0,0"></Option>
<Option name="minLengthUnit" type="QString" value="MM"></Option>
Expand Down Expand Up @@ -2545,8 +2545,8 @@ def my_form_open(dialog, layer, feature):
<attributeactions>
<defaultAction key="Canvas" value="{3df20b6f-cf49-467d-8cde-d37cd72688e6}"></defaultAction>
<actionsetting action="" capture="0" icon="" id="{3df20b6f-cf49-467d-8cde-d37cd72688e6}" isEnabledOnlyWhenEditable="0" name="" notificationMessage="" shortTitle="" type="0">
<actionScope id="Feature"></actionScope>
<actionScope id="Canvas"></actionScope>
<actionScope id="Feature"></actionScope>
<actionScope id="Field"></actionScope>
</actionsetting>
</attributeactions>
Expand Down Expand Up @@ -3363,8 +3363,8 @@ def my_form_open(dialog, layer, feature):
<Option type="QString" value="&quot;fid&quot;"></Option>
</Option>
<Option name="embeddedWidgets/count" type="int" value="0"></Option>
<Option name="variableNames"></Option>
<Option name="variableValues"></Option>
<Option name="variableNames" type="invalid"></Option>
<Option name="variableValues" type="invalid"></Option>
</Option>
</customproperties>
<blendMode>0</blendMode>
Expand Down Expand Up @@ -3819,8 +3819,8 @@ def my_form_open(dialog, layer, feature):
<Option type="QString" value="&quot;uuid&quot;"></Option>
</Option>
<Option name="embeddedWidgets/count" type="int" value="0"></Option>
<Option name="variableNames" type="invalid"></Option>
<Option name="variableValues" type="invalid"></Option>
<Option name="variableNames"></Option>
<Option name="variableValues"></Option>
</Option>
</customproperties>
<geometryOptions geometryPrecision="0" removeDuplicateNodes="0">
Expand Down Expand Up @@ -3914,7 +3914,7 @@ def my_form_open(dialog, layer, feature):
<constraint constraints="0" exp_strength="0" field="uuid" notnull_strength="0" unique_strength="0"></constraint>
<constraint constraints="0" exp_strength="0" field="observation_uuid" notnull_strength="0" unique_strength="0"></constraint>
<constraint constraints="0" exp_strength="0" field="species_uuid" notnull_strength="0" unique_strength="0"></constraint>
<constraint constraints="1" exp_strength="0" field="quantity" notnull_strength="1" unique_strength="0"></constraint>
<constraint constraints="1" exp_strength="0" field="quantity" notnull_strength="2" unique_strength="0"></constraint>
</constraints>
<constraintExpressions>
<constraint desc="" exp="" field="fid"></constraint>
Expand Down Expand Up @@ -5117,6 +5117,7 @@ def my_form_open(dialog, layer, feature):
</WFSTLayers>
<WFSUrl type="QString"></WFSUrl>
<WMSAccessConstraints type="QString">None</WMSAccessConstraints>
<WMSAddLayerGroupsLegendGraphic type="bool">false</WMSAddLayerGroupsLegendGraphic>
<WMSAddWktGeometry type="bool">false</WMSAddWktGeometry>
<WMSContactMail type="QString"></WMSContactMail>
<WMSContactOrganization type="QString">OPENGIS.ch</WMSContactOrganization>
Expand Down Expand Up @@ -6440,7 +6441,7 @@ def my_form_open(dialog, layer, feature):
<Bookmarks></Bookmarks>
<ProjectViewSettings UseProjectScales="0" rotation="0">
<Scales></Scales>
<DefaultViewExtent xmax="958853.91945121390745044" xmin="957929.63294554990716279" ymax="5863320.89696195349097252" ymin="5862820.10172797553241253">
<DefaultViewExtent xmax="961932.31381963938474655" xmin="954739.49345853854902089" ymax="5865897.82384689804166555" ymin="5863073.17550766747444868">
<spatialrefsys nativeFormat="Wkt">
<wkt>PROJCRS["WGS 84 / Pseudo-Mercator",BASEGEOGCRS["WGS 84",ENSEMBLE["World Geodetic System 1984 ensemble",MEMBER["World Geodetic System 1984 (Transit)"],MEMBER["World Geodetic System 1984 (G730)"],MEMBER["World Geodetic System 1984 (G873)"],MEMBER["World Geodetic System 1984 (G1150)"],MEMBER["World Geodetic System 1984 (G1674)"],MEMBER["World Geodetic System 1984 (G1762)"],MEMBER["World Geodetic System 1984 (G2139)"],ELLIPSOID["WGS 84",6378137,298.257223563,LENGTHUNIT["metre",1]],ENSEMBLEACCURACY[2.0]],PRIMEM["Greenwich",0,ANGLEUNIT["degree",0.0174532925199433]],ID["EPSG",4326]],CONVERSION["Popular Visualisation Pseudo-Mercator",METHOD["Popular Visualisation Pseudo Mercator",ID["EPSG",1024]],PARAMETER["Latitude of natural origin",0,ANGLEUNIT["degree",0.0174532925199433],ID["EPSG",8801]],PARAMETER["Longitude of natural origin",0,ANGLEUNIT["degree",0.0174532925199433],ID["EPSG",8802]],PARAMETER["False easting",0,LENGTHUNIT["metre",1],ID["EPSG",8806]],PARAMETER["False northing",0,LENGTHUNIT["metre",1],ID["EPSG",8807]]],CS[Cartesian,2],AXIS["easting (X)",east,ORDER[1],LENGTHUNIT["metre",1]],AXIS["northing (Y)",north,ORDER[2],LENGTHUNIT["metre",1]],USAGE[SCOPE["Web mapping and visualisation."],AREA["World between 85.06°S and 85.06°N."],BBOX[-85.06,-180,85.06,180]],ID["EPSG",3857]]</wkt>
<proj4>+proj=merc +a=6378137 +b=6378137 +lat_ts=0 +lon_0=0 +x_0=0 +y_0=0 +k=1 +units=m +nadgrids=@null +wktext +no_defs</proj4>
Expand Down Expand Up @@ -6505,7 +6506,7 @@ def my_form_open(dialog, layer, feature):
</spatialrefsys>
</CoordinateCustomCrs>
</ProjectDisplaySettings>
<ProjectGpsSettings autoAddTrackVertices="0" autoCommitFeatures="0" destinationFollowsActiveLayer="1" destinationLayer="fauna_observations_bfd869bd_c091_4aa5_8f51_24eeb4062a59" destinationLayerName="FaunaObservations" destinationLayerProvider="ogr" destinationLayerSource="/home/domi/dev/plugin/qgis-linking-relation-editor/demo_projects/bee_farming.gpkg|layername=fauna_observations">
<ProjectGpsSettings autoAddTrackVertices="0" autoCommitFeatures="0" destinationFollowsActiveLayer="1" destinationLayer="link_fauna_observations_species_034dd163_4071_40b4_89fd_a8ab96aaf6f9" destinationLayerName="link_fauna_observations_species" destinationLayerProvider="ogr" destinationLayerSource="/home/domi/dev/plugin/qgis-linking-relation-editor/demo_projects/bee_farming.gpkg|layername=link_fauna_observations_species">
<timeStampFields></timeStampFields>
</ProjectGpsSettings>
</qgis>
Binary file modified demo_projects/bee_farming_attachments.zip
Binary file not shown.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added documentation/JoinFeatureEditing.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit 7fcb02e

Please sign in to comment.