27 Commits

Author SHA1 Message Date
Michael Otto a4f50d6eb5 auf neuen Release-Workflow umgestellt
Release Plugin / release (push) Successful in 4s
2026-07-02 11:08:25 +02:00
Daniel ce4a7c51c4 qml Biotop-Linien ergänzt 2026-07-01 15:43:40 +02:00
Daniel dad11bd249 Biotope und Schutzgebiete in Linkliste ergänzt 2026-07-01 15:39:43 +02:00
Daniel 477e4f6f5c QML-Dateien ergänzt 2026-07-01 15:38:20 +02:00
Daniel 04ab4867f9 QML-Dateien ergänzt 2026-07-01 15:37:59 +02:00
release-bot 303f296af1 Release 26.6.1-unstable 2026-06-19 09:54:37 +00:00
Daniel 488d4bd125 changelog.txt aktualisiert
Release Plugin / release (push) Successful in 8s
2026-06-19 11:53:58 +02:00
Daniel 02557d0fdf Merge pull request 'VLN-API integriert' (#25) from API-Integration_Plan41 into unstable
Reviewed-on: #25
2026-06-19 11:49:43 +02:00
Daniel 16d6474bb9 VLN-API integriert 2026-06-19 11:47:15 +02:00
release-bot 10615b31f4 Release 26.4.3-unstable 2026-04-22 07:24:17 +00:00
Daniel ab51838db5 Merge pull request 'test überarbeitet' (#24) from feature/Tests_erweitert into unstable
Release Plugin / release (push) Successful in 3s
Reviewed-on: #24
2026-04-22 09:22:49 +02:00
Daniel e3e858233d Merge branch 'unstable' of https://entwicklung.flurneuordnung-sachsen.de/AG_QGIS/Plugin_SN_Plan41 into feature/Tests_erweitert 2026-04-22 09:21:18 +02:00
release-bot cc2d5c6200 Release 26.4.2-unstable 2026-04-22 07:07:17 +00:00
Daniel b2ee167132 QgsmaxVersion eingefügt
Release Plugin / release (push) Successful in 4s
2026-04-22 09:03:54 +02:00
Daniel 600a3c7aff test überarbeitet 2026-04-20 15:36:29 +02:00
Daniel 8f9cf4c9fb pdoc-dockstrings ergänzt 2026-04-20 14:31:49 +02:00
release-bot 18573cb3be Release 26.4.2-testing 2026-04-10 09:32:49 +00:00
Daniel 6b0d94c54e Merge pull request 'Druckfunktion nach sn_basis verschben, Bugfixes' (#22) from unstable into testing
Release Plugin / release (push) Successful in 3s
Reviewed-on: #22
2026-04-10 11:30:03 +02:00
Daniel a9f65893f0 Merge pull request 'log auf html umgestellt, meldebanner entfernt' (#21) from bug/Log_bereinigen into unstable
Reviewed-on: #21
2026-04-10 07:09:40 +02:00
Daniel dcaca4c883 log auf html umgestellt, meldebanner entfernt 2026-04-10 07:07:21 +02:00
release-bot dbd5fca40b Release 26.04.1-unstable 2026-04-08 12:39:37 +00:00
Daniel ecb1e49d8d Merge pull request 'verfahrensgebiet-Vaiable wird sauber gesetzt' (#20) from bug/Verfahrensgebiet_nicht_übernommen into unstable
Release Plugin / release (push) Successful in 4s
Reviewed-on: #20
2026-04-08 14:38:04 +02:00
Daniel ad6c7ea3e1 verfahrensgebiet-Vaiable wird sauber gesetzt 2026-04-08 14:36:30 +02:00
release-bot 1bb425e419 Release 26.3.3-unstable 2026-03-27 10:28:56 +00:00
Daniel b8f36bab7a Merge pull request 'Verfahrensgebiet-Layerauswahl nach sn_verfahrensgebiet verschoben' (#19) from refactor/Verfahrensgebiet-Auswahl_nach_sn_verfahrensgebiet into unstable
Release Plugin / release (push) Successful in 3s
Reviewed-on: #19
2026-03-27 11:26:52 +01:00
Daniel aacba1e5eb Verfahrensgebiet-Layerauswahl nach sn_verfahrensgebiet verschoben 2026-03-27 11:19:37 +01:00
release-bot 9efeff5aff Release 26.3.2-unstable 2026-03-26 20:47:58 +00:00
30 changed files with 13951 additions and 269 deletions
@@ -1,12 +1,12 @@
[general]
version=26.3.1-testing
version=
name=LNO Sachsen | Plan41
description=Plugin zum Erzeugen der Pläne nach §38 und §41
author=Daniel Helbig, Michael Otto
homepage=https://entwicklung.flurneuordnung-sachsen.de/AG_QGIS/Plugin_SN_Plan41
tracker=https://entwicklung.flurneuordnung-sachsen.de/AG_QGIS/Plugin_SN_Plan41/issues
repository=https://entwicklung.flurneuordnung-sachsen.de/AG_QGIS/Plugin_Test_Action/src/branch/testing/
repository=https://entwicklung.flurneuordnung-sachsen.de/AG_QGIS/Plugin_Test_Action/src/branch/unstable/
QGISMaximumVersion=4.99
qgisMinimumVersion=3.40
experimental=true
deprecated=false
+14
View File
@@ -1,3 +1,17 @@
"""sn_plan41 QGIS-Plugin für thematische Linklisten und Datenquellen.
Verwaltet Excel-basierte Link-Listen und Fachdatenabruf.
"""
def classFactory(iface):
"""Factory-Funktion für QGIS.
Wird von QGIS aufgerufen, um die Plugin-Instanz zu erstellen.
Args:
iface: QGIS-Schnittstellenobjekt
Returns:
Plan41: Instanziiertes Plugin
"""
from .main import Plan41
return Plan41(iface)
+866
View File
@@ -0,0 +1,866 @@
<!DOCTYPE qgis PUBLIC 'http://mrcc.com/qgis.dtd' 'SYSTEM'>
<qgis maxScale="0" simplifyDrawingHints="1" simplifyMaxScale="1" simplifyLocal="1" styleCategories="AllStyleCategories" labelsEnabled="0" simplifyAlgorithm="0" minScale="100000000" version="3.40.7-Bratislava" symbologyReferenceScale="-1" hasScaleBasedVisibilityFlag="0" autoRefreshMode="Disabled" readOnly="0" autoRefreshTime="0" simplifyDrawingTol="1">
<flags>
<Identifiable>1</Identifiable>
<Removable>1</Removable>
<Searchable>1</Searchable>
<Private>0</Private>
</flags>
<temporal endExpression="" durationField="OBJECTID" enabled="0" mode="0" fixedDuration="0" startField="" accumulate="0" limitMode="0" endField="" durationUnit="min" startExpression="">
<fixedRange>
<start></start>
<end></end>
</fixedRange>
</temporal>
<elevation respectLayerSymbol="1" zscale="1" extrusionEnabled="0" extrusion="0" type="IndividualFeatures" clamping="Terrain" symbology="Line" binding="Centroid" showMarkerSymbolInSurfacePlots="0" zoffset="0">
<data-defined-properties>
<Option type="Map">
<Option name="name" type="QString" value=""/>
<Option name="properties"/>
<Option name="type" type="QString" value="collection"/>
</Option>
</data-defined-properties>
<profileLineSymbol>
<symbol frame_rate="10" clip_to_extent="1" is_animated="0" name="" force_rhr="0" type="line" alpha="1">
<data_defined_properties>
<Option type="Map">
<Option name="name" type="QString" value=""/>
<Option name="properties"/>
<Option name="type" type="QString" value="collection"/>
</Option>
</data_defined_properties>
<layer enabled="1" class="SimpleLine" locked="0" id="{6c29bf72-f401-4d8a-b41c-3b305bb5a1cb}" pass="0">
<Option type="Map">
<Option name="align_dash_pattern" type="QString" value="0"/>
<Option name="capstyle" type="QString" value="square"/>
<Option name="customdash" type="QString" value="5;2"/>
<Option name="customdash_map_unit_scale" type="QString" value="3x:0,0,0,0,0,0"/>
<Option name="customdash_unit" type="QString" value="MM"/>
<Option name="dash_pattern_offset" type="QString" value="0"/>
<Option name="dash_pattern_offset_map_unit_scale" type="QString" value="3x:0,0,0,0,0,0"/>
<Option name="dash_pattern_offset_unit" type="QString" value="MM"/>
<Option name="draw_inside_polygon" type="QString" value="0"/>
<Option name="joinstyle" type="QString" value="bevel"/>
<Option name="line_color" type="QString" value="152,125,183,255,rgb:0.59607843137254901,0.49019607843137253,0.71764705882352942,1"/>
<Option name="line_style" type="QString" value="solid"/>
<Option name="line_width" type="QString" value="0.6"/>
<Option name="line_width_unit" type="QString" value="MM"/>
<Option name="offset" type="QString" value="0"/>
<Option name="offset_map_unit_scale" type="QString" value="3x:0,0,0,0,0,0"/>
<Option name="offset_unit" type="QString" value="MM"/>
<Option name="ring_filter" type="QString" value="0"/>
<Option name="trim_distance_end" type="QString" value="0"/>
<Option name="trim_distance_end_map_unit_scale" type="QString" value="3x:0,0,0,0,0,0"/>
<Option name="trim_distance_end_unit" type="QString" value="MM"/>
<Option name="trim_distance_start" type="QString" value="0"/>
<Option name="trim_distance_start_map_unit_scale" type="QString" value="3x:0,0,0,0,0,0"/>
<Option name="trim_distance_start_unit" type="QString" value="MM"/>
<Option name="tweak_dash_pattern_on_corners" type="QString" value="0"/>
<Option name="use_custom_dash" type="QString" value="0"/>
<Option name="width_map_unit_scale" type="QString" value="3x:0,0,0,0,0,0"/>
</Option>
<data_defined_properties>
<Option type="Map">
<Option name="name" type="QString" value=""/>
<Option name="properties"/>
<Option name="type" type="QString" value="collection"/>
</Option>
</data_defined_properties>
</layer>
</symbol>
</profileLineSymbol>
<profileFillSymbol>
<symbol frame_rate="10" clip_to_extent="1" is_animated="0" name="" force_rhr="0" type="fill" alpha="1">
<data_defined_properties>
<Option type="Map">
<Option name="name" type="QString" value=""/>
<Option name="properties"/>
<Option name="type" type="QString" value="collection"/>
</Option>
</data_defined_properties>
<layer enabled="1" class="SimpleFill" locked="0" id="{e2680116-f813-4429-9fa9-d867acb612b6}" pass="0">
<Option type="Map">
<Option name="border_width_map_unit_scale" type="QString" value="3x:0,0,0,0,0,0"/>
<Option name="color" type="QString" value="152,125,183,255,rgb:0.59607843137254901,0.49019607843137253,0.71764705882352942,1"/>
<Option name="joinstyle" type="QString" value="bevel"/>
<Option name="offset" type="QString" value="0,0"/>
<Option name="offset_map_unit_scale" type="QString" value="3x:0,0,0,0,0,0"/>
<Option name="offset_unit" type="QString" value="MM"/>
<Option name="outline_color" type="QString" value="109,89,131,255,rgb:0.42575722896162355,0.35013351644159607,0.51259632257572285,1"/>
<Option name="outline_style" type="QString" value="solid"/>
<Option name="outline_width" type="QString" value="0.2"/>
<Option name="outline_width_unit" type="QString" value="MM"/>
<Option name="style" type="QString" value="solid"/>
</Option>
<data_defined_properties>
<Option type="Map">
<Option name="name" type="QString" value=""/>
<Option name="properties"/>
<Option name="type" type="QString" value="collection"/>
</Option>
</data_defined_properties>
</layer>
</symbol>
</profileFillSymbol>
<profileMarkerSymbol>
<symbol frame_rate="10" clip_to_extent="1" is_animated="0" name="" force_rhr="0" type="marker" alpha="1">
<data_defined_properties>
<Option type="Map">
<Option name="name" type="QString" value=""/>
<Option name="properties"/>
<Option name="type" type="QString" value="collection"/>
</Option>
</data_defined_properties>
<layer enabled="1" class="SimpleMarker" locked="0" id="{138fd242-c263-4b78-9e45-35a46c014c45}" pass="0">
<Option type="Map">
<Option name="angle" type="QString" value="0"/>
<Option name="cap_style" type="QString" value="square"/>
<Option name="color" type="QString" value="152,125,183,255,rgb:0.59607843137254901,0.49019607843137253,0.71764705882352942,1"/>
<Option name="horizontal_anchor_point" type="QString" value="1"/>
<Option name="joinstyle" type="QString" value="bevel"/>
<Option name="name" type="QString" value="diamond"/>
<Option name="offset" type="QString" value="0,0"/>
<Option name="offset_map_unit_scale" type="QString" value="3x:0,0,0,0,0,0"/>
<Option name="offset_unit" type="QString" value="MM"/>
<Option name="outline_color" type="QString" value="109,89,131,255,rgb:0.42575722896162355,0.35013351644159607,0.51259632257572285,1"/>
<Option name="outline_style" type="QString" value="solid"/>
<Option name="outline_width" type="QString" value="0.2"/>
<Option name="outline_width_map_unit_scale" type="QString" value="3x:0,0,0,0,0,0"/>
<Option name="outline_width_unit" type="QString" value="MM"/>
<Option name="scale_method" type="QString" value="diameter"/>
<Option name="size" type="QString" value="3"/>
<Option name="size_map_unit_scale" type="QString" value="3x:0,0,0,0,0,0"/>
<Option name="size_unit" type="QString" value="MM"/>
<Option name="vertical_anchor_point" type="QString" value="1"/>
</Option>
<data_defined_properties>
<Option type="Map">
<Option name="name" type="QString" value=""/>
<Option name="properties"/>
<Option name="type" type="QString" value="collection"/>
</Option>
</data_defined_properties>
</layer>
</symbol>
</profileMarkerSymbol>
</elevation>
<renderer-v2 forceraster="0" type="singleSymbol" enableorderby="0" referencescale="-1" symbollevels="0">
<symbols>
<symbol frame_rate="10" clip_to_extent="1" is_animated="0" name="0" force_rhr="0" type="fill" alpha="1">
<data_defined_properties>
<Option type="Map">
<Option name="name" type="QString" value=""/>
<Option name="properties"/>
<Option name="type" type="QString" value="collection"/>
</Option>
</data_defined_properties>
<layer enabled="1" class="CentroidFill" locked="0" id="{13b6615d-1ea0-4ab5-a22e-ff53199febfd}" pass="0">
<Option type="Map">
<Option name="clip_on_current_part_only" type="QString" value="1"/>
<Option name="clip_points" type="QString" value="1"/>
<Option name="point_on_all_parts" type="QString" value="1"/>
<Option name="point_on_surface" type="QString" value="1"/>
</Option>
<data_defined_properties>
<Option type="Map">
<Option name="name" type="QString" value=""/>
<Option name="properties"/>
<Option name="type" type="QString" value="collection"/>
</Option>
</data_defined_properties>
<symbol frame_rate="10" clip_to_extent="1" is_animated="0" name="@0@0" force_rhr="0" type="marker" alpha="1">
<data_defined_properties>
<Option type="Map">
<Option name="name" type="QString" value=""/>
<Option name="properties"/>
<Option name="type" type="QString" value="collection"/>
</Option>
</data_defined_properties>
<layer enabled="1" class="SimpleMarker" locked="0" id="{22dff15d-7192-4a3b-b746-ebaa619293f8}" pass="0">
<Option type="Map">
<Option name="angle" type="QString" value="0"/>
<Option name="cap_style" type="QString" value="square"/>
<Option name="color" type="QString" value="255,0,0,0,rgb:1,0,0,0"/>
<Option name="horizontal_anchor_point" type="QString" value="1"/>
<Option name="joinstyle" type="QString" value="bevel"/>
<Option name="name" type="QString" value="circle"/>
<Option name="offset" type="QString" value="0,0"/>
<Option name="offset_map_unit_scale" type="QString" value="3x:0,0,0,0,0,0"/>
<Option name="offset_unit" type="QString" value="MM"/>
<Option name="outline_color" type="QString" value="35,35,35,255,rgb:0.13725490196078433,0.13725490196078433,0.13725490196078433,1"/>
<Option name="outline_style" type="QString" value="solid"/>
<Option name="outline_width" type="QString" value="0.5"/>
<Option name="outline_width_map_unit_scale" type="QString" value="3x:0,0,0,0,0,0"/>
<Option name="outline_width_unit" type="QString" value="MM"/>
<Option name="scale_method" type="QString" value="diameter"/>
<Option name="size" type="QString" value="15"/>
<Option name="size_map_unit_scale" type="QString" value="3x:0,0,0,0,0,0"/>
<Option name="size_unit" type="QString" value="MM"/>
<Option name="vertical_anchor_point" type="QString" value="1"/>
</Option>
<data_defined_properties>
<Option type="Map">
<Option name="name" type="QString" value=""/>
<Option name="properties"/>
<Option name="type" type="QString" value="collection"/>
</Option>
</data_defined_properties>
</layer>
<layer enabled="1" class="FontMarker" locked="0" id="{be8c7958-eff9-4238-ab27-fad83324e55d}" pass="0">
<Option type="Map">
<Option name="angle" type="QString" value="0"/>
<Option name="chr" type="QString" value="N"/>
<Option name="color" type="QString" value="0,0,0,255,rgb:0,0,0,1"/>
<Option name="font" type="QString" value="Arial"/>
<Option name="font_style" type="QString" value="Standard"/>
<Option name="horizontal_anchor_point" type="QString" value="1"/>
<Option name="joinstyle" type="QString" value="bevel"/>
<Option name="offset" type="QString" value="0,0"/>
<Option name="offset_map_unit_scale" type="QString" value="3x:0,0,0,0,0,0"/>
<Option name="offset_unit" type="QString" value="MM"/>
<Option name="outline_color" type="QString" value="35,35,35,255,rgb:0.13725490196078433,0.13725490196078433,0.13725490196078433,1"/>
<Option name="outline_width" type="QString" value="0"/>
<Option name="outline_width_map_unit_scale" type="QString" value="3x:0,0,0,0,0,0"/>
<Option name="outline_width_unit" type="QString" value="MM"/>
<Option name="size" type="QString" value="5"/>
<Option name="size_map_unit_scale" type="QString" value="3x:0,0,0,0,0,0"/>
<Option name="size_unit" type="QString" value="MM"/>
<Option name="vertical_anchor_point" type="QString" value="1"/>
</Option>
<data_defined_properties>
<Option type="Map">
<Option name="name" type="QString" value=""/>
<Option name="properties"/>
<Option name="type" type="QString" value="collection"/>
</Option>
</data_defined_properties>
</layer>
</symbol>
</layer>
<layer enabled="1" class="MarkerLine" locked="0" id="{3fbb33b2-51ae-4fdb-87ff-a779155198ad}" pass="0">
<Option type="Map">
<Option name="average_angle_length" type="QString" value="4"/>
<Option name="average_angle_map_unit_scale" type="QString" value="3x:0,0,0,0,0,0"/>
<Option name="average_angle_unit" type="QString" value="MM"/>
<Option name="interval" type="QString" value="5"/>
<Option name="interval_map_unit_scale" type="QString" value="3x:0,0,0,0,0,0"/>
<Option name="interval_unit" type="QString" value="MM"/>
<Option name="offset" type="QString" value="5.55112e-17"/>
<Option name="offset_along_line" type="QString" value="0"/>
<Option name="offset_along_line_map_unit_scale" type="QString" value="3x:0,0,0,0,0,0"/>
<Option name="offset_along_line_unit" type="QString" value="MM"/>
<Option name="offset_map_unit_scale" type="QString" value="3x:0,0,0,0,0,0"/>
<Option name="offset_unit" type="QString" value="Pixel"/>
<Option name="place_on_every_part" type="bool" value="true"/>
<Option name="placements" type="QString" value="Interval"/>
<Option name="ring_filter" type="QString" value="1"/>
<Option name="rotate" type="QString" value="1"/>
</Option>
<data_defined_properties>
<Option type="Map">
<Option name="name" type="QString" value=""/>
<Option name="properties"/>
<Option name="type" type="QString" value="collection"/>
</Option>
</data_defined_properties>
<symbol frame_rate="10" clip_to_extent="1" is_animated="0" name="@0@1" force_rhr="0" type="marker" alpha="1">
<data_defined_properties>
<Option type="Map">
<Option name="name" type="QString" value=""/>
<Option name="properties"/>
<Option name="type" type="QString" value="collection"/>
</Option>
</data_defined_properties>
<layer enabled="1" class="SimpleMarker" locked="0" id="{9e34c4c6-1165-4598-a42c-90fa8fc5ceb1}" pass="0">
<Option type="Map">
<Option name="angle" type="QString" value="90"/>
<Option name="cap_style" type="QString" value="square"/>
<Option name="color" type="QString" value="255,0,0,255,rgb:1,0,0,1"/>
<Option name="horizontal_anchor_point" type="QString" value="1"/>
<Option name="joinstyle" type="QString" value="bevel"/>
<Option name="name" type="QString" value="line"/>
<Option name="offset" type="QString" value="2,-1.5"/>
<Option name="offset_map_unit_scale" type="QString" value="3x:0,0,0,0,0,0"/>
<Option name="offset_unit" type="QString" value="MM"/>
<Option name="outline_color" type="QString" value="128,128,128,255,rgb:0.50196078431372548,0.50196078431372548,0.50196078431372548,1"/>
<Option name="outline_style" type="QString" value="solid"/>
<Option name="outline_width" type="QString" value="0.5"/>
<Option name="outline_width_map_unit_scale" type="QString" value="3x:0,0,0,0,0,0"/>
<Option name="outline_width_unit" type="QString" value="MM"/>
<Option name="scale_method" type="QString" value="diameter"/>
<Option name="size" type="QString" value="3"/>
<Option name="size_map_unit_scale" type="QString" value="3x:0,0,0,0,0,0"/>
<Option name="size_unit" type="QString" value="MM"/>
<Option name="vertical_anchor_point" type="QString" value="1"/>
</Option>
<data_defined_properties>
<Option type="Map">
<Option name="name" type="QString" value=""/>
<Option name="properties"/>
<Option name="type" type="QString" value="collection"/>
</Option>
</data_defined_properties>
</layer>
<layer enabled="1" class="SimpleMarker" locked="0" id="{740b060e-faa9-40ad-9cea-81c949fa1213}" pass="0">
<Option type="Map">
<Option name="angle" type="QString" value="0"/>
<Option name="cap_style" type="QString" value="square"/>
<Option name="color" type="QString" value="128,128,128,255,rgb:0.50196078431372548,0.50196078431372548,0.50196078431372548,1"/>
<Option name="horizontal_anchor_point" type="QString" value="1"/>
<Option name="joinstyle" type="QString" value="bevel"/>
<Option name="name" type="QString" value="line"/>
<Option name="offset" type="QString" value="3,1"/>
<Option name="offset_map_unit_scale" type="QString" value="3x:0,0,0,0,0,0"/>
<Option name="offset_unit" type="QString" value="MM"/>
<Option name="outline_color" type="QString" value="128,128,128,255,rgb:0.50196078431372548,0.50196078431372548,0.50196078431372548,1"/>
<Option name="outline_style" type="QString" value="solid"/>
<Option name="outline_width" type="QString" value="0.5"/>
<Option name="outline_width_map_unit_scale" type="QString" value="3x:0,0,0,0,0,0"/>
<Option name="outline_width_unit" type="QString" value="MM"/>
<Option name="scale_method" type="QString" value="diameter"/>
<Option name="size" type="QString" value="2"/>
<Option name="size_map_unit_scale" type="QString" value="3x:0,0,0,0,0,0"/>
<Option name="size_unit" type="QString" value="MM"/>
<Option name="vertical_anchor_point" type="QString" value="1"/>
</Option>
<data_defined_properties>
<Option type="Map">
<Option name="name" type="QString" value=""/>
<Option name="properties"/>
<Option name="type" type="QString" value="collection"/>
</Option>
</data_defined_properties>
</layer>
<layer enabled="1" class="SimpleMarker" locked="0" id="{ad3c4f89-aa14-4614-bf6a-1ce121763a53}" pass="0">
<Option type="Map">
<Option name="angle" type="QString" value="0"/>
<Option name="cap_style" type="QString" value="square"/>
<Option name="color" type="QString" value="255,0,0,255,rgb:1,0,0,1"/>
<Option name="horizontal_anchor_point" type="QString" value="1"/>
<Option name="joinstyle" type="QString" value="bevel"/>
<Option name="name" type="QString" value="line"/>
<Option name="offset" type="QString" value="2,1"/>
<Option name="offset_map_unit_scale" type="QString" value="3x:0,0,0,0,0,0"/>
<Option name="offset_unit" type="QString" value="MM"/>
<Option name="outline_color" type="QString" value="128,128,128,255,rgb:0.50196078431372548,0.50196078431372548,0.50196078431372548,1"/>
<Option name="outline_style" type="QString" value="solid"/>
<Option name="outline_width" type="QString" value="0.5"/>
<Option name="outline_width_map_unit_scale" type="QString" value="3x:0,0,0,0,0,0"/>
<Option name="outline_width_unit" type="QString" value="MM"/>
<Option name="scale_method" type="QString" value="diameter"/>
<Option name="size" type="QString" value="2"/>
<Option name="size_map_unit_scale" type="QString" value="3x:0,0,0,0,0,0"/>
<Option name="size_unit" type="QString" value="MM"/>
<Option name="vertical_anchor_point" type="QString" value="1"/>
</Option>
<data_defined_properties>
<Option type="Map">
<Option name="name" type="QString" value=""/>
<Option name="properties"/>
<Option name="type" type="QString" value="collection"/>
</Option>
</data_defined_properties>
</layer>
<layer enabled="1" class="SimpleMarker" locked="0" id="{19fe76ca-22b3-40fd-9177-9ac25a80499b}" pass="0">
<Option type="Map">
<Option name="angle" type="QString" value="0"/>
<Option name="cap_style" type="QString" value="square"/>
<Option name="color" type="QString" value="128,128,128,255,rgb:0.50196078431372548,0.50196078431372548,0.50196078431372548,1"/>
<Option name="horizontal_anchor_point" type="QString" value="1"/>
<Option name="joinstyle" type="QString" value="bevel"/>
<Option name="name" type="QString" value="line"/>
<Option name="offset" type="QString" value="1,1"/>
<Option name="offset_map_unit_scale" type="QString" value="3x:0,0,0,0,0,0"/>
<Option name="offset_unit" type="QString" value="MM"/>
<Option name="outline_color" type="QString" value="128,128,128,255,rgb:0.50196078431372548,0.50196078431372548,0.50196078431372548,1"/>
<Option name="outline_style" type="QString" value="solid"/>
<Option name="outline_width" type="QString" value="0.5"/>
<Option name="outline_width_map_unit_scale" type="QString" value="3x:0,0,0,0,0,0"/>
<Option name="outline_width_unit" type="QString" value="MM"/>
<Option name="scale_method" type="QString" value="diameter"/>
<Option name="size" type="QString" value="2"/>
<Option name="size_map_unit_scale" type="QString" value="3x:0,0,0,0,0,0"/>
<Option name="size_unit" type="QString" value="MM"/>
<Option name="vertical_anchor_point" type="QString" value="1"/>
</Option>
<data_defined_properties>
<Option type="Map">
<Option name="name" type="QString" value=""/>
<Option name="properties"/>
<Option name="type" type="QString" value="collection"/>
</Option>
</data_defined_properties>
</layer>
<layer enabled="1" class="SimpleMarker" locked="0" id="{cdfe941b-0a2d-450b-bcca-0901823247e1}" pass="0">
<Option type="Map">
<Option name="angle" type="QString" value="0"/>
<Option name="cap_style" type="QString" value="square"/>
<Option name="color" type="QString" value="128,128,128,255,rgb:0.50196078431372548,0.50196078431372548,0.50196078431372548,1"/>
<Option name="horizontal_anchor_point" type="QString" value="1"/>
<Option name="joinstyle" type="QString" value="bevel"/>
<Option name="name" type="QString" value="line"/>
<Option name="offset" type="QString" value="0,1"/>
<Option name="offset_map_unit_scale" type="QString" value="3x:0,0,0,0,0,0"/>
<Option name="offset_unit" type="QString" value="MM"/>
<Option name="outline_color" type="QString" value="128,128,128,255,rgb:0.50196078431372548,0.50196078431372548,0.50196078431372548,1"/>
<Option name="outline_style" type="QString" value="solid"/>
<Option name="outline_width" type="QString" value="0.5"/>
<Option name="outline_width_map_unit_scale" type="QString" value="3x:0,0,0,0,0,0"/>
<Option name="outline_width_unit" type="QString" value="MM"/>
<Option name="scale_method" type="QString" value="diameter"/>
<Option name="size" type="QString" value="2"/>
<Option name="size_map_unit_scale" type="QString" value="3x:0,0,0,0,0,0"/>
<Option name="size_unit" type="QString" value="MM"/>
<Option name="vertical_anchor_point" type="QString" value="1"/>
</Option>
<data_defined_properties>
<Option type="Map">
<Option name="name" type="QString" value=""/>
<Option name="properties"/>
<Option name="type" type="QString" value="collection"/>
</Option>
</data_defined_properties>
</layer>
</symbol>
</layer>
<layer enabled="1" class="SimpleLine" locked="0" id="{7ad934f6-f1ca-462a-8e99-2f3c035e1df4}" pass="0">
<Option type="Map">
<Option name="align_dash_pattern" type="QString" value="0"/>
<Option name="capstyle" type="QString" value="square"/>
<Option name="customdash" type="QString" value="5;2"/>
<Option name="customdash_map_unit_scale" type="QString" value="3x:0,0,0,0,0,0"/>
<Option name="customdash_unit" type="QString" value="MM"/>
<Option name="dash_pattern_offset" type="QString" value="0"/>
<Option name="dash_pattern_offset_map_unit_scale" type="QString" value="3x:0,0,0,0,0,0"/>
<Option name="dash_pattern_offset_unit" type="QString" value="MM"/>
<Option name="draw_inside_polygon" type="QString" value="0"/>
<Option name="joinstyle" type="QString" value="bevel"/>
<Option name="line_color" type="QString" value="128,128,128,255,rgb:0.50196078431372548,0.50196078431372548,0.50196078431372548,1"/>
<Option name="line_style" type="QString" value="solid"/>
<Option name="line_width" type="QString" value="0.5"/>
<Option name="line_width_unit" type="QString" value="MM"/>
<Option name="offset" type="QString" value="0"/>
<Option name="offset_map_unit_scale" type="QString" value="3x:0,0,0,0,0,0"/>
<Option name="offset_unit" type="QString" value="MM"/>
<Option name="ring_filter" type="QString" value="0"/>
<Option name="trim_distance_end" type="QString" value="0"/>
<Option name="trim_distance_end_map_unit_scale" type="QString" value="3x:0,0,0,0,0,0"/>
<Option name="trim_distance_end_unit" type="QString" value="MM"/>
<Option name="trim_distance_start" type="QString" value="0"/>
<Option name="trim_distance_start_map_unit_scale" type="QString" value="3x:0,0,0,0,0,0"/>
<Option name="trim_distance_start_unit" type="QString" value="MM"/>
<Option name="tweak_dash_pattern_on_corners" type="QString" value="0"/>
<Option name="use_custom_dash" type="QString" value="0"/>
<Option name="width_map_unit_scale" type="QString" value="3x:0,0,0,0,0,0"/>
</Option>
<data_defined_properties>
<Option type="Map">
<Option name="name" type="QString" value=""/>
<Option name="properties"/>
<Option name="type" type="QString" value="collection"/>
</Option>
</data_defined_properties>
</layer>
</symbol>
</symbols>
<rotation/>
<sizescale/>
<data-defined-properties>
<Option type="Map">
<Option name="name" type="QString" value=""/>
<Option name="properties"/>
<Option name="type" type="QString" value="collection"/>
</Option>
</data-defined-properties>
</renderer-v2>
<selection mode="Default">
<selectionColor invalid="1"/>
<selectionSymbol>
<symbol frame_rate="10" clip_to_extent="1" is_animated="0" name="" force_rhr="0" type="fill" alpha="1">
<data_defined_properties>
<Option type="Map">
<Option name="name" type="QString" value=""/>
<Option name="properties"/>
<Option name="type" type="QString" value="collection"/>
</Option>
</data_defined_properties>
<layer enabled="1" class="SimpleFill" locked="0" id="{9e97a033-5092-4073-b71d-2367914e7397}" pass="0">
<Option type="Map">
<Option name="border_width_map_unit_scale" type="QString" value="3x:0,0,0,0,0,0"/>
<Option name="color" type="QString" value="0,0,255,255,rgb:0,0,1,1"/>
<Option name="joinstyle" type="QString" value="bevel"/>
<Option name="offset" type="QString" value="0,0"/>
<Option name="offset_map_unit_scale" type="QString" value="3x:0,0,0,0,0,0"/>
<Option name="offset_unit" type="QString" value="MM"/>
<Option name="outline_color" type="QString" value="35,35,35,255,rgb:0.13725490196078433,0.13725490196078433,0.13725490196078433,1"/>
<Option name="outline_style" type="QString" value="solid"/>
<Option name="outline_width" type="QString" value="0.26"/>
<Option name="outline_width_unit" type="QString" value="MM"/>
<Option name="style" type="QString" value="solid"/>
</Option>
<data_defined_properties>
<Option type="Map">
<Option name="name" type="QString" value=""/>
<Option name="properties"/>
<Option name="type" type="QString" value="collection"/>
</Option>
</data_defined_properties>
</layer>
</symbol>
</selectionSymbol>
</selection>
<customproperties>
<Option type="Map">
<Option name="embeddedWidgets/count" type="int" value="0"/>
<Option name="variableNames"/>
<Option name="variableValues"/>
</Option>
</customproperties>
<blendMode>0</blendMode>
<featureBlendMode>0</featureBlendMode>
<layerOpacity>1</layerOpacity>
<geometryOptions geometryPrecision="0" removeDuplicateNodes="0">
<activeChecks/>
<checkConfiguration type="Map">
<Option name="QgsGeometryGapCheck" type="Map">
<Option name="allowedGapsBuffer" type="double" value="0"/>
<Option name="allowedGapsEnabled" type="bool" value="false"/>
<Option name="allowedGapsLayer" type="QString" value=""/>
</Option>
</checkConfiguration>
</geometryOptions>
<legend showLabelLegend="0" type="default-vector"/>
<referencedLayers/>
<fieldConfiguration>
<field name="OBJECTID" configurationFlags="NoFlag">
<editWidget type="TextEdit">
<config>
<Option/>
</config>
</editWidget>
</field>
<field name="KATEGORIE" configurationFlags="NoFlag">
<editWidget type="TextEdit">
<config>
<Option/>
</config>
</editWidget>
</field>
<field name="STATUS" configurationFlags="NoFlag">
<editWidget type="TextEdit">
<config>
<Option/>
</config>
</editWidget>
</field>
<field name="SG_NR" configurationFlags="NoFlag">
<editWidget type="TextEdit">
<config>
<Option/>
</config>
</editWidget>
</field>
<field name="NAME" configurationFlags="NoFlag">
<editWidget type="TextEdit">
<config>
<Option/>
</config>
</editWidget>
</field>
<field name="FLAECHE" configurationFlags="NoFlag">
<editWidget type="TextEdit">
<config>
<Option/>
</config>
</editWidget>
</field>
<field name="UMFANG" configurationFlags="NoFlag">
<editWidget type="TextEdit">
<config>
<Option/>
</config>
</editWidget>
</field>
<field name="RVO_DATUM" configurationFlags="NoFlag">
<editWidget type="TextEdit">
<config>
<Option/>
</config>
</editWidget>
</field>
<field name="RVO_1" configurationFlags="NoFlag">
<editWidget type="TextEdit">
<config>
<Option/>
</config>
</editWidget>
</field>
<field name="RVO_2" configurationFlags="NoFlag">
<editWidget type="TextEdit">
<config>
<Option/>
</config>
</editWidget>
</field>
<field name="PRAEZI" configurationFlags="NoFlag">
<editWidget type="TextEdit">
<config>
<Option/>
</config>
</editWidget>
</field>
<field name="ERFDAT" configurationFlags="NoFlag">
<editWidget type="TextEdit">
<config>
<Option/>
</config>
</editWidget>
</field>
<field name="UEBDAT" configurationFlags="NoFlag">
<editWidget type="TextEdit">
<config>
<Option/>
</config>
</editWidget>
</field>
<field name="Shape__Area" configurationFlags="NoFlag">
<editWidget type="TextEdit">
<config>
<Option/>
</config>
</editWidget>
</field>
<field name="Shape__Length" configurationFlags="NoFlag">
<editWidget type="TextEdit">
<config>
<Option/>
</config>
</editWidget>
</field>
<field name="SE_ANNO_CAD_DATA" configurationFlags="NoFlag">
<editWidget type="Binary">
<config>
<Option/>
</config>
</editWidget>
</field>
</fieldConfiguration>
<aliases>
<alias index="0" name="" field="OBJECTID"/>
<alias index="1" name="" field="KATEGORIE"/>
<alias index="2" name="" field="STATUS"/>
<alias index="3" name="" field="SG_NR"/>
<alias index="4" name="" field="NAME"/>
<alias index="5" name="" field="FLAECHE"/>
<alias index="6" name="" field="UMFANG"/>
<alias index="7" name="" field="RVO_DATUM"/>
<alias index="8" name="" field="RVO_1"/>
<alias index="9" name="" field="RVO_2"/>
<alias index="10" name="" field="PRAEZI"/>
<alias index="11" name="" field="ERFDAT"/>
<alias index="12" name="" field="UEBDAT"/>
<alias index="13" name="SHAPE.AREA" field="Shape__Area"/>
<alias index="14" name="SHAPE.LEN" field="Shape__Length"/>
<alias index="15" name="" field="SE_ANNO_CAD_DATA"/>
</aliases>
<splitPolicies>
<policy policy="Duplicate" field="OBJECTID"/>
<policy policy="Duplicate" field="KATEGORIE"/>
<policy policy="Duplicate" field="STATUS"/>
<policy policy="Duplicate" field="SG_NR"/>
<policy policy="Duplicate" field="NAME"/>
<policy policy="Duplicate" field="FLAECHE"/>
<policy policy="Duplicate" field="UMFANG"/>
<policy policy="Duplicate" field="RVO_DATUM"/>
<policy policy="Duplicate" field="RVO_1"/>
<policy policy="Duplicate" field="RVO_2"/>
<policy policy="Duplicate" field="PRAEZI"/>
<policy policy="Duplicate" field="ERFDAT"/>
<policy policy="Duplicate" field="UEBDAT"/>
<policy policy="Duplicate" field="Shape__Area"/>
<policy policy="Duplicate" field="Shape__Length"/>
<policy policy="Duplicate" field="SE_ANNO_CAD_DATA"/>
</splitPolicies>
<duplicatePolicies>
<policy policy="Duplicate" field="OBJECTID"/>
<policy policy="Duplicate" field="KATEGORIE"/>
<policy policy="Duplicate" field="STATUS"/>
<policy policy="Duplicate" field="SG_NR"/>
<policy policy="Duplicate" field="NAME"/>
<policy policy="Duplicate" field="FLAECHE"/>
<policy policy="Duplicate" field="UMFANG"/>
<policy policy="Duplicate" field="RVO_DATUM"/>
<policy policy="Duplicate" field="RVO_1"/>
<policy policy="Duplicate" field="RVO_2"/>
<policy policy="Duplicate" field="PRAEZI"/>
<policy policy="Duplicate" field="ERFDAT"/>
<policy policy="Duplicate" field="UEBDAT"/>
<policy policy="Duplicate" field="Shape__Area"/>
<policy policy="Duplicate" field="Shape__Length"/>
<policy policy="Duplicate" field="SE_ANNO_CAD_DATA"/>
</duplicatePolicies>
<defaults>
<default field="OBJECTID" expression="" applyOnUpdate="0"/>
<default field="KATEGORIE" expression="" applyOnUpdate="0"/>
<default field="STATUS" expression="" applyOnUpdate="0"/>
<default field="SG_NR" expression="" applyOnUpdate="0"/>
<default field="NAME" expression="" applyOnUpdate="0"/>
<default field="FLAECHE" expression="" applyOnUpdate="0"/>
<default field="UMFANG" expression="" applyOnUpdate="0"/>
<default field="RVO_DATUM" expression="" applyOnUpdate="0"/>
<default field="RVO_1" expression="" applyOnUpdate="0"/>
<default field="RVO_2" expression="" applyOnUpdate="0"/>
<default field="PRAEZI" expression="" applyOnUpdate="0"/>
<default field="ERFDAT" expression="" applyOnUpdate="0"/>
<default field="UEBDAT" expression="" applyOnUpdate="0"/>
<default field="Shape__Area" expression="" applyOnUpdate="0"/>
<default field="Shape__Length" expression="" applyOnUpdate="0"/>
<default field="SE_ANNO_CAD_DATA" expression="" applyOnUpdate="0"/>
</defaults>
<constraints>
<constraint constraints="3" unique_strength="1" exp_strength="0" notnull_strength="1" field="OBJECTID"/>
<constraint constraints="0" unique_strength="0" exp_strength="0" notnull_strength="0" field="KATEGORIE"/>
<constraint constraints="0" unique_strength="0" exp_strength="0" notnull_strength="0" field="STATUS"/>
<constraint constraints="0" unique_strength="0" exp_strength="0" notnull_strength="0" field="SG_NR"/>
<constraint constraints="0" unique_strength="0" exp_strength="0" notnull_strength="0" field="NAME"/>
<constraint constraints="0" unique_strength="0" exp_strength="0" notnull_strength="0" field="FLAECHE"/>
<constraint constraints="0" unique_strength="0" exp_strength="0" notnull_strength="0" field="UMFANG"/>
<constraint constraints="0" unique_strength="0" exp_strength="0" notnull_strength="0" field="RVO_DATUM"/>
<constraint constraints="0" unique_strength="0" exp_strength="0" notnull_strength="0" field="RVO_1"/>
<constraint constraints="0" unique_strength="0" exp_strength="0" notnull_strength="0" field="RVO_2"/>
<constraint constraints="0" unique_strength="0" exp_strength="0" notnull_strength="0" field="PRAEZI"/>
<constraint constraints="0" unique_strength="0" exp_strength="0" notnull_strength="0" field="ERFDAT"/>
<constraint constraints="0" unique_strength="0" exp_strength="0" notnull_strength="0" field="UEBDAT"/>
<constraint constraints="0" unique_strength="0" exp_strength="0" notnull_strength="0" field="Shape__Area"/>
<constraint constraints="0" unique_strength="0" exp_strength="0" notnull_strength="0" field="Shape__Length"/>
<constraint constraints="0" unique_strength="0" exp_strength="0" notnull_strength="0" field="SE_ANNO_CAD_DATA"/>
</constraints>
<constraintExpressions>
<constraint desc="" exp="" field="OBJECTID"/>
<constraint desc="" exp="" field="KATEGORIE"/>
<constraint desc="" exp="" field="STATUS"/>
<constraint desc="" exp="" field="SG_NR"/>
<constraint desc="" exp="" field="NAME"/>
<constraint desc="" exp="" field="FLAECHE"/>
<constraint desc="" exp="" field="UMFANG"/>
<constraint desc="" exp="" field="RVO_DATUM"/>
<constraint desc="" exp="" field="RVO_1"/>
<constraint desc="" exp="" field="RVO_2"/>
<constraint desc="" exp="" field="PRAEZI"/>
<constraint desc="" exp="" field="ERFDAT"/>
<constraint desc="" exp="" field="UEBDAT"/>
<constraint desc="" exp="" field="Shape__Area"/>
<constraint desc="" exp="" field="Shape__Length"/>
<constraint desc="" exp="" field="SE_ANNO_CAD_DATA"/>
</constraintExpressions>
<expressionfields/>
<attributeactions>
<defaultAction value="{00000000-0000-0000-0000-000000000000}" key="Canvas"/>
</attributeactions>
<attributetableconfig sortOrder="0" actionWidgetStyle="dropDown" sortExpression="">
<columns>
<column name="OBJECTID" width="-1" type="field" hidden="0"/>
<column name="KATEGORIE" width="-1" type="field" hidden="0"/>
<column name="STATUS" width="-1" type="field" hidden="0"/>
<column name="SG_NR" width="-1" type="field" hidden="0"/>
<column name="NAME" width="-1" type="field" hidden="0"/>
<column name="FLAECHE" width="-1" type="field" hidden="0"/>
<column name="UMFANG" width="-1" type="field" hidden="0"/>
<column name="RVO_DATUM" width="-1" type="field" hidden="0"/>
<column name="RVO_1" width="-1" type="field" hidden="0"/>
<column name="RVO_2" width="-1" type="field" hidden="0"/>
<column name="PRAEZI" width="-1" type="field" hidden="0"/>
<column name="ERFDAT" width="-1" type="field" hidden="0"/>
<column name="UEBDAT" width="-1" type="field" hidden="0"/>
<column name="Shape__Area" width="-1" type="field" hidden="0"/>
<column name="Shape__Length" width="-1" type="field" hidden="0"/>
<column name="SE_ANNO_CAD_DATA" width="-1" type="field" hidden="0"/>
<column width="-1" type="actions" hidden="1"/>
</columns>
</attributetableconfig>
<conditionalstyles>
<rowstyles/>
<fieldstyles/>
</conditionalstyles>
<storedexpressions/>
<editform tolerant="1"></editform>
<editforminit/>
<editforminitcodesource>0</editforminitcodesource>
<editforminitfilepath></editforminitfilepath>
<editforminitcode><![CDATA[# -*- coding: utf-8 -*-
"""
QGIS-Formulare können eine Python-Funktion haben,, die aufgerufen wird, wenn sich das Formular öffnet
Diese Funktion kann verwendet werden um dem Formular Extralogik hinzuzufügen.
Der Name der Funktion wird im Feld "Python Init-Function" angegeben
Ein Beispiel folgt:
"""
from qgis.PyQt.QtWidgets import QWidget
def my_form_open(dialog, layer, feature):
geom = feature.geometry()
control = dialog.findChild(QWidget, "MyLineEdit")
]]></editforminitcode>
<featformsuppress>0</featformsuppress>
<editorlayout>generatedlayout</editorlayout>
<editable>
<field name="ERFDAT" editable="1"/>
<field name="FLAECHE" editable="1"/>
<field name="KATEGORIE" editable="1"/>
<field name="NAME" editable="1"/>
<field name="OBJECTID" editable="0"/>
<field name="PRAEZI" editable="1"/>
<field name="RVO_1" editable="1"/>
<field name="RVO_2" editable="1"/>
<field name="RVO_DATUM" editable="1"/>
<field name="SE_ANNO_CAD_DATA" editable="1"/>
<field name="SG_NR" editable="1"/>
<field name="STATUS" editable="1"/>
<field name="Shape__Area" editable="0"/>
<field name="Shape__Length" editable="0"/>
<field name="UEBDAT" editable="1"/>
<field name="UMFANG" editable="1"/>
</editable>
<labelOnTop>
<field name="ERFDAT" labelOnTop="0"/>
<field name="FLAECHE" labelOnTop="0"/>
<field name="KATEGORIE" labelOnTop="0"/>
<field name="NAME" labelOnTop="0"/>
<field name="OBJECTID" labelOnTop="0"/>
<field name="PRAEZI" labelOnTop="0"/>
<field name="RVO_1" labelOnTop="0"/>
<field name="RVO_2" labelOnTop="0"/>
<field name="RVO_DATUM" labelOnTop="0"/>
<field name="SE_ANNO_CAD_DATA" labelOnTop="0"/>
<field name="SG_NR" labelOnTop="0"/>
<field name="STATUS" labelOnTop="0"/>
<field name="Shape__Area" labelOnTop="0"/>
<field name="Shape__Length" labelOnTop="0"/>
<field name="UEBDAT" labelOnTop="0"/>
<field name="UMFANG" labelOnTop="0"/>
</labelOnTop>
<reuseLastValue>
<field name="ERFDAT" reuseLastValue="0"/>
<field name="FLAECHE" reuseLastValue="0"/>
<field name="KATEGORIE" reuseLastValue="0"/>
<field name="NAME" reuseLastValue="0"/>
<field name="OBJECTID" reuseLastValue="0"/>
<field name="PRAEZI" reuseLastValue="0"/>
<field name="RVO_1" reuseLastValue="0"/>
<field name="RVO_2" reuseLastValue="0"/>
<field name="RVO_DATUM" reuseLastValue="0"/>
<field name="SE_ANNO_CAD_DATA" reuseLastValue="0"/>
<field name="SG_NR" reuseLastValue="0"/>
<field name="STATUS" reuseLastValue="0"/>
<field name="Shape__Area" reuseLastValue="0"/>
<field name="Shape__Length" reuseLastValue="0"/>
<field name="UEBDAT" reuseLastValue="0"/>
<field name="UMFANG" reuseLastValue="0"/>
</reuseLastValue>
<dataDefinedFieldProperties/>
<widgets/>
<previewExpression>"NAME"</previewExpression>
<mapTip enabled="1"></mapTip>
<layerGeometryType>2</layerGeometryType>
</qgis>
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+871
View File
@@ -0,0 +1,871 @@
<!DOCTYPE qgis PUBLIC 'http://mrcc.com/qgis.dtd' 'SYSTEM'>
<qgis maxScale="0" simplifyDrawingHints="1" simplifyMaxScale="1" simplifyLocal="1" styleCategories="AllStyleCategories" labelsEnabled="0" simplifyAlgorithm="0" minScale="100000000" version="3.40.7-Bratislava" symbologyReferenceScale="-1" hasScaleBasedVisibilityFlag="0" autoRefreshMode="Disabled" readOnly="0" autoRefreshTime="0" simplifyDrawingTol="1">
<flags>
<Identifiable>1</Identifiable>
<Removable>1</Removable>
<Searchable>1</Searchable>
<Private>0</Private>
</flags>
<temporal endExpression="" durationField="HFV_FLAECHE_RES" enabled="0" mode="0" fixedDuration="0" startField="HFV_DAT_ERF" accumulate="0" limitMode="0" endField="" durationUnit="min" startExpression="">
<fixedRange>
<start></start>
<end></end>
</fixedRange>
</temporal>
<elevation respectLayerSymbol="1" zscale="1" extrusionEnabled="0" extrusion="0" type="IndividualFeatures" clamping="Terrain" symbology="Line" binding="Centroid" showMarkerSymbolInSurfacePlots="0" zoffset="0">
<data-defined-properties>
<Option type="Map">
<Option name="name" type="QString" value=""/>
<Option name="properties"/>
<Option name="type" type="QString" value="collection"/>
</Option>
</data-defined-properties>
<profileLineSymbol>
<symbol frame_rate="10" clip_to_extent="1" is_animated="0" name="" force_rhr="0" type="line" alpha="1">
<data_defined_properties>
<Option type="Map">
<Option name="name" type="QString" value=""/>
<Option name="properties"/>
<Option name="type" type="QString" value="collection"/>
</Option>
</data_defined_properties>
<layer enabled="1" class="SimpleLine" locked="0" id="{e5f07881-cf7e-4b94-83db-53938f3f7ae2}" pass="0">
<Option type="Map">
<Option name="align_dash_pattern" type="QString" value="0"/>
<Option name="capstyle" type="QString" value="square"/>
<Option name="customdash" type="QString" value="5;2"/>
<Option name="customdash_map_unit_scale" type="QString" value="3x:0,0,0,0,0,0"/>
<Option name="customdash_unit" type="QString" value="MM"/>
<Option name="dash_pattern_offset" type="QString" value="0"/>
<Option name="dash_pattern_offset_map_unit_scale" type="QString" value="3x:0,0,0,0,0,0"/>
<Option name="dash_pattern_offset_unit" type="QString" value="MM"/>
<Option name="draw_inside_polygon" type="QString" value="0"/>
<Option name="joinstyle" type="QString" value="bevel"/>
<Option name="line_color" type="QString" value="114,155,111,255,rgb:0.44705882352941179,0.60784313725490191,0.43529411764705883,1"/>
<Option name="line_style" type="QString" value="solid"/>
<Option name="line_width" type="QString" value="0.6"/>
<Option name="line_width_unit" type="QString" value="MM"/>
<Option name="offset" type="QString" value="0"/>
<Option name="offset_map_unit_scale" type="QString" value="3x:0,0,0,0,0,0"/>
<Option name="offset_unit" type="QString" value="MM"/>
<Option name="ring_filter" type="QString" value="0"/>
<Option name="trim_distance_end" type="QString" value="0"/>
<Option name="trim_distance_end_map_unit_scale" type="QString" value="3x:0,0,0,0,0,0"/>
<Option name="trim_distance_end_unit" type="QString" value="MM"/>
<Option name="trim_distance_start" type="QString" value="0"/>
<Option name="trim_distance_start_map_unit_scale" type="QString" value="3x:0,0,0,0,0,0"/>
<Option name="trim_distance_start_unit" type="QString" value="MM"/>
<Option name="tweak_dash_pattern_on_corners" type="QString" value="0"/>
<Option name="use_custom_dash" type="QString" value="0"/>
<Option name="width_map_unit_scale" type="QString" value="3x:0,0,0,0,0,0"/>
</Option>
<data_defined_properties>
<Option type="Map">
<Option name="name" type="QString" value=""/>
<Option name="properties"/>
<Option name="type" type="QString" value="collection"/>
</Option>
</data_defined_properties>
</layer>
</symbol>
</profileLineSymbol>
<profileFillSymbol>
<symbol frame_rate="10" clip_to_extent="1" is_animated="0" name="" force_rhr="0" type="fill" alpha="1">
<data_defined_properties>
<Option type="Map">
<Option name="name" type="QString" value=""/>
<Option name="properties"/>
<Option name="type" type="QString" value="collection"/>
</Option>
</data_defined_properties>
<layer enabled="1" class="SimpleFill" locked="0" id="{67b96080-159c-481a-beb8-fd549559befd}" pass="0">
<Option type="Map">
<Option name="border_width_map_unit_scale" type="QString" value="3x:0,0,0,0,0,0"/>
<Option name="color" type="QString" value="114,155,111,255,rgb:0.44705882352941179,0.60784313725490191,0.43529411764705883,1"/>
<Option name="joinstyle" type="QString" value="bevel"/>
<Option name="offset" type="QString" value="0,0"/>
<Option name="offset_map_unit_scale" type="QString" value="3x:0,0,0,0,0,0"/>
<Option name="offset_unit" type="QString" value="MM"/>
<Option name="outline_color" type="QString" value="81,111,79,255,rgb:0.31932555123216599,0.4341649500267033,0.3109178301670863,1"/>
<Option name="outline_style" type="QString" value="solid"/>
<Option name="outline_width" type="QString" value="0.2"/>
<Option name="outline_width_unit" type="QString" value="MM"/>
<Option name="style" type="QString" value="solid"/>
</Option>
<data_defined_properties>
<Option type="Map">
<Option name="name" type="QString" value=""/>
<Option name="properties"/>
<Option name="type" type="QString" value="collection"/>
</Option>
</data_defined_properties>
</layer>
</symbol>
</profileFillSymbol>
<profileMarkerSymbol>
<symbol frame_rate="10" clip_to_extent="1" is_animated="0" name="" force_rhr="0" type="marker" alpha="1">
<data_defined_properties>
<Option type="Map">
<Option name="name" type="QString" value=""/>
<Option name="properties"/>
<Option name="type" type="QString" value="collection"/>
</Option>
</data_defined_properties>
<layer enabled="1" class="SimpleMarker" locked="0" id="{73b16b15-abe7-4a92-802d-ee527e2ef844}" pass="0">
<Option type="Map">
<Option name="angle" type="QString" value="0"/>
<Option name="cap_style" type="QString" value="square"/>
<Option name="color" type="QString" value="114,155,111,255,rgb:0.44705882352941179,0.60784313725490191,0.43529411764705883,1"/>
<Option name="horizontal_anchor_point" type="QString" value="1"/>
<Option name="joinstyle" type="QString" value="bevel"/>
<Option name="name" type="QString" value="diamond"/>
<Option name="offset" type="QString" value="0,0"/>
<Option name="offset_map_unit_scale" type="QString" value="3x:0,0,0,0,0,0"/>
<Option name="offset_unit" type="QString" value="MM"/>
<Option name="outline_color" type="QString" value="81,111,79,255,rgb:0.31932555123216599,0.4341649500267033,0.3109178301670863,1"/>
<Option name="outline_style" type="QString" value="solid"/>
<Option name="outline_width" type="QString" value="0.2"/>
<Option name="outline_width_map_unit_scale" type="QString" value="3x:0,0,0,0,0,0"/>
<Option name="outline_width_unit" type="QString" value="MM"/>
<Option name="scale_method" type="QString" value="diameter"/>
<Option name="size" type="QString" value="3"/>
<Option name="size_map_unit_scale" type="QString" value="3x:0,0,0,0,0,0"/>
<Option name="size_unit" type="QString" value="MM"/>
<Option name="vertical_anchor_point" type="QString" value="1"/>
</Option>
<data_defined_properties>
<Option type="Map">
<Option name="name" type="QString" value=""/>
<Option name="properties"/>
<Option name="type" type="QString" value="collection"/>
</Option>
</data_defined_properties>
</layer>
</symbol>
</profileMarkerSymbol>
</elevation>
<renderer-v2 forceraster="0" type="categorizedSymbol" enableorderby="0" referencescale="-1" attr="HBTP_BEZ" symbollevels="0">
<categories>
<category render="true" uuid="{6f28b785-1b9e-4468-b474-2f1743c40d73}" type="string" label="Brutbaum (Brutbaumkomplex)" value="Brutbaum (Brutbaumkomplex)" symbol="0"/>
<category render="true" uuid="{fd48cc7e-3a90-4576-8e5a-8262bbb27cd2}" type="string" label="Reproduktionshabitat" value="Reproduktionshabitat" symbol="1"/>
<category render="true" uuid="{53a85327-7622-4312-84f5-36f881aced7e}" type="NULL" label="" value="NULL" symbol="2"/>
</categories>
<symbols>
<symbol frame_rate="10" clip_to_extent="1" is_animated="0" name="0" force_rhr="0" type="fill" alpha="1">
<data_defined_properties>
<Option type="Map">
<Option name="name" type="QString" value=""/>
<Option name="properties"/>
<Option name="type" type="QString" value="collection"/>
</Option>
</data_defined_properties>
<layer enabled="1" class="SimpleFill" locked="0" id="{68961825-6501-4e47-9f29-94d9091d2f36}" pass="0">
<Option type="Map">
<Option name="border_width_map_unit_scale" type="QString" value="3x:0,0,0,0,0,0"/>
<Option name="color" type="QString" value="0,170,0,255,rgb:0,0.66666666666666663,0,1"/>
<Option name="joinstyle" type="QString" value="bevel"/>
<Option name="offset" type="QString" value="0,0"/>
<Option name="offset_map_unit_scale" type="QString" value="3x:0,0,0,0,0,0"/>
<Option name="offset_unit" type="QString" value="MM"/>
<Option name="outline_color" type="QString" value="35,35,35,255,rgb:0.13725490196078433,0.13725490196078433,0.13725490196078433,1"/>
<Option name="outline_style" type="QString" value="solid"/>
<Option name="outline_width" type="QString" value="0.26"/>
<Option name="outline_width_unit" type="QString" value="MM"/>
<Option name="style" type="QString" value="solid"/>
</Option>
<data_defined_properties>
<Option type="Map">
<Option name="name" type="QString" value=""/>
<Option name="properties"/>
<Option name="type" type="QString" value="collection"/>
</Option>
</data_defined_properties>
</layer>
</symbol>
<symbol frame_rate="10" clip_to_extent="1" is_animated="0" name="1" force_rhr="0" type="fill" alpha="1">
<data_defined_properties>
<Option type="Map">
<Option name="name" type="QString" value=""/>
<Option name="properties"/>
<Option name="type" type="QString" value="collection"/>
</Option>
</data_defined_properties>
<layer enabled="1" class="SimpleFill" locked="0" id="{a4195645-1010-4615-affb-26157b7fb07b}" pass="0">
<Option type="Map">
<Option name="border_width_map_unit_scale" type="QString" value="3x:0,0,0,0,0,0"/>
<Option name="color" type="QString" value="230,70,214,255,rgb:0.90196078431372551,0.27450980392156865,0.83921568627450982,1"/>
<Option name="joinstyle" type="QString" value="bevel"/>
<Option name="offset" type="QString" value="0,0"/>
<Option name="offset_map_unit_scale" type="QString" value="3x:0,0,0,0,0,0"/>
<Option name="offset_unit" type="QString" value="MM"/>
<Option name="outline_color" type="QString" value="35,35,35,255,rgb:0.13725490196078433,0.13725490196078433,0.13725490196078433,1"/>
<Option name="outline_style" type="QString" value="solid"/>
<Option name="outline_width" type="QString" value="0.26"/>
<Option name="outline_width_unit" type="QString" value="MM"/>
<Option name="style" type="QString" value="solid"/>
</Option>
<data_defined_properties>
<Option type="Map">
<Option name="name" type="QString" value=""/>
<Option name="properties"/>
<Option name="type" type="QString" value="collection"/>
</Option>
</data_defined_properties>
</layer>
</symbol>
<symbol frame_rate="10" clip_to_extent="1" is_animated="0" name="2" force_rhr="0" type="fill" alpha="1">
<data_defined_properties>
<Option type="Map">
<Option name="name" type="QString" value=""/>
<Option name="properties"/>
<Option name="type" type="QString" value="collection"/>
</Option>
</data_defined_properties>
<layer enabled="1" class="SimpleFill" locked="0" id="{b701f552-5171-4e40-a689-ab881a88384b}" pass="0">
<Option type="Map">
<Option name="border_width_map_unit_scale" type="QString" value="3x:0,0,0,0,0,0"/>
<Option name="color" type="QString" value="110,144,217,255,hsv:0.61388888888888893,0.49411764705882355,0.85098039215686272,1"/>
<Option name="joinstyle" type="QString" value="bevel"/>
<Option name="offset" type="QString" value="0,0"/>
<Option name="offset_map_unit_scale" type="QString" value="3x:0,0,0,0,0,0"/>
<Option name="offset_unit" type="QString" value="MM"/>
<Option name="outline_color" type="QString" value="35,35,35,255,rgb:0.13725490196078433,0.13725490196078433,0.13725490196078433,1"/>
<Option name="outline_style" type="QString" value="solid"/>
<Option name="outline_width" type="QString" value="0.26"/>
<Option name="outline_width_unit" type="QString" value="MM"/>
<Option name="style" type="QString" value="solid"/>
</Option>
<data_defined_properties>
<Option type="Map">
<Option name="name" type="QString" value=""/>
<Option name="properties"/>
<Option name="type" type="QString" value="collection"/>
</Option>
</data_defined_properties>
</layer>
</symbol>
</symbols>
<source-symbol>
<symbol frame_rate="10" clip_to_extent="1" is_animated="0" name="0" force_rhr="0" type="fill" alpha="1">
<data_defined_properties>
<Option type="Map">
<Option name="name" type="QString" value=""/>
<Option name="properties"/>
<Option name="type" type="QString" value="collection"/>
</Option>
</data_defined_properties>
<layer enabled="1" class="SimpleFill" locked="0" id="{08ef956c-cfc8-4429-be33-2c2aac3938c6}" pass="0">
<Option type="Map">
<Option name="border_width_map_unit_scale" type="QString" value="3x:0,0,0,0,0,0"/>
<Option name="color" type="QString" value="243,166,178,255,rgb:0.95294117647058818,0.65098039215686276,0.69803921568627447,1"/>
<Option name="joinstyle" type="QString" value="bevel"/>
<Option name="offset" type="QString" value="0,0"/>
<Option name="offset_map_unit_scale" type="QString" value="3x:0,0,0,0,0,0"/>
<Option name="offset_unit" type="QString" value="MM"/>
<Option name="outline_color" type="QString" value="35,35,35,255,rgb:0.13725490196078433,0.13725490196078433,0.13725490196078433,1"/>
<Option name="outline_style" type="QString" value="solid"/>
<Option name="outline_width" type="QString" value="0.26"/>
<Option name="outline_width_unit" type="QString" value="MM"/>
<Option name="style" type="QString" value="solid"/>
</Option>
<data_defined_properties>
<Option type="Map">
<Option name="name" type="QString" value=""/>
<Option name="properties"/>
<Option name="type" type="QString" value="collection"/>
</Option>
</data_defined_properties>
</layer>
</symbol>
</source-symbol>
<colorramp name="[source]" type="randomcolors">
<Option/>
</colorramp>
<rotation/>
<sizescale/>
<data-defined-properties>
<Option type="Map">
<Option name="name" type="QString" value=""/>
<Option name="properties"/>
<Option name="type" type="QString" value="collection"/>
</Option>
</data-defined-properties>
</renderer-v2>
<selection mode="Default">
<selectionColor invalid="1"/>
<selectionSymbol>
<symbol frame_rate="10" clip_to_extent="1" is_animated="0" name="" force_rhr="0" type="fill" alpha="1">
<data_defined_properties>
<Option type="Map">
<Option name="name" type="QString" value=""/>
<Option name="properties"/>
<Option name="type" type="QString" value="collection"/>
</Option>
</data_defined_properties>
<layer enabled="1" class="SimpleFill" locked="0" id="{54461271-fa73-4ec5-8323-72cc78b26ced}" pass="0">
<Option type="Map">
<Option name="border_width_map_unit_scale" type="QString" value="3x:0,0,0,0,0,0"/>
<Option name="color" type="QString" value="0,0,255,255,rgb:0,0,1,1"/>
<Option name="joinstyle" type="QString" value="bevel"/>
<Option name="offset" type="QString" value="0,0"/>
<Option name="offset_map_unit_scale" type="QString" value="3x:0,0,0,0,0,0"/>
<Option name="offset_unit" type="QString" value="MM"/>
<Option name="outline_color" type="QString" value="35,35,35,255,rgb:0.13725490196078433,0.13725490196078433,0.13725490196078433,1"/>
<Option name="outline_style" type="QString" value="solid"/>
<Option name="outline_width" type="QString" value="0.26"/>
<Option name="outline_width_unit" type="QString" value="MM"/>
<Option name="style" type="QString" value="solid"/>
</Option>
<data_defined_properties>
<Option type="Map">
<Option name="name" type="QString" value=""/>
<Option name="properties"/>
<Option name="type" type="QString" value="collection"/>
</Option>
</data_defined_properties>
</layer>
</symbol>
</selectionSymbol>
</selection>
<customproperties>
<Option type="Map">
<Option name="embeddedWidgets/count" type="int" value="0"/>
<Option name="variableNames"/>
<Option name="variableValues"/>
</Option>
</customproperties>
<blendMode>0</blendMode>
<featureBlendMode>0</featureBlendMode>
<layerOpacity>1</layerOpacity>
<geometryOptions geometryPrecision="0" removeDuplicateNodes="0">
<activeChecks/>
<checkConfiguration type="Map">
<Option name="QgsGeometryGapCheck" type="Map">
<Option name="allowedGapsBuffer" type="double" value="0"/>
<Option name="allowedGapsEnabled" type="bool" value="false"/>
<Option name="allowedGapsLayer" type="QString" value=""/>
</Option>
</checkConfiguration>
</geometryOptions>
<legend showLabelLegend="0" type="default-vector"/>
<referencedLayers/>
<fieldConfiguration>
<field name="ART_DEUTSCH" configurationFlags="NoFlag">
<editWidget type="TextEdit">
<config>
<Option/>
</config>
</editWidget>
</field>
<field name="ART_WISSENSCHAFTL" configurationFlags="NoFlag">
<editWidget type="TextEdit">
<config>
<Option/>
</config>
</editWidget>
</field>
<field name="HBTP_BEZ" configurationFlags="NoFlag">
<editWidget type="TextEdit">
<config>
<Option/>
</config>
</editWidget>
</field>
<field name="HFV_DAT_ERF" configurationFlags="NoFlag">
<editWidget type="DateTime">
<config>
<Option/>
</config>
</editWidget>
</field>
<field name="HFV_FLAECHE_RES" configurationFlags="NoFlag">
<editWidget type="TextEdit">
<config>
<Option/>
</config>
</editWidget>
</field>
<field name="HFF_HABF_ID" configurationFlags="NoFlag">
<editWidget type="TextEdit">
<config>
<Option/>
</config>
</editWidget>
</field>
<field name="HFF_FLTYP" configurationFlags="NoFlag">
<editWidget type="TextEdit">
<config>
<Option/>
</config>
</editWidget>
</field>
<field name="GDF_NR_LAND" configurationFlags="NoFlag">
<editWidget type="TextEdit">
<config>
<Option/>
</config>
</editWidget>
</field>
<field name="GID_BEZ" configurationFlags="NoFlag">
<editWidget type="TextEdit">
<config>
<Option/>
</config>
</editWidget>
</field>
<field name="GTF_NR" configurationFlags="NoFlag">
<editWidget type="TextEdit">
<config>
<Option/>
</config>
</editWidget>
</field>
<field name="HFV_BEW_POP" configurationFlags="NoFlag">
<editWidget type="TextEdit">
<config>
<Option/>
</config>
</editWidget>
</field>
<field name="HFV_BEW_HAB" configurationFlags="NoFlag">
<editWidget type="TextEdit">
<config>
<Option/>
</config>
</editWidget>
</field>
<field name="HFV_BEW_BTR" configurationFlags="NoFlag">
<editWidget type="TextEdit">
<config>
<Option/>
</config>
</editWidget>
</field>
<field name="HFV_ZUS_ERH" configurationFlags="NoFlag">
<editWidget type="TextEdit">
<config>
<Option/>
</config>
</editWidget>
</field>
<field name="HFV_ABW_GA" configurationFlags="NoFlag">
<editWidget type="TextEdit">
<config>
<Option/>
</config>
</editWidget>
</field>
<field name="HFV_BEM_ZUS_ERH" configurationFlags="NoFlag">
<editWidget type="TextEdit">
<config>
<Option/>
</config>
</editWidget>
</field>
<field name="LEGENDE" configurationFlags="NoFlag">
<editWidget type="Range">
<config>
<Option/>
</config>
</editWidget>
</field>
<field name="REPORT" configurationFlags="NoFlag">
<editWidget type="TextEdit">
<config>
<Option/>
</config>
</editWidget>
</field>
<field name="GDF_ID" configurationFlags="NoFlag">
<editWidget type="TextEdit">
<config>
<Option/>
</config>
</editWidget>
</field>
<field name="HFF_ID" configurationFlags="NoFlag">
<editWidget type="TextEdit">
<config>
<Option/>
</config>
</editWidget>
</field>
<field name="HTFF_ID" configurationFlags="NoFlag">
<editWidget type="TextEdit">
<config>
<Option/>
</config>
</editWidget>
</field>
<field name="HTFF_HABF_ID" configurationFlags="NoFlag">
<editWidget type="TextEdit">
<config>
<Option/>
</config>
</editWidget>
</field>
<field name="OBJECTID" configurationFlags="NoFlag">
<editWidget type="TextEdit">
<config>
<Option/>
</config>
</editWidget>
</field>
<field name="Shape__Area" configurationFlags="NoFlag">
<editWidget type="TextEdit">
<config>
<Option/>
</config>
</editWidget>
</field>
<field name="Shape__Length" configurationFlags="NoFlag">
<editWidget type="TextEdit">
<config>
<Option/>
</config>
</editWidget>
</field>
<field name="LEGENDE_2" configurationFlags="NoFlag">
<editWidget type="TextEdit">
<config>
<Option/>
</config>
</editWidget>
</field>
<field name="SE_ANNO_CAD_DATA" configurationFlags="NoFlag">
<editWidget type="Binary">
<config>
<Option/>
</config>
</editWidget>
</field>
</fieldConfiguration>
<aliases>
<alias index="0" name="Art dt" field="ART_DEUTSCH"/>
<alias index="1" name="Art wiss" field="ART_WISSENSCHAFTL"/>
<alias index="2" name="Habit_Typ" field="HBTP_BEZ"/>
<alias index="3" name="Datum Erf" field="HFV_DAT_ERF"/>
<alias index="4" name="Flaeche" field="HFV_FLAECHE_RES"/>
<alias index="5" name="Habit ID" field="HFF_HABF_ID"/>
<alias index="6" name="Flaechentyp" field="HFF_FLTYP"/>
<alias index="7" name="SN Nr Gebiet" field="GDF_NR_LAND"/>
<alias index="8" name="Name_Gebiet" field="GID_BEZ"/>
<alias index="9" name="Nr_Teilfl" field="GTF_NR"/>
<alias index="10" name="Bew Popula" field="HFV_BEW_POP"/>
<alias index="11" name="Bew Habitat" field="HFV_BEW_HAB"/>
<alias index="12" name="Bew Beeintr" field="HFV_BEW_BTR"/>
<alias index="13" name="EHZ" field="HFV_ZUS_ERH"/>
<alias index="14" name="Abw_EHZ" field="HFV_ABW_GA"/>
<alias index="15" name="Grund Abw" field="HFV_BEM_ZUS_ERH"/>
<alias index="16" name="Legende" field="LEGENDE"/>
<alias index="17" name="Report" field="REPORT"/>
<alias index="18" name="" field="GDF_ID"/>
<alias index="19" name="" field="HFF_ID"/>
<alias index="20" name="" field="HTFF_ID"/>
<alias index="21" name="Habit Tf ID" field="HTFF_HABF_ID"/>
<alias index="22" name="" field="OBJECTID"/>
<alias index="23" name="SHAPE.AREA" field="Shape__Area"/>
<alias index="24" name="SHAPE.LEN" field="Shape__Length"/>
<alias index="25" name="" field="LEGENDE_2"/>
<alias index="26" name="" field="SE_ANNO_CAD_DATA"/>
</aliases>
<splitPolicies>
<policy policy="Duplicate" field="ART_DEUTSCH"/>
<policy policy="Duplicate" field="ART_WISSENSCHAFTL"/>
<policy policy="Duplicate" field="HBTP_BEZ"/>
<policy policy="Duplicate" field="HFV_DAT_ERF"/>
<policy policy="Duplicate" field="HFV_FLAECHE_RES"/>
<policy policy="Duplicate" field="HFF_HABF_ID"/>
<policy policy="Duplicate" field="HFF_FLTYP"/>
<policy policy="Duplicate" field="GDF_NR_LAND"/>
<policy policy="Duplicate" field="GID_BEZ"/>
<policy policy="Duplicate" field="GTF_NR"/>
<policy policy="Duplicate" field="HFV_BEW_POP"/>
<policy policy="Duplicate" field="HFV_BEW_HAB"/>
<policy policy="Duplicate" field="HFV_BEW_BTR"/>
<policy policy="Duplicate" field="HFV_ZUS_ERH"/>
<policy policy="Duplicate" field="HFV_ABW_GA"/>
<policy policy="Duplicate" field="HFV_BEM_ZUS_ERH"/>
<policy policy="Duplicate" field="LEGENDE"/>
<policy policy="Duplicate" field="REPORT"/>
<policy policy="Duplicate" field="GDF_ID"/>
<policy policy="Duplicate" field="HFF_ID"/>
<policy policy="Duplicate" field="HTFF_ID"/>
<policy policy="Duplicate" field="HTFF_HABF_ID"/>
<policy policy="Duplicate" field="OBJECTID"/>
<policy policy="Duplicate" field="Shape__Area"/>
<policy policy="Duplicate" field="Shape__Length"/>
<policy policy="Duplicate" field="LEGENDE_2"/>
<policy policy="Duplicate" field="SE_ANNO_CAD_DATA"/>
</splitPolicies>
<duplicatePolicies>
<policy policy="Duplicate" field="ART_DEUTSCH"/>
<policy policy="Duplicate" field="ART_WISSENSCHAFTL"/>
<policy policy="Duplicate" field="HBTP_BEZ"/>
<policy policy="Duplicate" field="HFV_DAT_ERF"/>
<policy policy="Duplicate" field="HFV_FLAECHE_RES"/>
<policy policy="Duplicate" field="HFF_HABF_ID"/>
<policy policy="Duplicate" field="HFF_FLTYP"/>
<policy policy="Duplicate" field="GDF_NR_LAND"/>
<policy policy="Duplicate" field="GID_BEZ"/>
<policy policy="Duplicate" field="GTF_NR"/>
<policy policy="Duplicate" field="HFV_BEW_POP"/>
<policy policy="Duplicate" field="HFV_BEW_HAB"/>
<policy policy="Duplicate" field="HFV_BEW_BTR"/>
<policy policy="Duplicate" field="HFV_ZUS_ERH"/>
<policy policy="Duplicate" field="HFV_ABW_GA"/>
<policy policy="Duplicate" field="HFV_BEM_ZUS_ERH"/>
<policy policy="Duplicate" field="LEGENDE"/>
<policy policy="Duplicate" field="REPORT"/>
<policy policy="Duplicate" field="GDF_ID"/>
<policy policy="Duplicate" field="HFF_ID"/>
<policy policy="Duplicate" field="HTFF_ID"/>
<policy policy="Duplicate" field="HTFF_HABF_ID"/>
<policy policy="Duplicate" field="OBJECTID"/>
<policy policy="Duplicate" field="Shape__Area"/>
<policy policy="Duplicate" field="Shape__Length"/>
<policy policy="Duplicate" field="LEGENDE_2"/>
<policy policy="Duplicate" field="SE_ANNO_CAD_DATA"/>
</duplicatePolicies>
<defaults>
<default field="ART_DEUTSCH" expression="" applyOnUpdate="0"/>
<default field="ART_WISSENSCHAFTL" expression="" applyOnUpdate="0"/>
<default field="HBTP_BEZ" expression="" applyOnUpdate="0"/>
<default field="HFV_DAT_ERF" expression="" applyOnUpdate="0"/>
<default field="HFV_FLAECHE_RES" expression="" applyOnUpdate="0"/>
<default field="HFF_HABF_ID" expression="" applyOnUpdate="0"/>
<default field="HFF_FLTYP" expression="" applyOnUpdate="0"/>
<default field="GDF_NR_LAND" expression="" applyOnUpdate="0"/>
<default field="GID_BEZ" expression="" applyOnUpdate="0"/>
<default field="GTF_NR" expression="" applyOnUpdate="0"/>
<default field="HFV_BEW_POP" expression="" applyOnUpdate="0"/>
<default field="HFV_BEW_HAB" expression="" applyOnUpdate="0"/>
<default field="HFV_BEW_BTR" expression="" applyOnUpdate="0"/>
<default field="HFV_ZUS_ERH" expression="" applyOnUpdate="0"/>
<default field="HFV_ABW_GA" expression="" applyOnUpdate="0"/>
<default field="HFV_BEM_ZUS_ERH" expression="" applyOnUpdate="0"/>
<default field="LEGENDE" expression="" applyOnUpdate="0"/>
<default field="REPORT" expression="" applyOnUpdate="0"/>
<default field="GDF_ID" expression="" applyOnUpdate="0"/>
<default field="HFF_ID" expression="" applyOnUpdate="0"/>
<default field="HTFF_ID" expression="" applyOnUpdate="0"/>
<default field="HTFF_HABF_ID" expression="" applyOnUpdate="0"/>
<default field="OBJECTID" expression="" applyOnUpdate="0"/>
<default field="Shape__Area" expression="" applyOnUpdate="0"/>
<default field="Shape__Length" expression="" applyOnUpdate="0"/>
<default field="LEGENDE_2" expression="" applyOnUpdate="0"/>
<default field="SE_ANNO_CAD_DATA" expression="" applyOnUpdate="0"/>
</defaults>
<constraints>
<constraint constraints="0" unique_strength="0" exp_strength="0" notnull_strength="0" field="ART_DEUTSCH"/>
<constraint constraints="0" unique_strength="0" exp_strength="0" notnull_strength="0" field="ART_WISSENSCHAFTL"/>
<constraint constraints="0" unique_strength="0" exp_strength="0" notnull_strength="0" field="HBTP_BEZ"/>
<constraint constraints="0" unique_strength="0" exp_strength="0" notnull_strength="0" field="HFV_DAT_ERF"/>
<constraint constraints="0" unique_strength="0" exp_strength="0" notnull_strength="0" field="HFV_FLAECHE_RES"/>
<constraint constraints="0" unique_strength="0" exp_strength="0" notnull_strength="0" field="HFF_HABF_ID"/>
<constraint constraints="0" unique_strength="0" exp_strength="0" notnull_strength="0" field="HFF_FLTYP"/>
<constraint constraints="0" unique_strength="0" exp_strength="0" notnull_strength="0" field="GDF_NR_LAND"/>
<constraint constraints="0" unique_strength="0" exp_strength="0" notnull_strength="0" field="GID_BEZ"/>
<constraint constraints="0" unique_strength="0" exp_strength="0" notnull_strength="0" field="GTF_NR"/>
<constraint constraints="0" unique_strength="0" exp_strength="0" notnull_strength="0" field="HFV_BEW_POP"/>
<constraint constraints="0" unique_strength="0" exp_strength="0" notnull_strength="0" field="HFV_BEW_HAB"/>
<constraint constraints="0" unique_strength="0" exp_strength="0" notnull_strength="0" field="HFV_BEW_BTR"/>
<constraint constraints="0" unique_strength="0" exp_strength="0" notnull_strength="0" field="HFV_ZUS_ERH"/>
<constraint constraints="0" unique_strength="0" exp_strength="0" notnull_strength="0" field="HFV_ABW_GA"/>
<constraint constraints="0" unique_strength="0" exp_strength="0" notnull_strength="0" field="HFV_BEM_ZUS_ERH"/>
<constraint constraints="0" unique_strength="0" exp_strength="0" notnull_strength="0" field="LEGENDE"/>
<constraint constraints="0" unique_strength="0" exp_strength="0" notnull_strength="0" field="REPORT"/>
<constraint constraints="0" unique_strength="0" exp_strength="0" notnull_strength="0" field="GDF_ID"/>
<constraint constraints="0" unique_strength="0" exp_strength="0" notnull_strength="0" field="HFF_ID"/>
<constraint constraints="0" unique_strength="0" exp_strength="0" notnull_strength="0" field="HTFF_ID"/>
<constraint constraints="0" unique_strength="0" exp_strength="0" notnull_strength="0" field="HTFF_HABF_ID"/>
<constraint constraints="3" unique_strength="1" exp_strength="0" notnull_strength="1" field="OBJECTID"/>
<constraint constraints="0" unique_strength="0" exp_strength="0" notnull_strength="0" field="Shape__Area"/>
<constraint constraints="0" unique_strength="0" exp_strength="0" notnull_strength="0" field="Shape__Length"/>
<constraint constraints="0" unique_strength="0" exp_strength="0" notnull_strength="0" field="LEGENDE_2"/>
<constraint constraints="0" unique_strength="0" exp_strength="0" notnull_strength="0" field="SE_ANNO_CAD_DATA"/>
</constraints>
<constraintExpressions>
<constraint desc="" exp="" field="ART_DEUTSCH"/>
<constraint desc="" exp="" field="ART_WISSENSCHAFTL"/>
<constraint desc="" exp="" field="HBTP_BEZ"/>
<constraint desc="" exp="" field="HFV_DAT_ERF"/>
<constraint desc="" exp="" field="HFV_FLAECHE_RES"/>
<constraint desc="" exp="" field="HFF_HABF_ID"/>
<constraint desc="" exp="" field="HFF_FLTYP"/>
<constraint desc="" exp="" field="GDF_NR_LAND"/>
<constraint desc="" exp="" field="GID_BEZ"/>
<constraint desc="" exp="" field="GTF_NR"/>
<constraint desc="" exp="" field="HFV_BEW_POP"/>
<constraint desc="" exp="" field="HFV_BEW_HAB"/>
<constraint desc="" exp="" field="HFV_BEW_BTR"/>
<constraint desc="" exp="" field="HFV_ZUS_ERH"/>
<constraint desc="" exp="" field="HFV_ABW_GA"/>
<constraint desc="" exp="" field="HFV_BEM_ZUS_ERH"/>
<constraint desc="" exp="" field="LEGENDE"/>
<constraint desc="" exp="" field="REPORT"/>
<constraint desc="" exp="" field="GDF_ID"/>
<constraint desc="" exp="" field="HFF_ID"/>
<constraint desc="" exp="" field="HTFF_ID"/>
<constraint desc="" exp="" field="HTFF_HABF_ID"/>
<constraint desc="" exp="" field="OBJECTID"/>
<constraint desc="" exp="" field="Shape__Area"/>
<constraint desc="" exp="" field="Shape__Length"/>
<constraint desc="" exp="" field="LEGENDE_2"/>
<constraint desc="" exp="" field="SE_ANNO_CAD_DATA"/>
</constraintExpressions>
<expressionfields/>
<attributeactions>
<defaultAction value="{00000000-0000-0000-0000-000000000000}" key="Canvas"/>
</attributeactions>
<attributetableconfig sortOrder="0" actionWidgetStyle="dropDown" sortExpression="">
<columns>
<column name="ART_DEUTSCH" width="-1" type="field" hidden="0"/>
<column name="ART_WISSENSCHAFTL" width="-1" type="field" hidden="0"/>
<column name="HBTP_BEZ" width="-1" type="field" hidden="0"/>
<column name="HFV_DAT_ERF" width="-1" type="field" hidden="0"/>
<column name="HFV_FLAECHE_RES" width="-1" type="field" hidden="0"/>
<column name="HFF_HABF_ID" width="-1" type="field" hidden="0"/>
<column name="HFF_FLTYP" width="-1" type="field" hidden="0"/>
<column name="GDF_NR_LAND" width="-1" type="field" hidden="0"/>
<column name="GID_BEZ" width="-1" type="field" hidden="0"/>
<column name="GTF_NR" width="-1" type="field" hidden="0"/>
<column name="HFV_BEW_POP" width="-1" type="field" hidden="0"/>
<column name="HFV_BEW_HAB" width="-1" type="field" hidden="0"/>
<column name="HFV_BEW_BTR" width="-1" type="field" hidden="0"/>
<column name="HFV_ZUS_ERH" width="-1" type="field" hidden="0"/>
<column name="HFV_ABW_GA" width="-1" type="field" hidden="0"/>
<column name="HFV_BEM_ZUS_ERH" width="-1" type="field" hidden="0"/>
<column name="LEGENDE" width="-1" type="field" hidden="0"/>
<column name="REPORT" width="-1" type="field" hidden="0"/>
<column name="GDF_ID" width="-1" type="field" hidden="0"/>
<column name="HFF_ID" width="-1" type="field" hidden="0"/>
<column name="HTFF_ID" width="-1" type="field" hidden="0"/>
<column name="HTFF_HABF_ID" width="-1" type="field" hidden="0"/>
<column name="OBJECTID" width="-1" type="field" hidden="0"/>
<column name="Shape__Area" width="-1" type="field" hidden="0"/>
<column name="Shape__Length" width="-1" type="field" hidden="0"/>
<column name="LEGENDE_2" width="-1" type="field" hidden="0"/>
<column name="SE_ANNO_CAD_DATA" width="-1" type="field" hidden="0"/>
<column width="-1" type="actions" hidden="1"/>
</columns>
</attributetableconfig>
<conditionalstyles>
<rowstyles/>
<fieldstyles/>
</conditionalstyles>
<storedexpressions/>
<editform tolerant="1"></editform>
<editforminit/>
<editforminitcodesource>0</editforminitcodesource>
<editforminitfilepath></editforminitfilepath>
<editforminitcode><![CDATA[# -*- coding: utf-8 -*-
"""
QGIS-Formulare können eine Python-Funktion haben,, die aufgerufen wird, wenn sich das Formular öffnet
Diese Funktion kann verwendet werden um dem Formular Extralogik hinzuzufügen.
Der Name der Funktion wird im Feld "Python Init-Function" angegeben
Ein Beispiel folgt:
"""
from qgis.PyQt.QtWidgets import QWidget
def my_form_open(dialog, layer, feature):
geom = feature.geometry()
control = dialog.findChild(QWidget, "MyLineEdit")
]]></editforminitcode>
<featformsuppress>0</featformsuppress>
<editorlayout>generatedlayout</editorlayout>
<editable>
<field name="ART_DEUTSCH" editable="1"/>
<field name="ART_WISSENSCHAFTL" editable="1"/>
<field name="GDF_ID" editable="1"/>
<field name="GDF_NR_LAND" editable="1"/>
<field name="GID_BEZ" editable="1"/>
<field name="GTF_NR" editable="1"/>
<field name="HBTP_BEZ" editable="1"/>
<field name="HFF_FLTYP" editable="1"/>
<field name="HFF_HABF_ID" editable="1"/>
<field name="HFF_ID" editable="1"/>
<field name="HFV_ABW_GA" editable="1"/>
<field name="HFV_BEM_ZUS_ERH" editable="1"/>
<field name="HFV_BEW_BTR" editable="1"/>
<field name="HFV_BEW_HAB" editable="1"/>
<field name="HFV_BEW_POP" editable="1"/>
<field name="HFV_DAT_ERF" editable="1"/>
<field name="HFV_FLAECHE_RES" editable="1"/>
<field name="HFV_ZUS_ERH" editable="1"/>
<field name="HTFF_HABF_ID" editable="1"/>
<field name="HTFF_ID" editable="1"/>
<field name="LEGENDE" editable="1"/>
<field name="LEGENDE_2" editable="1"/>
<field name="OBJECTID" editable="0"/>
<field name="REPORT" editable="1"/>
<field name="SE_ANNO_CAD_DATA" editable="1"/>
<field name="Shape__Area" editable="0"/>
<field name="Shape__Length" editable="0"/>
</editable>
<labelOnTop>
<field name="ART_DEUTSCH" labelOnTop="0"/>
<field name="ART_WISSENSCHAFTL" labelOnTop="0"/>
<field name="GDF_ID" labelOnTop="0"/>
<field name="GDF_NR_LAND" labelOnTop="0"/>
<field name="GID_BEZ" labelOnTop="0"/>
<field name="GTF_NR" labelOnTop="0"/>
<field name="HBTP_BEZ" labelOnTop="0"/>
<field name="HFF_FLTYP" labelOnTop="0"/>
<field name="HFF_HABF_ID" labelOnTop="0"/>
<field name="HFF_ID" labelOnTop="0"/>
<field name="HFV_ABW_GA" labelOnTop="0"/>
<field name="HFV_BEM_ZUS_ERH" labelOnTop="0"/>
<field name="HFV_BEW_BTR" labelOnTop="0"/>
<field name="HFV_BEW_HAB" labelOnTop="0"/>
<field name="HFV_BEW_POP" labelOnTop="0"/>
<field name="HFV_DAT_ERF" labelOnTop="0"/>
<field name="HFV_FLAECHE_RES" labelOnTop="0"/>
<field name="HFV_ZUS_ERH" labelOnTop="0"/>
<field name="HTFF_HABF_ID" labelOnTop="0"/>
<field name="HTFF_ID" labelOnTop="0"/>
<field name="LEGENDE" labelOnTop="0"/>
<field name="LEGENDE_2" labelOnTop="0"/>
<field name="OBJECTID" labelOnTop="0"/>
<field name="REPORT" labelOnTop="0"/>
<field name="SE_ANNO_CAD_DATA" labelOnTop="0"/>
<field name="Shape__Area" labelOnTop="0"/>
<field name="Shape__Length" labelOnTop="0"/>
</labelOnTop>
<reuseLastValue>
<field name="ART_DEUTSCH" reuseLastValue="0"/>
<field name="ART_WISSENSCHAFTL" reuseLastValue="0"/>
<field name="GDF_ID" reuseLastValue="0"/>
<field name="GDF_NR_LAND" reuseLastValue="0"/>
<field name="GID_BEZ" reuseLastValue="0"/>
<field name="GTF_NR" reuseLastValue="0"/>
<field name="HBTP_BEZ" reuseLastValue="0"/>
<field name="HFF_FLTYP" reuseLastValue="0"/>
<field name="HFF_HABF_ID" reuseLastValue="0"/>
<field name="HFF_ID" reuseLastValue="0"/>
<field name="HFV_ABW_GA" reuseLastValue="0"/>
<field name="HFV_BEM_ZUS_ERH" reuseLastValue="0"/>
<field name="HFV_BEW_BTR" reuseLastValue="0"/>
<field name="HFV_BEW_HAB" reuseLastValue="0"/>
<field name="HFV_BEW_POP" reuseLastValue="0"/>
<field name="HFV_DAT_ERF" reuseLastValue="0"/>
<field name="HFV_FLAECHE_RES" reuseLastValue="0"/>
<field name="HFV_ZUS_ERH" reuseLastValue="0"/>
<field name="HTFF_HABF_ID" reuseLastValue="0"/>
<field name="HTFF_ID" reuseLastValue="0"/>
<field name="LEGENDE" reuseLastValue="0"/>
<field name="LEGENDE_2" reuseLastValue="0"/>
<field name="OBJECTID" reuseLastValue="0"/>
<field name="REPORT" reuseLastValue="0"/>
<field name="SE_ANNO_CAD_DATA" reuseLastValue="0"/>
<field name="Shape__Area" reuseLastValue="0"/>
<field name="Shape__Length" reuseLastValue="0"/>
</reuseLastValue>
<dataDefinedFieldProperties/>
<widgets/>
<previewExpression>"ART_DEUTSCH"</previewExpression>
<mapTip enabled="1"></mapTip>
<layerGeometryType>2</layerGeometryType>
</qgis>
File diff suppressed because it is too large Load Diff
Binary file not shown.
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+597
View File
@@ -0,0 +1,597 @@
<!DOCTYPE qgis PUBLIC 'http://mrcc.com/qgis.dtd' 'SYSTEM'>
<qgis autoRefreshMode="Disabled" autoRefreshTime="0" readOnly="0" styleCategories="AllStyleCategories" simplifyLocal="1" symbologyReferenceScale="-1" minScale="100000000" maxScale="0" labelsEnabled="1" simplifyDrawingHints="1" version="3.40.7-Bratislava" simplifyAlgorithm="0" hasScaleBasedVisibilityFlag="0" simplifyMaxScale="1" simplifyDrawingTol="1">
<flags>
<Identifiable>1</Identifiable>
<Removable>1</Removable>
<Searchable>1</Searchable>
<Private>0</Private>
</flags>
<temporal enabled="0" limitMode="0" startField="" mode="0" durationField="Anzahl" endField="" endExpression="" durationUnit="min" fixedDuration="0" accumulate="0" startExpression="">
<fixedRange>
<start></start>
<end></end>
</fixedRange>
</temporal>
<elevation zscale="1" type="IndividualFeatures" symbology="Line" respectLayerSymbol="1" extrusionEnabled="0" clamping="Terrain" showMarkerSymbolInSurfacePlots="0" extrusion="0" zoffset="0" binding="Centroid">
<data-defined-properties>
<Option type="Map">
<Option type="QString" name="name" value=""/>
<Option name="properties"/>
<Option type="QString" name="type" value="collection"/>
</Option>
</data-defined-properties>
<profileLineSymbol>
<symbol alpha="1" type="line" name="" force_rhr="0" clip_to_extent="1" is_animated="0" frame_rate="10">
<data_defined_properties>
<Option type="Map">
<Option type="QString" name="name" value=""/>
<Option name="properties"/>
<Option type="QString" name="type" value="collection"/>
</Option>
</data_defined_properties>
<layer enabled="1" id="{806bb2f8-e515-41c5-931f-aa961a636da4}" locked="0" class="SimpleLine" pass="0">
<Option type="Map">
<Option type="QString" name="align_dash_pattern" value="0"/>
<Option type="QString" name="capstyle" value="square"/>
<Option type="QString" name="customdash" value="5;2"/>
<Option type="QString" name="customdash_map_unit_scale" value="3x:0,0,0,0,0,0"/>
<Option type="QString" name="customdash_unit" value="MM"/>
<Option type="QString" name="dash_pattern_offset" value="0"/>
<Option type="QString" name="dash_pattern_offset_map_unit_scale" value="3x:0,0,0,0,0,0"/>
<Option type="QString" name="dash_pattern_offset_unit" value="MM"/>
<Option type="QString" name="draw_inside_polygon" value="0"/>
<Option type="QString" name="joinstyle" value="bevel"/>
<Option type="QString" name="line_color" value="231,113,72,255,rgb:0.90588235294117647,0.44313725490196076,0.28235294117647058,1"/>
<Option type="QString" name="line_style" value="solid"/>
<Option type="QString" name="line_width" value="0.6"/>
<Option type="QString" name="line_width_unit" value="MM"/>
<Option type="QString" name="offset" value="0"/>
<Option type="QString" name="offset_map_unit_scale" value="3x:0,0,0,0,0,0"/>
<Option type="QString" name="offset_unit" value="MM"/>
<Option type="QString" name="ring_filter" value="0"/>
<Option type="QString" name="trim_distance_end" value="0"/>
<Option type="QString" name="trim_distance_end_map_unit_scale" value="3x:0,0,0,0,0,0"/>
<Option type="QString" name="trim_distance_end_unit" value="MM"/>
<Option type="QString" name="trim_distance_start" value="0"/>
<Option type="QString" name="trim_distance_start_map_unit_scale" value="3x:0,0,0,0,0,0"/>
<Option type="QString" name="trim_distance_start_unit" value="MM"/>
<Option type="QString" name="tweak_dash_pattern_on_corners" value="0"/>
<Option type="QString" name="use_custom_dash" value="0"/>
<Option type="QString" name="width_map_unit_scale" value="3x:0,0,0,0,0,0"/>
</Option>
<data_defined_properties>
<Option type="Map">
<Option type="QString" name="name" value=""/>
<Option name="properties"/>
<Option type="QString" name="type" value="collection"/>
</Option>
</data_defined_properties>
</layer>
</symbol>
</profileLineSymbol>
<profileFillSymbol>
<symbol alpha="1" type="fill" name="" force_rhr="0" clip_to_extent="1" is_animated="0" frame_rate="10">
<data_defined_properties>
<Option type="Map">
<Option type="QString" name="name" value=""/>
<Option name="properties"/>
<Option type="QString" name="type" value="collection"/>
</Option>
</data_defined_properties>
<layer enabled="1" id="{5fceef15-676f-4c5c-bb67-84e236dc3eab}" locked="0" class="SimpleFill" pass="0">
<Option type="Map">
<Option type="QString" name="border_width_map_unit_scale" value="3x:0,0,0,0,0,0"/>
<Option type="QString" name="color" value="231,113,72,255,rgb:0.90588235294117647,0.44313725490196076,0.28235294117647058,1"/>
<Option type="QString" name="joinstyle" value="bevel"/>
<Option type="QString" name="offset" value="0,0"/>
<Option type="QString" name="offset_map_unit_scale" value="3x:0,0,0,0,0,0"/>
<Option type="QString" name="offset_unit" value="MM"/>
<Option type="QString" name="outline_color" value="165,81,51,255,rgb:0.6470588235294118,0.31651789120317386,0.20167849240863661,1"/>
<Option type="QString" name="outline_style" value="solid"/>
<Option type="QString" name="outline_width" value="0.2"/>
<Option type="QString" name="outline_width_unit" value="MM"/>
<Option type="QString" name="style" value="solid"/>
</Option>
<data_defined_properties>
<Option type="Map">
<Option type="QString" name="name" value=""/>
<Option name="properties"/>
<Option type="QString" name="type" value="collection"/>
</Option>
</data_defined_properties>
</layer>
</symbol>
</profileFillSymbol>
<profileMarkerSymbol>
<symbol alpha="1" type="marker" name="" force_rhr="0" clip_to_extent="1" is_animated="0" frame_rate="10">
<data_defined_properties>
<Option type="Map">
<Option type="QString" name="name" value=""/>
<Option name="properties"/>
<Option type="QString" name="type" value="collection"/>
</Option>
</data_defined_properties>
<layer enabled="1" id="{6c4ff12c-7cf1-4ddc-a6e1-b7f01dda66ad}" locked="0" class="SimpleMarker" pass="0">
<Option type="Map">
<Option type="QString" name="angle" value="0"/>
<Option type="QString" name="cap_style" value="square"/>
<Option type="QString" name="color" value="231,113,72,255,rgb:0.90588235294117647,0.44313725490196076,0.28235294117647058,1"/>
<Option type="QString" name="horizontal_anchor_point" value="1"/>
<Option type="QString" name="joinstyle" value="bevel"/>
<Option type="QString" name="name" value="diamond"/>
<Option type="QString" name="offset" value="0,0"/>
<Option type="QString" name="offset_map_unit_scale" value="3x:0,0,0,0,0,0"/>
<Option type="QString" name="offset_unit" value="MM"/>
<Option type="QString" name="outline_color" value="165,81,51,255,rgb:0.6470588235294118,0.31651789120317386,0.20167849240863661,1"/>
<Option type="QString" name="outline_style" value="solid"/>
<Option type="QString" name="outline_width" value="0.2"/>
<Option type="QString" name="outline_width_map_unit_scale" value="3x:0,0,0,0,0,0"/>
<Option type="QString" name="outline_width_unit" value="MM"/>
<Option type="QString" name="scale_method" value="diameter"/>
<Option type="QString" name="size" value="3"/>
<Option type="QString" name="size_map_unit_scale" value="3x:0,0,0,0,0,0"/>
<Option type="QString" name="size_unit" value="MM"/>
<Option type="QString" name="vertical_anchor_point" value="1"/>
</Option>
<data_defined_properties>
<Option type="Map">
<Option type="QString" name="name" value=""/>
<Option name="properties"/>
<Option type="QString" name="type" value="collection"/>
</Option>
</data_defined_properties>
</layer>
</symbol>
</profileMarkerSymbol>
</elevation>
<renderer-v2 referencescale="-1" type="singleSymbol" forceraster="0" enableorderby="0" symbollevels="0">
<symbols>
<symbol alpha="1" type="fill" name="0" force_rhr="0" clip_to_extent="1" is_animated="0" frame_rate="10">
<data_defined_properties>
<Option type="Map">
<Option type="QString" name="name" value=""/>
<Option name="properties"/>
<Option type="QString" name="type" value="collection"/>
</Option>
</data_defined_properties>
<layer enabled="1" id="{37953f01-68d9-43be-b9d8-546ca454487e}" locked="0" class="SimpleFill" pass="0">
<Option type="Map">
<Option type="QString" name="border_width_map_unit_scale" value="3x:0,0,0,0,0,0"/>
<Option type="QString" name="color" value="0,85,255,255,rgb:0,0.33333333333333331,1,1"/>
<Option type="QString" name="joinstyle" value="bevel"/>
<Option type="QString" name="offset" value="0,0"/>
<Option type="QString" name="offset_map_unit_scale" value="3x:0,0,0,0,0,0"/>
<Option type="QString" name="offset_unit" value="MM"/>
<Option type="QString" name="outline_color" value="0,85,255,255,rgb:0,0.33333333333333331,1,1"/>
<Option type="QString" name="outline_style" value="solid"/>
<Option type="QString" name="outline_width" value="1.06"/>
<Option type="QString" name="outline_width_unit" value="MM"/>
<Option type="QString" name="style" value="no"/>
</Option>
<data_defined_properties>
<Option type="Map">
<Option type="QString" name="name" value=""/>
<Option name="properties"/>
<Option type="QString" name="type" value="collection"/>
</Option>
</data_defined_properties>
</layer>
</symbol>
</symbols>
<rotation/>
<sizescale/>
<data-defined-properties>
<Option type="Map">
<Option type="QString" name="name" value=""/>
<Option name="properties"/>
<Option type="QString" name="type" value="collection"/>
</Option>
</data-defined-properties>
</renderer-v2>
<selection mode="Default">
<selectionColor invalid="1"/>
<selectionSymbol>
<symbol alpha="1" type="fill" name="" force_rhr="0" clip_to_extent="1" is_animated="0" frame_rate="10">
<data_defined_properties>
<Option type="Map">
<Option type="QString" name="name" value=""/>
<Option name="properties"/>
<Option type="QString" name="type" value="collection"/>
</Option>
</data_defined_properties>
<layer enabled="1" id="{37c84ab2-1f8e-4d9f-90bb-400976543063}" locked="0" class="SimpleFill" pass="0">
<Option type="Map">
<Option type="QString" name="border_width_map_unit_scale" value="3x:0,0,0,0,0,0"/>
<Option type="QString" name="color" value="0,0,255,255,rgb:0,0,1,1"/>
<Option type="QString" name="joinstyle" value="bevel"/>
<Option type="QString" name="offset" value="0,0"/>
<Option type="QString" name="offset_map_unit_scale" value="3x:0,0,0,0,0,0"/>
<Option type="QString" name="offset_unit" value="MM"/>
<Option type="QString" name="outline_color" value="35,35,35,255,rgb:0.13725490196078433,0.13725490196078433,0.13725490196078433,1"/>
<Option type="QString" name="outline_style" value="solid"/>
<Option type="QString" name="outline_width" value="0.26"/>
<Option type="QString" name="outline_width_unit" value="MM"/>
<Option type="QString" name="style" value="solid"/>
</Option>
<data_defined_properties>
<Option type="Map">
<Option type="QString" name="name" value=""/>
<Option name="properties"/>
<Option type="QString" name="type" value="collection"/>
</Option>
</data_defined_properties>
</layer>
</symbol>
</selectionSymbol>
</selection>
<labeling type="rule-based">
<rules key="{31adca09-e30f-437a-bc70-ef63b20670ed}">
<rule filter="left(&quot;MKZ&quot;,3)='222'" key="{79a5bb52-55b4-45ee-89fe-d90e0fe95f62}" description="Wege,geplant">
<settings calloutType="simple">
<text-style fontKerning="0" useSubstitutions="0" namedStyle="Bold" previewBkgrdColor="255,255,255,255,rgb:1,1,1,1" fontWeight="75" tabStopDistanceMapUnitScale="3x:0,0,0,0,0,0" fontUnderline="0" tabStopDistance="80" fieldName="left(&quot;MKZ&quot;,3)|| '\n' || '―'|| '\n' || right(&quot;MKZ&quot;,4)" textColor="5,125,180,255,rgb:0.0196078431372549,0.49019607843137253,0.70588235294117652,1" fontStrikeout="0" forcedBold="0" forcedItalic="0" allowHtml="0" multilineHeight="0.59999999999999998" fontSize="10" fontWordSpacing="-0.6875" stretchFactor="100" blendMode="0" fontSizeMapUnitScale="3x:0,0,0,0,0,0" textOrientation="horizontal" fontItalic="0" fontLetterSpacing="-0.5625" tabStopDistanceUnit="Point" multilineHeightUnit="Percentage" fontFamily="Arial" fontSizeUnit="Point" capitalization="0" isExpression="1" legendString="Aa" textOpacity="1">
<families/>
<text-buffer bufferColor="255,0,0,255,hsv:0,1,1,1" bufferNoFill="1" bufferSize="1" bufferSizeMapUnitScale="3x:0,0,0,0,0,0" bufferSizeUnits="MM" bufferDraw="0" bufferJoinStyle="128" bufferOpacity="1" bufferBlendMode="0"/>
<text-mask maskedSymbolLayers="" maskJoinStyle="128" maskEnabled="0" maskType="0" maskSize2="1.5" maskSizeUnits="MM" maskSizeMapUnitScale="3x:0,0,0,0,0,0" maskSize="1.5" maskOpacity="1"/>
<background shapeJoinStyle="64" shapeBlendMode="0" shapeRotationType="0" shapeRadiiX="0" shapeRadiiY="0" shapeSVGFile="" shapeSizeType="0" shapeBorderWidthMapUnitScale="3x:0,0,0,0,0,0" shapeSizeUnit="Point" shapeRadiiMapUnitScale="3x:0,0,0,0,0,0" shapeFillColor="255,255,255,255,rgb:1,1,1,1" shapeOffsetMapUnitScale="3x:0,0,0,0,0,0" shapeDraw="1" shapeRotation="0" shapeType="5" shapeSizeMapUnitScale="3x:0,0,0,0,0,0" shapeOffsetUnit="Point" shapeRadiiUnit="Point" shapeSizeX="3" shapeOpacity="1" shapeBorderWidth="0" shapeOffsetY="0" shapeBorderColor="128,128,128,255,rgb:0.50196078431372548,0.50196078431372548,0.50196078431372548,1" shapeBorderWidthUnit="Point" shapeSizeY="0" shapeOffsetX="0">
<symbol alpha="1" type="marker" name="markerSymbol" force_rhr="0" clip_to_extent="1" is_animated="0" frame_rate="10">
<data_defined_properties>
<Option type="Map">
<Option type="QString" name="name" value=""/>
<Option name="properties"/>
<Option type="QString" name="type" value="collection"/>
</Option>
</data_defined_properties>
<layer enabled="1" id="" locked="0" class="SimpleMarker" pass="0">
<Option type="Map">
<Option type="QString" name="angle" value="0"/>
<Option type="QString" name="cap_style" value="square"/>
<Option type="QString" name="color" value="255,255,255,255,rgb:1,1,1,1"/>
<Option type="QString" name="horizontal_anchor_point" value="1"/>
<Option type="QString" name="joinstyle" value="bevel"/>
<Option type="QString" name="name" value="circle"/>
<Option type="QString" name="offset" value="0,0"/>
<Option type="QString" name="offset_map_unit_scale" value="3x:0,0,0,0,0,0"/>
<Option type="QString" name="offset_unit" value="MM"/>
<Option type="QString" name="outline_color" value="8,135,203,255,rgb:0.03137254901960784,0.52941176470588236,0.79607843137254897,1"/>
<Option type="QString" name="outline_style" value="solid"/>
<Option type="QString" name="outline_width" value="0.6"/>
<Option type="QString" name="outline_width_map_unit_scale" value="3x:0,0,0,0,0,0"/>
<Option type="QString" name="outline_width_unit" value="MM"/>
<Option type="QString" name="scale_method" value="diameter"/>
<Option type="QString" name="size" value="2"/>
<Option type="QString" name="size_map_unit_scale" value="3x:0,0,0,0,0,0"/>
<Option type="QString" name="size_unit" value="MM"/>
<Option type="QString" name="vertical_anchor_point" value="1"/>
</Option>
<data_defined_properties>
<Option type="Map">
<Option type="QString" name="name" value=""/>
<Option name="properties"/>
<Option type="QString" name="type" value="collection"/>
</Option>
</data_defined_properties>
</layer>
</symbol>
<symbol alpha="1" type="fill" name="fillSymbol" force_rhr="0" clip_to_extent="1" is_animated="0" frame_rate="10">
<data_defined_properties>
<Option type="Map">
<Option type="QString" name="name" value=""/>
<Option name="properties"/>
<Option type="QString" name="type" value="collection"/>
</Option>
</data_defined_properties>
<layer enabled="1" id="" locked="0" class="SimpleFill" pass="0">
<Option type="Map">
<Option type="QString" name="border_width_map_unit_scale" value="3x:0,0,0,0,0,0"/>
<Option type="QString" name="color" value="255,255,255,255,rgb:1,1,1,1"/>
<Option type="QString" name="joinstyle" value="bevel"/>
<Option type="QString" name="offset" value="0,0"/>
<Option type="QString" name="offset_map_unit_scale" value="3x:0,0,0,0,0,0"/>
<Option type="QString" name="offset_unit" value="MM"/>
<Option type="QString" name="outline_color" value="128,128,128,255,rgb:0.50196078431372548,0.50196078431372548,0.50196078431372548,1"/>
<Option type="QString" name="outline_style" value="no"/>
<Option type="QString" name="outline_width" value="0"/>
<Option type="QString" name="outline_width_unit" value="Point"/>
<Option type="QString" name="style" value="solid"/>
</Option>
<data_defined_properties>
<Option type="Map">
<Option type="QString" name="name" value=""/>
<Option name="properties"/>
<Option type="QString" name="type" value="collection"/>
</Option>
</data_defined_properties>
</layer>
</symbol>
</background>
<shadow shadowOffsetAngle="135" shadowRadiusAlphaOnly="0" shadowUnder="0" shadowOffsetMapUnitScale="3x:0,0,0,0,0,0" shadowRadius="1.5" shadowOffsetDist="1" shadowScale="100" shadowColor="0,0,0,255,rgb:0,0,0,1" shadowOffsetUnit="MM" shadowRadiusUnit="MM" shadowBlendMode="6" shadowOpacity="0.69999999999999996" shadowDraw="0" shadowRadiusMapUnitScale="3x:0,0,0,0,0,0" shadowOffsetGlobal="1"/>
<dd_properties>
<Option type="Map">
<Option type="QString" name="name" value=""/>
<Option name="properties"/>
<Option type="QString" name="type" value="collection"/>
</Option>
</dd_properties>
<substitutions/>
</text-style>
<text-format useMaxLineLengthForAutoWrap="1" formatNumbers="0" leftDirectionSymbol="&lt;" rightDirectionSymbol=">" reverseDirectionSymbol="0" decimals="3" wrapChar="" autoWrapLength="0" placeDirectionSymbol="0" plussign="0" multilineAlign="1" addDirectionSymbol="0"/>
<placement placementFlags="14" placement="4" distUnits="MM" maximumDistance="0" fitInPolygonOnly="0" offsetUnits="MM" repeatDistance="0" geometryGeneratorEnabled="0" rotationUnit="AngleDegrees" lineAnchorTextPoint="CenterOfText" lineAnchorClipping="1" centroidWhole="0" priority="6" geometryGeneratorType="PointGeometry" prioritization="PreferCloser" repeatDistanceMapUnitScale="3x:0,0,0,0,0,0" overrunDistance="0" rotationAngle="0" quadOffset="4" dist="5" overlapHandling="PreventOverlap" offsetType="0" layerType="PolygonGeometry" repeatDistanceUnits="MM" predefinedPositionOrder="TR,TL,BR,BL,R,L,TSR,BSR" overrunDistanceMapUnitScale="3x:0,0,0,0,0,0" centroidInside="0" maximumDistanceUnit="MM" allowDegraded="0" maxCurvedCharAngleOut="-25" polygonPlacementFlags="3" labelOffsetMapUnitScale="3x:0,0,0,0,0,0" geometryGenerator="" lineAnchorType="0" lineAnchorPercent="0.5" xOffset="0" preserveRotation="0" maxCurvedCharAngleIn="25" overrunDistanceUnit="MM" yOffset="0" maximumDistanceMapUnitScale="3x:0,0,0,0,0,0" distMapUnitScale="3x:0,0,0,0,0,0"/>
<rendering obstacle="1" scaleVisibility="0" maxNumLabels="2000" drawLabels="1" labelPerPart="0" obstacleFactor="1.2" fontMinPixelSize="3" scaleMin="0" unplacedVisibility="0" zIndex="0" upsidedownLabels="0" fontLimitPixelSize="0" limitNumLabels="0" minFeatureSize="0" fontMaxPixelSize="10000" scaleMax="0" obstacleType="1" mergeLines="0"/>
<dd_properties>
<Option type="Map">
<Option type="QString" name="name" value=""/>
<Option name="properties"/>
<Option type="QString" name="type" value="collection"/>
</Option>
</dd_properties>
<callout type="simple">
<Option type="Map">
<Option type="QString" name="anchorPoint" value="pole_of_inaccessibility"/>
<Option type="int" name="blendMode" value="0"/>
<Option type="Map" name="ddProperties">
<Option type="QString" name="name" value=""/>
<Option name="properties"/>
<Option type="QString" name="type" value="collection"/>
</Option>
<Option type="bool" name="drawToAllParts" value="false"/>
<Option type="QString" name="enabled" value="0"/>
<Option type="QString" name="labelAnchorPoint" value="point_on_exterior"/>
<Option type="QString" name="lineSymbol" value="&lt;symbol alpha=&quot;1&quot; type=&quot;line&quot; name=&quot;symbol&quot; force_rhr=&quot;0&quot; clip_to_extent=&quot;1&quot; is_animated=&quot;0&quot; frame_rate=&quot;10&quot;>&lt;data_defined_properties>&lt;Option type=&quot;Map&quot;>&lt;Option type=&quot;QString&quot; name=&quot;name&quot; value=&quot;&quot;/>&lt;Option name=&quot;properties&quot;/>&lt;Option type=&quot;QString&quot; name=&quot;type&quot; value=&quot;collection&quot;/>&lt;/Option>&lt;/data_defined_properties>&lt;layer enabled=&quot;1&quot; id=&quot;{03dc8a93-2fef-4767-9787-e3607853696d}&quot; locked=&quot;0&quot; class=&quot;SimpleLine&quot; pass=&quot;0&quot;>&lt;Option type=&quot;Map&quot;>&lt;Option type=&quot;QString&quot; name=&quot;align_dash_pattern&quot; value=&quot;0&quot;/>&lt;Option type=&quot;QString&quot; name=&quot;capstyle&quot; value=&quot;square&quot;/>&lt;Option type=&quot;QString&quot; name=&quot;customdash&quot; value=&quot;5;2&quot;/>&lt;Option type=&quot;QString&quot; name=&quot;customdash_map_unit_scale&quot; value=&quot;3x:0,0,0,0,0,0&quot;/>&lt;Option type=&quot;QString&quot; name=&quot;customdash_unit&quot; value=&quot;MM&quot;/>&lt;Option type=&quot;QString&quot; name=&quot;dash_pattern_offset&quot; value=&quot;0&quot;/>&lt;Option type=&quot;QString&quot; name=&quot;dash_pattern_offset_map_unit_scale&quot; value=&quot;3x:0,0,0,0,0,0&quot;/>&lt;Option type=&quot;QString&quot; name=&quot;dash_pattern_offset_unit&quot; value=&quot;MM&quot;/>&lt;Option type=&quot;QString&quot; name=&quot;draw_inside_polygon&quot; value=&quot;0&quot;/>&lt;Option type=&quot;QString&quot; name=&quot;joinstyle&quot; value=&quot;bevel&quot;/>&lt;Option type=&quot;QString&quot; name=&quot;line_color&quot; value=&quot;60,60,60,255,rgb:0.23529411764705882,0.23529411764705882,0.23529411764705882,1&quot;/>&lt;Option type=&quot;QString&quot; name=&quot;line_style&quot; value=&quot;solid&quot;/>&lt;Option type=&quot;QString&quot; name=&quot;line_width&quot; value=&quot;0.3&quot;/>&lt;Option type=&quot;QString&quot; name=&quot;line_width_unit&quot; value=&quot;MM&quot;/>&lt;Option type=&quot;QString&quot; name=&quot;offset&quot; value=&quot;0&quot;/>&lt;Option type=&quot;QString&quot; name=&quot;offset_map_unit_scale&quot; value=&quot;3x:0,0,0,0,0,0&quot;/>&lt;Option type=&quot;QString&quot; name=&quot;offset_unit&quot; value=&quot;MM&quot;/>&lt;Option type=&quot;QString&quot; name=&quot;ring_filter&quot; value=&quot;0&quot;/>&lt;Option type=&quot;QString&quot; name=&quot;trim_distance_end&quot; value=&quot;0&quot;/>&lt;Option type=&quot;QString&quot; name=&quot;trim_distance_end_map_unit_scale&quot; value=&quot;3x:0,0,0,0,0,0&quot;/>&lt;Option type=&quot;QString&quot; name=&quot;trim_distance_end_unit&quot; value=&quot;MM&quot;/>&lt;Option type=&quot;QString&quot; name=&quot;trim_distance_start&quot; value=&quot;0&quot;/>&lt;Option type=&quot;QString&quot; name=&quot;trim_distance_start_map_unit_scale&quot; value=&quot;3x:0,0,0,0,0,0&quot;/>&lt;Option type=&quot;QString&quot; name=&quot;trim_distance_start_unit&quot; value=&quot;MM&quot;/>&lt;Option type=&quot;QString&quot; name=&quot;tweak_dash_pattern_on_corners&quot; value=&quot;0&quot;/>&lt;Option type=&quot;QString&quot; name=&quot;use_custom_dash&quot; value=&quot;0&quot;/>&lt;Option type=&quot;QString&quot; name=&quot;width_map_unit_scale&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 type=&quot;QString&quot; name=&quot;name&quot; value=&quot;&quot;/>&lt;Option name=&quot;properties&quot;/>&lt;Option type=&quot;QString&quot; name=&quot;type&quot; value=&quot;collection&quot;/>&lt;/Option>&lt;/data_defined_properties>&lt;/layer>&lt;/symbol>"/>
<Option type="double" name="minLength" value="0"/>
<Option type="QString" name="minLengthMapUnitScale" value="3x:0,0,0,0,0,0"/>
<Option type="QString" name="minLengthUnit" value="MM"/>
<Option type="double" name="offsetFromAnchor" value="0"/>
<Option type="QString" name="offsetFromAnchorMapUnitScale" value="3x:0,0,0,0,0,0"/>
<Option type="QString" name="offsetFromAnchorUnit" value="MM"/>
<Option type="double" name="offsetFromLabel" value="0"/>
<Option type="QString" name="offsetFromLabelMapUnitScale" value="3x:0,0,0,0,0,0"/>
<Option type="QString" name="offsetFromLabelUnit" value="MM"/>
</Option>
</callout>
</settings>
</rule>
</rules>
</labeling>
<customproperties>
<Option type="Map">
<Option type="List" name="dualview/previewExpressions">
<Option type="QString" value="&quot;NAME&quot;"/>
</Option>
<Option type="int" name="embeddedWidgets/count" value="0"/>
<Option type="QString" name="geopdf/groupName" value="Verfahren"/>
<Option name="variableNames"/>
<Option name="variableValues"/>
<Option type="QString" name="vln_karten/api_path" value="/maps/p41/27027"/>
<Option type="QString" name="vln_karten/dataset" value="p41"/>
<Option type="QString" name="vln_karten/verfahren" value="27027"/>
</Option>
</customproperties>
<blendMode>0</blendMode>
<featureBlendMode>0</featureBlendMode>
<layerOpacity>1</layerOpacity>
<geometryOptions removeDuplicateNodes="0" geometryPrecision="0">
<activeChecks/>
<checkConfiguration type="Map">
<Option type="Map" name="QgsGeometryGapCheck">
<Option type="double" name="allowedGapsBuffer" value="0"/>
<Option type="bool" name="allowedGapsEnabled" value="false"/>
<Option type="QString" name="allowedGapsLayer" value=""/>
</Option>
</checkConfiguration>
</geometryOptions>
<legend type="default-vector" showLabelLegend="0"/>
<referencedLayers/>
<fieldConfiguration>
<field name="Anzahl" configurationFlags="NoFlag">
<editWidget type="Range">
<config>
<Option/>
</config>
</editWidget>
</field>
<field name="Baumart" configurationFlags="NoFlag">
<editWidget type="TextEdit">
<config>
<Option/>
</config>
</editWidget>
</field>
<field name="Belag" configurationFlags="NoFlag">
<editWidget type="TextEdit">
<config>
<Option/>
</config>
</editWidget>
</field>
<field name="Fahrbahn" configurationFlags="NoFlag">
<editWidget type="TextEdit">
<config>
<Option/>
</config>
</editWidget>
</field>
<field name="Krone" configurationFlags="NoFlag">
<editWidget type="Range">
<config>
<Option/>
</config>
</editWidget>
</field>
<field name="MKZ" configurationFlags="NoFlag">
<editWidget type="TextEdit">
<config>
<Option/>
</config>
</editWidget>
</field>
<field name="NAME" configurationFlags="NoFlag">
<editWidget type="TextEdit">
<config>
<Option/>
</config>
</editWidget>
</field>
<field name="VKZ" configurationFlags="NoFlag">
<editWidget type="TextEdit">
<config>
<Option/>
</config>
</editWidget>
</field>
<field name="qm" configurationFlags="NoFlag">
<editWidget type="Range">
<config>
<Option/>
</config>
</editWidget>
</field>
</fieldConfiguration>
<aliases>
<alias name="" index="0" field="Anzahl"/>
<alias name="" index="1" field="Baumart"/>
<alias name="" index="2" field="Belag"/>
<alias name="" index="3" field="Fahrbahn"/>
<alias name="" index="4" field="Krone"/>
<alias name="" index="5" field="MKZ"/>
<alias name="" index="6" field="NAME"/>
<alias name="" index="7" field="VKZ"/>
<alias name="" index="8" field="qm"/>
</aliases>
<splitPolicies>
<policy policy="Duplicate" field="Anzahl"/>
<policy policy="Duplicate" field="Baumart"/>
<policy policy="Duplicate" field="Belag"/>
<policy policy="Duplicate" field="Fahrbahn"/>
<policy policy="Duplicate" field="Krone"/>
<policy policy="Duplicate" field="MKZ"/>
<policy policy="Duplicate" field="NAME"/>
<policy policy="Duplicate" field="VKZ"/>
<policy policy="Duplicate" field="qm"/>
</splitPolicies>
<duplicatePolicies>
<policy policy="Duplicate" field="Anzahl"/>
<policy policy="Duplicate" field="Baumart"/>
<policy policy="Duplicate" field="Belag"/>
<policy policy="Duplicate" field="Fahrbahn"/>
<policy policy="Duplicate" field="Krone"/>
<policy policy="Duplicate" field="MKZ"/>
<policy policy="Duplicate" field="NAME"/>
<policy policy="Duplicate" field="VKZ"/>
<policy policy="Duplicate" field="qm"/>
</duplicatePolicies>
<defaults>
<default expression="" applyOnUpdate="0" field="Anzahl"/>
<default expression="" applyOnUpdate="0" field="Baumart"/>
<default expression="" applyOnUpdate="0" field="Belag"/>
<default expression="" applyOnUpdate="0" field="Fahrbahn"/>
<default expression="" applyOnUpdate="0" field="Krone"/>
<default expression="" applyOnUpdate="0" field="MKZ"/>
<default expression="" applyOnUpdate="0" field="NAME"/>
<default expression="" applyOnUpdate="0" field="VKZ"/>
<default expression="" applyOnUpdate="0" field="qm"/>
</defaults>
<constraints>
<constraint exp_strength="0" notnull_strength="0" constraints="0" unique_strength="0" field="Anzahl"/>
<constraint exp_strength="0" notnull_strength="0" constraints="0" unique_strength="0" field="Baumart"/>
<constraint exp_strength="0" notnull_strength="0" constraints="0" unique_strength="0" field="Belag"/>
<constraint exp_strength="0" notnull_strength="0" constraints="0" unique_strength="0" field="Fahrbahn"/>
<constraint exp_strength="0" notnull_strength="0" constraints="0" unique_strength="0" field="Krone"/>
<constraint exp_strength="0" notnull_strength="0" constraints="0" unique_strength="0" field="MKZ"/>
<constraint exp_strength="0" notnull_strength="0" constraints="0" unique_strength="0" field="NAME"/>
<constraint exp_strength="0" notnull_strength="0" constraints="0" unique_strength="0" field="VKZ"/>
<constraint exp_strength="0" notnull_strength="0" constraints="0" unique_strength="0" field="qm"/>
</constraints>
<constraintExpressions>
<constraint exp="" desc="" field="Anzahl"/>
<constraint exp="" desc="" field="Baumart"/>
<constraint exp="" desc="" field="Belag"/>
<constraint exp="" desc="" field="Fahrbahn"/>
<constraint exp="" desc="" field="Krone"/>
<constraint exp="" desc="" field="MKZ"/>
<constraint exp="" desc="" field="NAME"/>
<constraint exp="" desc="" field="VKZ"/>
<constraint exp="" desc="" field="qm"/>
</constraintExpressions>
<expressionfields/>
<attributeactions>
<defaultAction value="{00000000-0000-0000-0000-000000000000}" key="Canvas"/>
</attributeactions>
<attributetableconfig sortExpression="" actionWidgetStyle="dropDown" sortOrder="0">
<columns>
<column type="field" name="Anzahl" width="-1" hidden="0"/>
<column type="field" name="Baumart" width="-1" hidden="0"/>
<column type="field" name="Belag" width="-1" hidden="0"/>
<column type="field" name="Fahrbahn" width="-1" hidden="0"/>
<column type="field" name="Krone" width="-1" hidden="0"/>
<column type="field" name="MKZ" width="-1" hidden="0"/>
<column type="field" name="NAME" width="-1" hidden="0"/>
<column type="field" name="VKZ" width="-1" hidden="0"/>
<column type="field" name="qm" width="-1" hidden="0"/>
<column type="actions" width="-1" hidden="1"/>
</columns>
</attributetableconfig>
<conditionalstyles>
<rowstyles/>
<fieldstyles/>
</conditionalstyles>
<storedexpressions/>
<editform tolerant="1"></editform>
<editforminit/>
<editforminitcodesource>0</editforminitcodesource>
<editforminitfilepath></editforminitfilepath>
<editforminitcode><![CDATA[# -*- coding: utf-8 -*-
"""
QGIS-Formulare können eine Python-Funktion haben,, die aufgerufen wird, wenn sich das Formular öffnet
Diese Funktion kann verwendet werden um dem Formular Extralogik hinzuzufügen.
Der Name der Funktion wird im Feld "Python Init-Function" angegeben
Ein Beispiel folgt:
"""
from qgis.PyQt.QtWidgets import QWidget
def my_form_open(dialog, layer, feature):
geom = feature.geometry()
control = dialog.findChild(QWidget, "MyLineEdit")
]]></editforminitcode>
<featformsuppress>0</featformsuppress>
<editorlayout>generatedlayout</editorlayout>
<editable>
<field name="Anzahl" editable="1"/>
<field name="Baumart" editable="1"/>
<field name="Belag" editable="1"/>
<field name="Fahrbahn" editable="1"/>
<field name="Krone" editable="1"/>
<field name="MKZ" editable="1"/>
<field name="NAME" editable="1"/>
<field name="VKZ" editable="1"/>
<field name="qm" editable="1"/>
</editable>
<labelOnTop>
<field name="Anzahl" labelOnTop="0"/>
<field name="Baumart" labelOnTop="0"/>
<field name="Belag" labelOnTop="0"/>
<field name="Fahrbahn" labelOnTop="0"/>
<field name="Krone" labelOnTop="0"/>
<field name="MKZ" labelOnTop="0"/>
<field name="NAME" labelOnTop="0"/>
<field name="VKZ" labelOnTop="0"/>
<field name="qm" labelOnTop="0"/>
</labelOnTop>
<reuseLastValue>
<field reuseLastValue="0" name="Anzahl"/>
<field reuseLastValue="0" name="Baumart"/>
<field reuseLastValue="0" name="Belag"/>
<field reuseLastValue="0" name="Fahrbahn"/>
<field reuseLastValue="0" name="Krone"/>
<field reuseLastValue="0" name="MKZ"/>
<field reuseLastValue="0" name="NAME"/>
<field reuseLastValue="0" name="VKZ"/>
<field reuseLastValue="0" name="qm"/>
</reuseLastValue>
<dataDefinedFieldProperties/>
<widgets/>
<previewExpression>"NAME"</previewExpression>
<mapTip enabled="1"></mapTip>
<layerGeometryType>2</layerGeometryType>
</qgis>
+516
View File
@@ -0,0 +1,516 @@
<!DOCTYPE qgis PUBLIC 'http://mrcc.com/qgis.dtd' 'SYSTEM'>
<qgis maxScale="0" simplifyDrawingHints="1" simplifyMaxScale="1" simplifyLocal="1" styleCategories="AllStyleCategories" labelsEnabled="0" simplifyAlgorithm="0" minScale="100000000" version="3.40.7-Bratislava" symbologyReferenceScale="-1" hasScaleBasedVisibilityFlag="0" autoRefreshMode="Disabled" readOnly="0" autoRefreshTime="0" simplifyDrawingTol="1">
<flags>
<Identifiable>1</Identifiable>
<Removable>1</Removable>
<Searchable>1</Searchable>
<Private>0</Private>
</flags>
<temporal endExpression="" durationField="OBJECTID" enabled="0" mode="0" fixedDuration="0" startField="" accumulate="0" limitMode="0" endField="" durationUnit="min" startExpression="">
<fixedRange>
<start></start>
<end></end>
</fixedRange>
</temporal>
<elevation respectLayerSymbol="1" zscale="1" extrusionEnabled="0" extrusion="0" type="IndividualFeatures" clamping="Terrain" symbology="Line" binding="Centroid" showMarkerSymbolInSurfacePlots="0" zoffset="0">
<data-defined-properties>
<Option type="Map">
<Option name="name" type="QString" value=""/>
<Option name="properties"/>
<Option name="type" type="QString" value="collection"/>
</Option>
</data-defined-properties>
<profileLineSymbol>
<symbol frame_rate="10" clip_to_extent="1" is_animated="0" name="" force_rhr="0" type="line" alpha="1">
<data_defined_properties>
<Option type="Map">
<Option name="name" type="QString" value=""/>
<Option name="properties"/>
<Option name="type" type="QString" value="collection"/>
</Option>
</data_defined_properties>
<layer enabled="1" class="SimpleLine" locked="0" id="{322ac269-5ed9-4529-82eb-f6d50258e9d7}" pass="0">
<Option type="Map">
<Option name="align_dash_pattern" type="QString" value="0"/>
<Option name="capstyle" type="QString" value="square"/>
<Option name="customdash" type="QString" value="5;2"/>
<Option name="customdash_map_unit_scale" type="QString" value="3x:0,0,0,0,0,0"/>
<Option name="customdash_unit" type="QString" value="MM"/>
<Option name="dash_pattern_offset" type="QString" value="0"/>
<Option name="dash_pattern_offset_map_unit_scale" type="QString" value="3x:0,0,0,0,0,0"/>
<Option name="dash_pattern_offset_unit" type="QString" value="MM"/>
<Option name="draw_inside_polygon" type="QString" value="0"/>
<Option name="joinstyle" type="QString" value="bevel"/>
<Option name="line_color" type="QString" value="145,82,45,255,rgb:0.56862745098039214,0.32156862745098042,0.17647058823529413,1"/>
<Option name="line_style" type="QString" value="solid"/>
<Option name="line_width" type="QString" value="0.6"/>
<Option name="line_width_unit" type="QString" value="MM"/>
<Option name="offset" type="QString" value="0"/>
<Option name="offset_map_unit_scale" type="QString" value="3x:0,0,0,0,0,0"/>
<Option name="offset_unit" type="QString" value="MM"/>
<Option name="ring_filter" type="QString" value="0"/>
<Option name="trim_distance_end" type="QString" value="0"/>
<Option name="trim_distance_end_map_unit_scale" type="QString" value="3x:0,0,0,0,0,0"/>
<Option name="trim_distance_end_unit" type="QString" value="MM"/>
<Option name="trim_distance_start" type="QString" value="0"/>
<Option name="trim_distance_start_map_unit_scale" type="QString" value="3x:0,0,0,0,0,0"/>
<Option name="trim_distance_start_unit" type="QString" value="MM"/>
<Option name="tweak_dash_pattern_on_corners" type="QString" value="0"/>
<Option name="use_custom_dash" type="QString" value="0"/>
<Option name="width_map_unit_scale" type="QString" value="3x:0,0,0,0,0,0"/>
</Option>
<data_defined_properties>
<Option type="Map">
<Option name="name" type="QString" value=""/>
<Option name="properties"/>
<Option name="type" type="QString" value="collection"/>
</Option>
</data_defined_properties>
</layer>
</symbol>
</profileLineSymbol>
<profileFillSymbol>
<symbol frame_rate="10" clip_to_extent="1" is_animated="0" name="" force_rhr="0" type="fill" alpha="1">
<data_defined_properties>
<Option type="Map">
<Option name="name" type="QString" value=""/>
<Option name="properties"/>
<Option name="type" type="QString" value="collection"/>
</Option>
</data_defined_properties>
<layer enabled="1" class="SimpleFill" locked="0" id="{8a672c34-07cc-4c89-b9a6-b505a5d0e87f}" pass="0">
<Option type="Map">
<Option name="border_width_map_unit_scale" type="QString" value="3x:0,0,0,0,0,0"/>
<Option name="color" type="QString" value="145,82,45,255,rgb:0.56862745098039214,0.32156862745098042,0.17647058823529413,1"/>
<Option name="joinstyle" type="QString" value="bevel"/>
<Option name="offset" type="QString" value="0,0"/>
<Option name="offset_map_unit_scale" type="QString" value="3x:0,0,0,0,0,0"/>
<Option name="offset_unit" type="QString" value="MM"/>
<Option name="outline_color" type="QString" value="104,59,32,255,rgb:0.40614938582436866,0.22967879758907453,0.12603952086671244,1"/>
<Option name="outline_style" type="QString" value="solid"/>
<Option name="outline_width" type="QString" value="0.2"/>
<Option name="outline_width_unit" type="QString" value="MM"/>
<Option name="style" type="QString" value="solid"/>
</Option>
<data_defined_properties>
<Option type="Map">
<Option name="name" type="QString" value=""/>
<Option name="properties"/>
<Option name="type" type="QString" value="collection"/>
</Option>
</data_defined_properties>
</layer>
</symbol>
</profileFillSymbol>
<profileMarkerSymbol>
<symbol frame_rate="10" clip_to_extent="1" is_animated="0" name="" force_rhr="0" type="marker" alpha="1">
<data_defined_properties>
<Option type="Map">
<Option name="name" type="QString" value=""/>
<Option name="properties"/>
<Option name="type" type="QString" value="collection"/>
</Option>
</data_defined_properties>
<layer enabled="1" class="SimpleMarker" locked="0" id="{203784dc-59ab-4b43-bd5b-cc85a7fcf2f5}" pass="0">
<Option type="Map">
<Option name="angle" type="QString" value="0"/>
<Option name="cap_style" type="QString" value="square"/>
<Option name="color" type="QString" value="145,82,45,255,rgb:0.56862745098039214,0.32156862745098042,0.17647058823529413,1"/>
<Option name="horizontal_anchor_point" type="QString" value="1"/>
<Option name="joinstyle" type="QString" value="bevel"/>
<Option name="name" type="QString" value="diamond"/>
<Option name="offset" type="QString" value="0,0"/>
<Option name="offset_map_unit_scale" type="QString" value="3x:0,0,0,0,0,0"/>
<Option name="offset_unit" type="QString" value="MM"/>
<Option name="outline_color" type="QString" value="104,59,32,255,rgb:0.40614938582436866,0.22967879758907453,0.12603952086671244,1"/>
<Option name="outline_style" type="QString" value="solid"/>
<Option name="outline_width" type="QString" value="0.2"/>
<Option name="outline_width_map_unit_scale" type="QString" value="3x:0,0,0,0,0,0"/>
<Option name="outline_width_unit" type="QString" value="MM"/>
<Option name="scale_method" type="QString" value="diameter"/>
<Option name="size" type="QString" value="3"/>
<Option name="size_map_unit_scale" type="QString" value="3x:0,0,0,0,0,0"/>
<Option name="size_unit" type="QString" value="MM"/>
<Option name="vertical_anchor_point" type="QString" value="1"/>
</Option>
<data_defined_properties>
<Option type="Map">
<Option name="name" type="QString" value=""/>
<Option name="properties"/>
<Option name="type" type="QString" value="collection"/>
</Option>
</data_defined_properties>
</layer>
</symbol>
</profileMarkerSymbol>
</elevation>
<renderer-v2 forceraster="0" type="categorizedSymbol" enableorderby="0" referencescale="-1" attr="FB_BN_KAT" symbollevels="0">
<categories>
<category render="true" uuid="{fe3d6ff3-2b79-4775-8ee7-3d1ccfd1cd77}" type="string" label="AL" value="AL" symbol="0"/>
<category render="true" uuid="{4bea0187-6bcf-418a-bbd9-39f7b5334b19}" type="NULL" label="" value="NULL" symbol="1"/>
</categories>
<symbols>
<symbol frame_rate="10" clip_to_extent="1" is_animated="0" name="0" force_rhr="0" type="fill" alpha="1">
<data_defined_properties>
<Option type="Map">
<Option name="name" type="QString" value=""/>
<Option name="properties"/>
<Option name="type" type="QString" value="collection"/>
</Option>
</data_defined_properties>
<layer enabled="1" class="SimpleFill" locked="0" id="{6725bd87-d1ed-46a2-a500-d22c83510ab8}" pass="0">
<Option type="Map">
<Option name="border_width_map_unit_scale" type="QString" value="3x:0,0,0,0,0,0"/>
<Option name="color" type="QString" value="203,203,101,255,rgb:0.79607843137254897,0.79607843137254897,0.396078431372549,1"/>
<Option name="joinstyle" type="QString" value="bevel"/>
<Option name="offset" type="QString" value="0,0"/>
<Option name="offset_map_unit_scale" type="QString" value="3x:0,0,0,0,0,0"/>
<Option name="offset_unit" type="QString" value="MM"/>
<Option name="outline_color" type="QString" value="35,35,35,255,rgb:0.13725490196078433,0.13725490196078433,0.13725490196078433,1"/>
<Option name="outline_style" type="QString" value="solid"/>
<Option name="outline_width" type="QString" value="0.26"/>
<Option name="outline_width_unit" type="QString" value="MM"/>
<Option name="style" type="QString" value="solid"/>
</Option>
<data_defined_properties>
<Option type="Map">
<Option name="name" type="QString" value=""/>
<Option name="properties"/>
<Option name="type" type="QString" value="collection"/>
</Option>
</data_defined_properties>
</layer>
</symbol>
<symbol frame_rate="10" clip_to_extent="1" is_animated="0" name="1" force_rhr="0" type="fill" alpha="1">
<data_defined_properties>
<Option type="Map">
<Option name="name" type="QString" value=""/>
<Option name="properties"/>
<Option name="type" type="QString" value="collection"/>
</Option>
</data_defined_properties>
<layer enabled="1" class="SimpleFill" locked="0" id="{e0ad06d8-97eb-4592-a841-0b06fa4c1fe0}" pass="0">
<Option type="Map">
<Option name="border_width_map_unit_scale" type="QString" value="3x:0,0,0,0,0,0"/>
<Option name="color" type="QString" value="100,222,94,255,hsv:0.32500000000000001,0.57647058823529407,0.87058823529411766,1"/>
<Option name="joinstyle" type="QString" value="bevel"/>
<Option name="offset" type="QString" value="0,0"/>
<Option name="offset_map_unit_scale" type="QString" value="3x:0,0,0,0,0,0"/>
<Option name="offset_unit" type="QString" value="MM"/>
<Option name="outline_color" type="QString" value="35,35,35,255,rgb:0.13725490196078433,0.13725490196078433,0.13725490196078433,1"/>
<Option name="outline_style" type="QString" value="solid"/>
<Option name="outline_width" type="QString" value="0.26"/>
<Option name="outline_width_unit" type="QString" value="MM"/>
<Option name="style" type="QString" value="solid"/>
</Option>
<data_defined_properties>
<Option type="Map">
<Option name="name" type="QString" value=""/>
<Option name="properties"/>
<Option name="type" type="QString" value="collection"/>
</Option>
</data_defined_properties>
</layer>
</symbol>
</symbols>
<source-symbol>
<symbol frame_rate="10" clip_to_extent="1" is_animated="0" name="0" force_rhr="0" type="fill" alpha="1">
<data_defined_properties>
<Option type="Map">
<Option name="name" type="QString" value=""/>
<Option name="properties"/>
<Option name="type" type="QString" value="collection"/>
</Option>
</data_defined_properties>
<layer enabled="1" class="SimpleFill" locked="0" id="{d5672f9f-8595-4ee2-bce8-db0978ea6f57}" pass="0">
<Option type="Map">
<Option name="border_width_map_unit_scale" type="QString" value="3x:0,0,0,0,0,0"/>
<Option name="color" type="QString" value="125,139,143,255,rgb:0.49019607843137253,0.54509803921568623,0.5607843137254902,1"/>
<Option name="joinstyle" type="QString" value="bevel"/>
<Option name="offset" type="QString" value="0,0"/>
<Option name="offset_map_unit_scale" type="QString" value="3x:0,0,0,0,0,0"/>
<Option name="offset_unit" type="QString" value="MM"/>
<Option name="outline_color" type="QString" value="35,35,35,255,rgb:0.13725490196078433,0.13725490196078433,0.13725490196078433,1"/>
<Option name="outline_style" type="QString" value="solid"/>
<Option name="outline_width" type="QString" value="0.26"/>
<Option name="outline_width_unit" type="QString" value="MM"/>
<Option name="style" type="QString" value="solid"/>
</Option>
<data_defined_properties>
<Option type="Map">
<Option name="name" type="QString" value=""/>
<Option name="properties"/>
<Option name="type" type="QString" value="collection"/>
</Option>
</data_defined_properties>
</layer>
</symbol>
</source-symbol>
<colorramp name="[source]" type="randomcolors">
<Option/>
</colorramp>
<rotation/>
<sizescale/>
<data-defined-properties>
<Option type="Map">
<Option name="name" type="QString" value=""/>
<Option name="properties"/>
<Option name="type" type="QString" value="collection"/>
</Option>
</data-defined-properties>
</renderer-v2>
<selection mode="Default">
<selectionColor invalid="1"/>
<selectionSymbol>
<symbol frame_rate="10" clip_to_extent="1" is_animated="0" name="" force_rhr="0" type="fill" alpha="1">
<data_defined_properties>
<Option type="Map">
<Option name="name" type="QString" value=""/>
<Option name="properties"/>
<Option name="type" type="QString" value="collection"/>
</Option>
</data_defined_properties>
<layer enabled="1" class="SimpleFill" locked="0" id="{9ffb125e-e358-4390-8adb-d8c9c14a882f}" pass="0">
<Option type="Map">
<Option name="border_width_map_unit_scale" type="QString" value="3x:0,0,0,0,0,0"/>
<Option name="color" type="QString" value="0,0,255,255,rgb:0,0,1,1"/>
<Option name="joinstyle" type="QString" value="bevel"/>
<Option name="offset" type="QString" value="0,0"/>
<Option name="offset_map_unit_scale" type="QString" value="3x:0,0,0,0,0,0"/>
<Option name="offset_unit" type="QString" value="MM"/>
<Option name="outline_color" type="QString" value="35,35,35,255,rgb:0.13725490196078433,0.13725490196078433,0.13725490196078433,1"/>
<Option name="outline_style" type="QString" value="solid"/>
<Option name="outline_width" type="QString" value="0.26"/>
<Option name="outline_width_unit" type="QString" value="MM"/>
<Option name="style" type="QString" value="solid"/>
</Option>
<data_defined_properties>
<Option type="Map">
<Option name="name" type="QString" value=""/>
<Option name="properties"/>
<Option name="type" type="QString" value="collection"/>
</Option>
</data_defined_properties>
</layer>
</symbol>
</selectionSymbol>
</selection>
<customproperties>
<Option type="Map">
<Option name="embeddedWidgets/count" type="int" value="0"/>
<Option name="variableNames"/>
<Option name="variableValues"/>
</Option>
</customproperties>
<blendMode>0</blendMode>
<featureBlendMode>0</featureBlendMode>
<layerOpacity>1</layerOpacity>
<geometryOptions geometryPrecision="0" removeDuplicateNodes="0">
<activeChecks/>
<checkConfiguration type="Map">
<Option name="QgsGeometryGapCheck" type="Map">
<Option name="allowedGapsBuffer" type="double" value="0"/>
<Option name="allowedGapsEnabled" type="bool" value="false"/>
<Option name="allowedGapsLayer" type="QString" value=""/>
</Option>
</checkConfiguration>
</geometryOptions>
<legend showLabelLegend="0" type="default-vector"/>
<referencedLayers/>
<fieldConfiguration>
<field name="OBJECTID" configurationFlags="NoFlag">
<editWidget type="TextEdit">
<config>
<Option/>
</config>
</editWidget>
</field>
<field name="FL" configurationFlags="NoFlag">
<editWidget type="TextEdit">
<config>
<Option/>
</config>
</editWidget>
</field>
<field name="FB_BN_KAT" configurationFlags="NoFlag">
<editWidget type="TextEdit">
<config>
<Option/>
</config>
</editWidget>
</field>
<field name="FB_BEZEICH" configurationFlags="NoFlag">
<editWidget type="TextEdit">
<config>
<Option/>
</config>
</editWidget>
</field>
<field name="REG_SAAT" configurationFlags="NoFlag">
<editWidget type="TextEdit">
<config>
<Option/>
</config>
</editWidget>
</field>
<field name="SE_ANNO_CAD_DATA" configurationFlags="NoFlag">
<editWidget type="Binary">
<config>
<Option/>
</config>
</editWidget>
</field>
<field name="Shape__Area" configurationFlags="NoFlag">
<editWidget type="TextEdit">
<config>
<Option/>
</config>
</editWidget>
</field>
<field name="Shape__Length" configurationFlags="NoFlag">
<editWidget type="TextEdit">
<config>
<Option/>
</config>
</editWidget>
</field>
</fieldConfiguration>
<aliases>
<alias index="0" name="" field="OBJECTID"/>
<alias index="1" name="Flaeche_des_Feldblocks_in_ha" field="FL"/>
<alias index="2" name="Kategorie_des_Feldblocks" field="FB_BN_KAT"/>
<alias index="3" name="Bezeichnung_des_Feldblocks" field="FB_BEZEICH"/>
<alias index="4" name="Ursprungsgebiet_UG_Herkunft_des_Regiosaatguts" field="REG_SAAT"/>
<alias index="5" name="" field="SE_ANNO_CAD_DATA"/>
<alias index="6" name="SHAPE.AREA" field="Shape__Area"/>
<alias index="7" name="SHAPE.LEN" field="Shape__Length"/>
</aliases>
<splitPolicies>
<policy policy="Duplicate" field="OBJECTID"/>
<policy policy="Duplicate" field="FL"/>
<policy policy="Duplicate" field="FB_BN_KAT"/>
<policy policy="Duplicate" field="FB_BEZEICH"/>
<policy policy="Duplicate" field="REG_SAAT"/>
<policy policy="Duplicate" field="SE_ANNO_CAD_DATA"/>
<policy policy="Duplicate" field="Shape__Area"/>
<policy policy="Duplicate" field="Shape__Length"/>
</splitPolicies>
<duplicatePolicies>
<policy policy="Duplicate" field="OBJECTID"/>
<policy policy="Duplicate" field="FL"/>
<policy policy="Duplicate" field="FB_BN_KAT"/>
<policy policy="Duplicate" field="FB_BEZEICH"/>
<policy policy="Duplicate" field="REG_SAAT"/>
<policy policy="Duplicate" field="SE_ANNO_CAD_DATA"/>
<policy policy="Duplicate" field="Shape__Area"/>
<policy policy="Duplicate" field="Shape__Length"/>
</duplicatePolicies>
<defaults>
<default field="OBJECTID" expression="" applyOnUpdate="0"/>
<default field="FL" expression="" applyOnUpdate="0"/>
<default field="FB_BN_KAT" expression="" applyOnUpdate="0"/>
<default field="FB_BEZEICH" expression="" applyOnUpdate="0"/>
<default field="REG_SAAT" expression="" applyOnUpdate="0"/>
<default field="SE_ANNO_CAD_DATA" expression="" applyOnUpdate="0"/>
<default field="Shape__Area" expression="" applyOnUpdate="0"/>
<default field="Shape__Length" expression="" applyOnUpdate="0"/>
</defaults>
<constraints>
<constraint constraints="3" unique_strength="1" exp_strength="0" notnull_strength="1" field="OBJECTID"/>
<constraint constraints="0" unique_strength="0" exp_strength="0" notnull_strength="0" field="FL"/>
<constraint constraints="0" unique_strength="0" exp_strength="0" notnull_strength="0" field="FB_BN_KAT"/>
<constraint constraints="0" unique_strength="0" exp_strength="0" notnull_strength="0" field="FB_BEZEICH"/>
<constraint constraints="0" unique_strength="0" exp_strength="0" notnull_strength="0" field="REG_SAAT"/>
<constraint constraints="0" unique_strength="0" exp_strength="0" notnull_strength="0" field="SE_ANNO_CAD_DATA"/>
<constraint constraints="0" unique_strength="0" exp_strength="0" notnull_strength="0" field="Shape__Area"/>
<constraint constraints="0" unique_strength="0" exp_strength="0" notnull_strength="0" field="Shape__Length"/>
</constraints>
<constraintExpressions>
<constraint desc="" exp="" field="OBJECTID"/>
<constraint desc="" exp="" field="FL"/>
<constraint desc="" exp="" field="FB_BN_KAT"/>
<constraint desc="" exp="" field="FB_BEZEICH"/>
<constraint desc="" exp="" field="REG_SAAT"/>
<constraint desc="" exp="" field="SE_ANNO_CAD_DATA"/>
<constraint desc="" exp="" field="Shape__Area"/>
<constraint desc="" exp="" field="Shape__Length"/>
</constraintExpressions>
<expressionfields/>
<attributeactions>
<defaultAction value="{00000000-0000-0000-0000-000000000000}" key="Canvas"/>
</attributeactions>
<attributetableconfig sortOrder="0" actionWidgetStyle="dropDown" sortExpression="">
<columns>
<column name="OBJECTID" width="-1" type="field" hidden="0"/>
<column name="FL" width="-1" type="field" hidden="0"/>
<column name="FB_BN_KAT" width="-1" type="field" hidden="0"/>
<column name="FB_BEZEICH" width="-1" type="field" hidden="0"/>
<column name="REG_SAAT" width="-1" type="field" hidden="0"/>
<column name="SE_ANNO_CAD_DATA" width="-1" type="field" hidden="0"/>
<column name="Shape__Area" width="-1" type="field" hidden="0"/>
<column name="Shape__Length" width="-1" type="field" hidden="0"/>
<column width="-1" type="actions" hidden="1"/>
</columns>
</attributetableconfig>
<conditionalstyles>
<rowstyles/>
<fieldstyles/>
</conditionalstyles>
<storedexpressions/>
<editform tolerant="1"></editform>
<editforminit/>
<editforminitcodesource>0</editforminitcodesource>
<editforminitfilepath></editforminitfilepath>
<editforminitcode><![CDATA[# -*- coding: utf-8 -*-
"""
QGIS-Formulare können eine Python-Funktion haben,, die aufgerufen wird, wenn sich das Formular öffnet
Diese Funktion kann verwendet werden um dem Formular Extralogik hinzuzufügen.
Der Name der Funktion wird im Feld "Python Init-Function" angegeben
Ein Beispiel folgt:
"""
from qgis.PyQt.QtWidgets import QWidget
def my_form_open(dialog, layer, feature):
geom = feature.geometry()
control = dialog.findChild(QWidget, "MyLineEdit")
]]></editforminitcode>
<featformsuppress>0</featformsuppress>
<editorlayout>generatedlayout</editorlayout>
<editable>
<field name="FB_BEZEICH" editable="1"/>
<field name="FB_BN_KAT" editable="1"/>
<field name="FL" editable="1"/>
<field name="OBJECTID" editable="0"/>
<field name="REG_SAAT" editable="1"/>
<field name="SE_ANNO_CAD_DATA" editable="1"/>
<field name="Shape__Area" editable="0"/>
<field name="Shape__Length" editable="0"/>
</editable>
<labelOnTop>
<field name="FB_BEZEICH" labelOnTop="0"/>
<field name="FB_BN_KAT" labelOnTop="0"/>
<field name="FL" labelOnTop="0"/>
<field name="OBJECTID" labelOnTop="0"/>
<field name="REG_SAAT" labelOnTop="0"/>
<field name="SE_ANNO_CAD_DATA" labelOnTop="0"/>
<field name="Shape__Area" labelOnTop="0"/>
<field name="Shape__Length" labelOnTop="0"/>
</labelOnTop>
<reuseLastValue>
<field name="FB_BEZEICH" reuseLastValue="0"/>
<field name="FB_BN_KAT" reuseLastValue="0"/>
<field name="FL" reuseLastValue="0"/>
<field name="OBJECTID" reuseLastValue="0"/>
<field name="REG_SAAT" reuseLastValue="0"/>
<field name="SE_ANNO_CAD_DATA" reuseLastValue="0"/>
<field name="Shape__Area" reuseLastValue="0"/>
<field name="Shape__Length" reuseLastValue="0"/>
</reuseLastValue>
<dataDefinedFieldProperties/>
<widgets/>
<previewExpression>"FB_BN_KAT"</previewExpression>
<mapTip enabled="1"></mapTip>
<layerGeometryType>2</layerGeometryType>
</qgis>
+13
View File
@@ -1,4 +1,17 @@
---
Version 26.6.1-unstable:
- VLN-API zum Laden der Plan41-Maßnahmen integriert
---
Version 26.4.3-unstable:
---
Version 26.4.2-testing:
---
Version 26.04.1-unstable:
---
Version 26.3.3-unstable:
---
Version 26.3.2-unstable:
---
Version 26.3.1-testing:
- unstable als testing veröffentlicht
---
+6 -1
View File
@@ -1,4 +1,6 @@
# sn_plan41/main.py
"""sn_plan41/main.py Einstiegspunkt des sn_plan41 Plugins.
Orchestriert die UI und den Datenabruf für Thematische Linklisten.
"""
from qgis.utils import plugins
from sn_basis.ui.dockmanager import DockManager
@@ -8,6 +10,9 @@ from sn_basis.modules.Pruefmanager import Pruefmanager
class Plan41:
"""Einstiegspunkt des sn_plan41-Plugins.
Verwaltet die DockWidget-Initialisierung und den Datenflusss.
"""
def __init__(self, iface):
self.iface = iface
self.pruefmanager=Pruefmanager(ui_modus="qgis")
+4 -1
View File
@@ -1,4 +1,7 @@
#sn_plan41/modules/listenauswerter.py
"""sn_plan41/modules/listenauswerter.py Validierung von Linklisten.
Prüft Zeilen aus DataDict auf Vollständigkeit und Konsistenz.
"""
from typing import Any, Dict, List, Mapping, Optional, Tuple
from collections.abc import Mapping as _Mapping
# Prüfer-Typen (werden als Instanzen erwartet)
+248
View File
@@ -0,0 +1,248 @@
"""HTTP-Client für die VLN-Manager-API.
API-Vertrag (Stand 2026-06-08):
Basis-URL: https://api.flurneuordnung-sachsen.de/v2
POST /person/login
Body: {"mail": "...", "password": "..."}
Antwort: {"data": {"userauth": "<url_token>", "id": ...}}
Das userauth-Token ist der API-Key (= PERSON.url_token).
GET /tgen -> Teilnehmergemeinschaften (Verfahren)
GET /maps/<layer>/{vkz} -> GeoJSON FeatureCollection (EPSG:25833)
PUT /maps/<layer>/{vkz} <- GeoJSON (ersetzt den Layer dieser VKZ)
Antwort: {"data": {"vkz", "layer", "art", "speicher_id"}, "status": "ok"}
Layer: umringe, p41, st, kas, we
Auth nach Login über den Header "X-API-Key".
Fehlerformat: RFC 7807 (application/problem+json).
Es wird QgsBlockingNetworkRequest verwendet, damit Proxy- und
Zertifikatseinstellungen aus QGIS automatisch greifen.
"""
import json
from sn_basis.functions.qt_wrapper import QUrl, QNetworkRequest
from sn_basis.functions.qgiscore_wrapper import QgsBlockingNetworkRequest
# Fest verdrahtete Produktiv-API des VLN Managers.
DEFAULT_BASE_URL = "https://api.flurneuordnung-sachsen.de/v2"
class ApiError(Exception):
"""Fehler bei der Kommunikation mit der Karten-API."""
class AuthError(ApiError):
"""API-Key fehlt, ist abgelaufen oder hat keine Berechtigung (401/403)."""
class KartenApiClient:
def __init__(self, base_url=DEFAULT_BASE_URL, api_key=None, mail=None):
self.base_url = base_url.rstrip("/")
self.api_key = api_key
self.mail = mail
@property
def is_authenticated(self):
return bool(self.api_key)
def login(self, mail, password):
"""Meldet den Benutzer an. Die API liefert das userauth-Token
(= API-Key), das für alle weiteren Requests verwendet wird."""
data = self._request(
"POST",
"/person/login",
payload={"mail": mail, "password": password},
with_auth=False,
)
payload = data.get("data") if isinstance(data, dict) else None
if not isinstance(payload, dict):
payload = data if isinstance(data, dict) else {}
api_key = payload.get("userauth")
if not api_key:
raise ApiError(
"Login-Antwort enthielt kein userauth-Token. "
"Erhaltene Antwort: %s" % json.dumps(data)[:300]
)
self.api_key = api_key
self.mail = mail
return api_key
def logout(self):
self.api_key = None
self.mail = None
# ------------------------------------------------------------------
# Verfahren (Teilnehmergemeinschaften)
# ------------------------------------------------------------------
def get_verfahren(self):
"""Liste der Verfahren (TGs) als [{"vkz": ..., "name": ...}, ...],
sortiert nach VKZ. Quelle: GET /tgen."""
data = self._request("GET", "/tgen")
rows = None
if isinstance(data, list):
rows = data
elif isinstance(data, dict):
for key in ("data", "rows"):
value = data.get(key)
if isinstance(value, list):
rows = value
break
if isinstance(value, dict) and isinstance(value.get("rows"), list):
rows = value["rows"]
break
if rows is None:
raise ApiError(
"Antwort von /tgen hat ein unerwartetes Format: %s"
% json.dumps(data)[:200]
)
verfahren = []
for row in rows:
if not isinstance(row, dict):
continue
vkz = row.get("vkz") or row.get("VKZ")
name = (
row.get("kurzname")
or row.get("Kurzname")
or row.get("name")
or row.get("Name")
or ""
)
if vkz:
verfahren.append({"vkz": str(vkz), "name": str(name)})
verfahren.sort(key=lambda v: v["vkz"])
return verfahren
# ------------------------------------------------------------------
# Karten-Layer
# ------------------------------------------------------------------
def load_layer_complete(self, layer_key, vkz, page_size=2000):
"""Lädt ALLE Objekte eines Layers für eine VKZ aus KARTE_OBJEKT.
Nutzt den Listen-Endpunkt /maps/<layer>?vkz=… mit limit/offset-Paging,
bis keine weitere Seite mehr kommt."""
from urllib.parse import quote
features = []
offset = 0
while True:
data = self._request(
"GET",
"/maps/%s?vkz=%s&limit=%d&offset=%d"
% (quote(str(layer_key)), quote(str(vkz)), page_size, offset),
)
if not isinstance(data, dict) or data.get("type") != "FeatureCollection":
raise ApiError(
"Antwort von /maps/%s ist keine GeoJSON FeatureCollection."
% layer_key
)
page = data.get("features", [])
features.extend(page)
if len(page) < page_size:
break
offset += page_size
return {"type": "FeatureCollection", "features": features}
def load_feature_collection(self, path):
"""Lädt einen Layer als GeoJSON FeatureCollection (dict)."""
data = self._request("GET", path)
if isinstance(data, dict):
if data.get("type") == "FeatureCollection":
return data
inner = data.get("data")
if isinstance(inner, dict) and inner.get("type") == "FeatureCollection":
return inner
raise ApiError(
"Antwort von %s ist keine GeoJSON FeatureCollection." % path
)
def save_feature_collection(self, path, feature_collection):
"""Schreibt eine GeoJSON FeatureCollection zurück an die API
(PUT ersetzt den kompletten Layer der jeweiligen VKZ)."""
return self._request("PUT", path, payload=feature_collection)
# ------------------------------------------------------------------
# Intern
# ------------------------------------------------------------------
def _request(self, method, path, payload=None, with_auth=True):
if with_auth and not self.is_authenticated:
raise AuthError("Nicht angemeldet — bitte zuerst einloggen.")
request = QNetworkRequest(QUrl(self.base_url + path))
request.setHeader(
QNetworkRequest.KnownHeaders.ContentTypeHeader, "application/json"
)
request.setRawHeader(b"Accept", b"application/json")
if with_auth:
request.setRawHeader(b"X-API-Key", self.api_key.encode("utf-8"))
body = b""
if payload is not None:
body = json.dumps(payload).encode("utf-8")
blocking = QgsBlockingNetworkRequest()
if method == "GET":
error = blocking.get(request)
elif method == "POST":
error = blocking.post(request, body)
elif method == "PUT":
error = blocking.put(request, body)
else:
raise ApiError("Nicht unterstützte HTTP-Methode: %s" % method)
reply = blocking.reply()
content = bytes(reply.content())
status = reply.attribute(
QNetworkRequest.Attribute.HttpStatusCodeAttribute
)
status = int(status) if status is not None else None
if status in (401, 403):
raise AuthError(
"Keine Berechtigung für %s %s (HTTP %s)%s"
% (method, path, status, self._error_detail(content))
)
if error != QgsBlockingNetworkRequest.NoError:
raise ApiError(
"%s %s fehlgeschlagen: %s%s"
% (method, path, blocking.errorMessage(), self._error_detail(content))
)
if status is not None and status >= 400:
raise ApiError(
"%s %s lieferte HTTP %s%s"
% (method, path, status, self._error_detail(content))
)
if not content:
return None
try:
return json.loads(content.decode("utf-8"))
except ValueError:
raise ApiError(
"Antwort von %s ist kein gültiges JSON." % path
)
@staticmethod
def _error_detail(content):
"""Liest title/detail aus einer RFC-7807-Fehlerantwort."""
if not content:
return ""
try:
problem = json.loads(content.decode("utf-8"))
parts = [
str(problem[k]) for k in ("title", "detail") if problem.get(k)
]
if parts:
return "" + ": ".join(parts)
except (ValueError, AttributeError):
pass
return "" + content[:300].decode("utf-8", "replace")
+378
View File
@@ -0,0 +1,378 @@
"""
sn_plan41/modules/vln_api_logic.py Fachlogik für die VLN-API-Integration in Tab A.
Kapselt:
- Anmeldung / Abmeldung (KartenApiClient aus vln_karten)
- Persistierung des API-Keys in QSettings
- Verfahrensliste laden (GET /tgen)
- Persistierung der VKZ-Auswahl in der Projektdatei
- Plan 41 laden (2 Layer + Stile aus sn_plan41/assets/)
- Aktiven Layer hochladen
Voraussetzung: Das Plugin `vln_karten` muss installiert sein.
Wenn nicht vorhanden, liefert :attr:`is_available` False; die UI
kann dann einen entsprechenden Hinweis anzeigen.
Sitzungsablauf bei AuthError:
- :meth:`handle_session_expired` aufrufen → API-Key löschen + logout
- In der UI danach :meth:`_update_vln_ui_state` aufrufen und
QMessageBox.warning anzeigen. Kein automatischer Login-Dialog.
"""
from __future__ import annotations
from typing import Optional
from sn_basis.functions.qt_wrapper import QSettings
from sn_basis.functions.qgiscore_wrapper import QgsProject
from sn_basis.functions.sys_wrapper import get_plugin_root, join_path
from sn_basis.functions.ly_style_wrapper import apply_style_from_path
# Lokale API-Module — fallenübrig, sobald QGIS verfügbar ist.
# In der reinen Python-Testumgebung (kein qgis-Paket) schlagen die
# qgis-Imports in den Untermodulen fehl; daher der try/except-Guard.
try:
from sn_plan41.modules.vln_api_client import KartenApiClient, ApiError, AuthError
from sn_plan41.modules.vln_layer_manager import (
feature_collection_to_layers,
plugin_layers,
layers_to_feature_collection,
layer_api_path,
PROP_DATASET,
PROP_VERFAHREN,
)
VLN_KARTEN_AVAILABLE = True
except (ImportError, ModuleNotFoundError):
KartenApiClient = None # type: ignore[assignment,misc]
ApiError = Exception # type: ignore[assignment,misc]
AuthError = Exception # type: ignore[assignment,misc]
VLN_KARTEN_AVAILABLE = False
# Geometrietyp-Konstanten (QGIS intern: 1 = Linie, 2 = Fläche)
try:
from qgis.core import Qgis as _Qgis
_GEOM_LINE = _Qgis.GeometryType.Line
_GEOM_POLYGON = _Qgis.GeometryType.Polygon
except (ImportError, AttributeError):
try:
from qgis.core import QgsWkbTypes as _QgsWkbTypes
_GEOM_LINE = _QgsWkbTypes.LineGeometry
_GEOM_POLYGON = _QgsWkbTypes.PolygonGeometry
except (ImportError, AttributeError):
_GEOM_LINE = 1
_GEOM_POLYGON = 2
# Konstanten
SETTINGS_GROUP = "vln_karten"
PROJECT_SCOPE = "vln_karten"
PROJECT_KEY_VKZ = "/vkz"
P41_DATASET_KEY = "p41"
P41_LABEL = "Plan 41 (Wege- und Gewässerplan)"
P41_PATH_TEMPLATE = "/maps/p41/{vkz}"
P41_GEOMETRY = "MultiPolygon"
STYLE_FLAECHE = "QGIS_P41_API_Layer_flaeche.qml"
STYLE_LINIE = "QGIS_P41_API_Layer_Linie.qml"
class VlnApiLogic:
"""
Kapselt die VLN-API-Fachlogik für den Plan41-Tab.
Alle Methoden, die Netzwerkkommunikation erfordern, können
``ApiError`` oder ``AuthError`` werfen die UI ist für die
Fehlerdarstellung zuständig.
"""
def __init__(self, pruefmanager=None) -> None:
self.pruefmanager = pruefmanager
self._client: Optional[object] = None # KartenApiClient | None
# API-Client aus gespeicherten Credentials initialisieren
if VLN_KARTEN_AVAILABLE:
api_key, mail = self.load_stored_credentials()
if api_key:
self._client = KartenApiClient(api_key=api_key, mail=mail)
# ------------------------------------------------------------------
# Verfügbarkeit
# ------------------------------------------------------------------
@staticmethod
def is_available() -> bool:
"""True, wenn die lokalen API-Module geladen werden konnten
(erfordert eine QGIS-Laufzeitumgebung)."""
return VLN_KARTEN_AVAILABLE
# ------------------------------------------------------------------
# Authentifizierungsstatus
# ------------------------------------------------------------------
@property
def is_authenticated(self) -> bool:
"""True, wenn ein gültiger API-Key vorhanden ist."""
if self._client is None:
return False
return bool(getattr(self._client, "is_authenticated", False))
@property
def mail(self) -> Optional[str]:
"""E-Mail-Adresse des angemeldeten Benutzers oder None."""
if self._client is None:
return None
return getattr(self._client, "mail", None)
# ------------------------------------------------------------------
# QSettings: API-Key persistieren
# ------------------------------------------------------------------
def load_stored_credentials(self) -> tuple:
"""Liest API-Key und Mail aus QSettings.
Gibt ``(api_key, mail)`` zurück leere Strings wenn nicht vorhanden.
"""
settings = QSettings()
settings.beginGroup(SETTINGS_GROUP)
api_key = settings.value("api_key", "")
mail = settings.value("mail", "")
settings.endGroup()
return api_key or None, mail or None
def save_api_key(self, api_key: str, mail: str) -> None:
"""Speichert API-Key und Mail in QSettings."""
settings = QSettings()
settings.beginGroup(SETTINGS_GROUP)
settings.setValue("api_key", api_key)
settings.setValue("mail", mail or "")
settings.endGroup()
def clear_api_key(self) -> None:
"""Entfernt API-Key aus QSettings."""
settings = QSettings()
settings.beginGroup(SETTINGS_GROUP)
settings.remove("api_key")
settings.endGroup()
# ------------------------------------------------------------------
# Login / Logout
# ------------------------------------------------------------------
def login(self, mail: str, password: str) -> None:
"""
Meldet den Benutzer an und speichert den API-Key.
:raises ApiError: Bei ungültigen Zugangsdaten oder Netzwerkproblem.
:raises RuntimeError: Wenn QGIS nicht verfügbar ist (kein qgis-Paket).
"""
if not VLN_KARTEN_AVAILABLE:
raise RuntimeError(
"VLN-API-Module nicht verfügbar (QGIS-Laufzeitumgebung benötigt)."
)
client = KartenApiClient()
client.login(mail, password) # wirft ApiError bei Fehler
self._client = client
self.save_api_key(client.api_key, mail)
def logout(self) -> None:
"""Meldet den Benutzer ab (lokal, kein API-Aufruf)."""
if self._client is not None:
getattr(self._client, "logout", lambda: None)()
self._client = None
def handle_session_expired(self) -> None:
"""
Behandelt einen abgelaufenen API-Key:
entfernt ihn aus QSettings und setzt den Client zurück.
"""
self.clear_api_key()
self.logout()
# ------------------------------------------------------------------
# Verfahrensliste
# ------------------------------------------------------------------
def get_verfahren(self) -> list:
"""
Lädt alle Verfahren (TGs) vom Server.
:returns: Sortierte Liste von ``{"vkz": ..., "name": ...}``-Dicts.
:raises AuthError: Wenn nicht angemeldet oder Session abgelaufen.
:raises ApiError: Bei sonstigem Netzwerkfehler.
"""
if self._client is None:
raise AuthError("Nicht angemeldet.")
return self._client.get_verfahren()
# ------------------------------------------------------------------
# VKZ-Persistenz in Projektdatei
# ------------------------------------------------------------------
def load_stored_vkz(self) -> Optional[str]:
"""Liest die zuletzt gewählte VKZ aus der Projektdatei."""
try:
vkz, _ok = QgsProject.instance().readEntry(
PROJECT_SCOPE, PROJECT_KEY_VKZ, ""
)
return vkz if vkz else None
except Exception:
return None
def save_vkz(self, vkz: Optional[str]) -> None:
"""Schreibt die gewählte VKZ in die Projektdatei."""
if not vkz:
return
try:
QgsProject.instance().writeEntry(PROJECT_SCOPE, PROJECT_KEY_VKZ, vkz)
except Exception:
pass
# ------------------------------------------------------------------
# Plan 41 laden
# ------------------------------------------------------------------
def get_p41_layers(self, vkz: str) -> list:
"""Gibt alle bereits geladenen P41-Layer für diese VKZ zurück."""
return plugin_layers(P41_DATASET_KEY, vkz)
def remove_p41_layers(self, vkz: str) -> None:
"""Entfernt alle P41-Layer dieser VKZ aus dem Projekt."""
existing = plugin_layers(P41_DATASET_KEY, vkz)
if existing:
QgsProject.instance().removeMapLayers([l.id() for l in existing])
def load_p41(self, vkz: str) -> list:
"""
Lädt den Plan-41-Datensatz für eine VKZ vom Server und legt
Memory-Layer im Projekt an. Auf die entstandenen Layer werden
die passenden QML-Stile aus ``sn_plan41/assets/`` angewendet.
:returns: Liste der erzeugten ``QgsVectorLayer``.
:raises AuthError: Wenn nicht angemeldet oder Session abgelaufen.
:raises ApiError: Bei sonstigem Netzwerkfehler.
:raises RuntimeError: Wenn QGIS nicht verfügbar ist.
"""
if not VLN_KARTEN_AVAILABLE:
raise RuntimeError(
"VLN-API-Module nicht verfügbar (QGIS-Laufzeitumgebung benötigt)."
)
if self._client is None:
raise AuthError("Nicht angemeldet.")
path = P41_PATH_TEMPLATE.format(vkz=vkz)
feature_collection = self._client.load_layer_complete(
P41_DATASET_KEY, vkz
)
base_name = "%s %s" % (P41_LABEL, vkz)
layers = feature_collection_to_layers(
feature_collection,
base_name,
P41_GEOMETRY,
P41_DATASET_KEY,
vkz,
path,
)
self._apply_p41_styles(layers)
return layers
def _apply_p41_styles(self, layers: list) -> None:
"""Wendet den passenden QML-Stil auf jeden Layer an."""
assets_dir = join_path(get_plugin_root(), "sn_plan41", "assets")
for layer in layers:
try:
gtype = layer.geometryType()
except Exception:
continue
if gtype == _GEOM_POLYGON:
style_file = STYLE_FLAECHE
elif gtype == _GEOM_LINE:
style_file = STYLE_LINIE
else:
continue # Punkt- und None-Layer erhalten keinen Stil
style_path = join_path(assets_dir, style_file)
apply_style_from_path(layer, style_path)
# ------------------------------------------------------------------
# Upload
# ------------------------------------------------------------------
def upload_active_layer(self, active_layer) -> tuple:
"""
Lädt alle Teil-Layer des aktiven Layers zum Server hoch.
:param active_layer: Aktiver ``QgsVectorLayer`` (aus ``iface.activeLayer()``).
:returns: ``(success: bool, message: str)``
:raises AuthError: Wenn Session abgelaufen.
:raises ApiError: Bei Netzwerkfehler.
"""
if not VLN_KARTEN_AVAILABLE:
return False, (
"VLN-API-Module nicht verfügbar (QGIS-Laufzeitumgebung benötigt)."
)
if self._client is None:
raise AuthError("Nicht angemeldet.")
path = layer_api_path(active_layer) if active_layer else None
if not path:
return (
False,
"Der aktive Layer wurde nicht über 'vln_karten' geladen. "
"Bitte einen Plan41-Layer aus dem Projekt auswählen.",
)
dataset_key = active_layer.customProperty(PROP_DATASET)
vkz = active_layer.customProperty(PROP_VERFAHREN)
siblings = plugin_layers(dataset_key, vkz)
for layer in siblings:
if layer.isEditable() and not layer.commitChanges():
return (
False,
"Die Bearbeitungssitzung von '%s' konnte nicht "
"gespeichert werden." % layer.name(),
)
feature_collection = layers_to_feature_collection(siblings)
self._client.save_feature_collection(path, feature_collection)
total = sum(layer.featureCount() for layer in siblings)
return (
True,
"%d Objekte aus %d Layer(n) erfolgreich hochgeladen."
% (total, len(siblings)),
)
def upload_summary(self, active_layer) -> Optional[dict]:
"""
Gibt eine Zusammenfassung der zu hochladenden Layer zurück
(für den Bestätigungs-Dialog in der UI), ohne den Upload
tatsächlich auszuführen.
:returns: Dict mit ``dataset_label``, ``vkz``, ``siblings``
(Layer-Liste), ``total`` (Objektanzahl), ``listing`` (str)
oder ``None`` wenn kein gültiger Layer.
"""
if not VLN_KARTEN_AVAILABLE or active_layer is None:
return None
path = layer_api_path(active_layer)
if not path:
return None
dataset_key = active_layer.customProperty(PROP_DATASET)
vkz = active_layer.customProperty(PROP_VERFAHREN)
siblings = plugin_layers(dataset_key, vkz)
total = sum(l.featureCount() for l in siblings)
listing = "\n".join(
"%s (%d Objekte)" % (l.name(), l.featureCount())
for l in siblings
)
return {
"dataset_label": P41_LABEL if dataset_key == P41_DATASET_KEY else dataset_key,
"vkz": vkz,
"siblings": siblings,
"total": total,
"listing": listing,
}
+177
View File
@@ -0,0 +1,177 @@
"""Konvertierung GeoJSON <-> QGIS-Layer für die VLN-API.
Lokale Kopie des Layer-Managers aus dem vln_karten-Plugin — sn_plan41
benötigt kein separat installiertes vln_karten-Plugin mehr.
Die API liefert je Layer (z.B. Plan 41) gemischte Geometrietypen in einer
FeatureCollection: Punkte, Linien, Polygone sowie deren Multi-Varianten.
QGIS-Memory-Layer können nur einen Geometrietyp halten — beim Laden wird
deshalb nach Geometrie-Familie (Punkte/Linien/Flächen) in bis zu drei
Layer gesplittet; Single-Geometrien werden zu Multi befördert.
Beim Hochladen müssen alle Teil-Layer desselben Datensatzes wieder zu
EINER FeatureCollection vereint werden, weil der PUT der API den
kompletten Layer-Bestand der VKZ ersetzt.
Custom-Properties an Layern (kompatibel mit vln_karten, falls beide
Plugins gleichzeitig installiert sind):
vln_karten/dataset — z.B. "p41"
vln_karten/verfahren — VKZ-Nummer
vln_karten/api_path — API-Pfad für Upload
"""
import json
from sn_basis.functions.qgiscore_wrapper import (
QgsJsonExporter,
QgsJsonUtils,
QgsProject,
QgsVectorLayer,
GEOM_POINT,
GEOM_LINE,
GEOM_POLYGON,
)
_GEOM_POINT = GEOM_POINT
_GEOM_LINE = GEOM_LINE
_GEOM_POLYGON = GEOM_POLYGON
# Die VLN-API liefert Koordinaten in ETRS89 / UTM Zone 33 (EPSG:25833).
GEOJSON_CRS = "EPSG:25833"
# Custom-Property-Schlüssel — identisch mit vln_karten für Kompatibilität.
PROP_DATASET = "vln_karten/dataset"
PROP_VERFAHREN = "vln_karten/verfahren"
PROP_PATH = "vln_karten/api_path"
# Geometrie-Familie → (Memory-Provider-Typ, Namenszusatz).
# Reihenfolge = Lade-Reihenfolge: Flächen zuerst, damit Punkte im
# Layerbaum oben landen und nicht verdeckt werden.
_FAMILIES = (
("polygon", "MultiPolygon", "Flächen"),
("line", "MultiLineString", "Linien"),
("point", "MultiPoint", "Punkte"),
("none", "None", "ohne Geometrie"),
)
def _family(feature):
"""Geometrie-Familie eines Features. Unbekannte Typen (z.B.
GeometryCollection) landen bei 'none'."""
if not feature.hasGeometry() or feature.geometry().isNull():
return "none"
gtype = feature.geometry().type()
if gtype == _GEOM_POINT:
return "point"
if gtype == _GEOM_LINE:
return "line"
if gtype == _GEOM_POLYGON:
return "polygon"
return "none"
def memory_layer_from_features(
uri_type, name, fields, features, dataset_key, verfahren_nr, api_path, promote=True
):
"""Baut einen Memory-Layer aus fertigen QgsFeatures, setzt die
Plugin-Custom-Properties und hängt ihn ins Projekt."""
uri = uri_type if uri_type == "None" else "%s?crs=%s" % (uri_type, GEOJSON_CRS)
layer = QgsVectorLayer(uri, name, "memory")
if not layer.isValid():
raise RuntimeError("Memory-Layer '%s' konnte nicht erzeugt werden." % name)
provider = layer.dataProvider()
provider.addAttributes(fields.toList())
layer.updateFields()
prepared = []
for feature in features:
geometry = feature.geometry()
if promote and not geometry.isNull() and not geometry.isMultipart():
geometry.convertToMultiType()
feature.setGeometry(geometry)
prepared.append(feature)
provider.addFeatures(prepared)
layer.updateExtents()
layer.setCustomProperty(PROP_DATASET, dataset_key)
layer.setCustomProperty(PROP_VERFAHREN, verfahren_nr)
layer.setCustomProperty(PROP_PATH, api_path)
return layer
def feature_collection_to_layers(
feature_collection, base_name, default_geometry, dataset_key, verfahren_nr, api_path
):
"""Erzeugt aus einer GeoJSON FeatureCollection je vorkommender
Geometrie-Familie einen Memory-Layer und hängt sie ins Projekt.
Liefert die Liste der erzeugten Layer."""
text = json.dumps(feature_collection)
fields = QgsJsonUtils.stringToFields(text)
features = QgsJsonUtils.stringToFeatureList(text, fields)
groups = {}
for feature in features:
groups.setdefault(_family(feature), []).append(feature)
layers = []
multiple = len(groups) > 1
def make_layer(uri_type, name, group_features, promote):
layers.append(
memory_layer_from_features(
uri_type, name, fields, group_features,
dataset_key, verfahren_nr, api_path, promote=promote,
)
)
if not groups:
# Leerer Datensatz: ein leerer Layer im Default-Typ, damit der
# Nutzer digitalisieren und hochladen kann.
make_layer(default_geometry, base_name, [], promote=False)
else:
for family, uri_type, suffix in _FAMILIES:
if family not in groups:
continue
name = "%s%s" % (base_name, suffix) if multiple else base_name
make_layer(uri_type, name, groups[family], promote=(family != "none"))
QgsProject.instance().addMapLayers(layers)
return layers
def plugin_layers(dataset_key, verfahren_nr):
"""Alle Layer im Projekt, die zu diesem Datensatz und dieser VKZ
gehören (z.B. die Punkte-/Linien-/Flächen-Teil-Layer von Plan 41)."""
result = []
for layer in QgsProject.instance().mapLayers().values():
if (
isinstance(layer, QgsVectorLayer)
and layer.customProperty(PROP_DATASET) == dataset_key
and str(layer.customProperty(PROP_VERFAHREN)) == str(verfahren_nr)
):
result.append(layer)
return result
def layers_to_feature_collection(layers):
"""Vereint die Features mehrerer Layer zu EINER GeoJSON
FeatureCollection (für den PUT, der den Serverbestand ersetzt).
Keine Transformation nach WGS84: Die API erwartet die Koordinaten im
selben CRS, in dem sie sie liefert (EPSG:25833)."""
merged = []
for layer in layers:
exporter = QgsJsonExporter(layer)
exporter.setSourceCrs(layer.crs())
exporter.setTransformGeometries(False)
collection = json.loads(
exporter.exportFeatures(list(layer.getFeatures()))
)
merged.extend(collection.get("features", []))
return {"type": "FeatureCollection", "features": merged}
def layer_api_path(layer):
"""API-Pfad, unter dem dieser Layer geladen wurde — oder None,
wenn der Layer nicht von diesem Plugin stammt."""
if not isinstance(layer, QgsVectorLayer):
return None
return layer.customProperty(PROP_PATH) or None
+3 -1
View File
@@ -1 +1,3 @@
#Testordner
"""sn_plan41/tests Test-Suite für das sn_plan41 Plugin.
Enthält Unit-Tests und Integrationstests für Tab-Logik und Datengrabber.
"""
+14
View File
@@ -5,6 +5,7 @@ Zentraler Test-Runner für sn_plan41.
Wrapper-konform, QGIS-unabhängig, CI- und IDE-fähig.
"""
import io
import unittest
import datetime
import inspect
@@ -12,6 +13,19 @@ import os
import sys
from pathlib import Path
# Stdout auf UTF-8 umstellen, damit Emoji-Print-Statements in
# qt_wrapper.py (Mock-Modus) auf Windows-Konsolen (CP1252) nicht zu
# UnicodeEncodeError führen.
if hasattr(sys.stdout, "reconfigure"):
try:
sys.stdout.reconfigure(encoding="utf-8", errors="replace")
except Exception:
pass
elif hasattr(sys.stdout, "buffer"):
sys.stdout = io.TextIOWrapper(
sys.stdout.buffer, encoding="utf-8", errors="replace"
)
# ---------------------------------------------------------
# Plugin-Roots bestimmen
+84
View File
@@ -0,0 +1,84 @@
import unittest
from typing import Any
from sn_basis.modules.pruef_ergebnis import pruef_ergebnis
from sn_plan41.modules.listenauswerter import Listenauswerter
class _DummyPruefmanager:
def __init__(self) -> None:
self.seen = []
def verarbeite(self, ergebnis: Any):
self.seen.append(ergebnis)
return ergebnis
class _DummyStilPruefer:
def __init__(self, ok: bool = True) -> None:
self.ok = ok
def pruefe(self, _path: str) -> pruef_ergebnis:
if self.ok:
return pruef_ergebnis(ok=True, meldung="ok", aktion="ok", kontext=None)
return pruef_ergebnis(ok=False, meldung="stil fehler", aktion="falsche_endung", kontext=None)
class TestListenauswerter(unittest.TestCase):
def test_validate_rows_accepts_valid_row_and_normalizes_provider(self):
manager = _DummyPruefmanager()
validator = Listenauswerter(manager, _DummyStilPruefer(ok=True))
data = {"rows": [{"ident": "A1", "Inhalt": "Test", "Link": "http://x", "Provider": "wfs"}]}
validated, processed = validator.validate_rows(data)
self.assertEqual(len(validated["rows"]), 1)
self.assertEqual(validated["rows"][0]["Provider"], "WFS")
self.assertEqual(processed, [])
def test_validate_rows_rejects_missing_required_fields(self):
manager = _DummyPruefmanager()
validator = Listenauswerter(manager, _DummyStilPruefer(ok=True))
data = {"rows": [{"ident": "", "Link": "", "Provider": ""}]}
validated, processed = validator.validate_rows(data)
self.assertEqual(validated["rows"], [])
self.assertEqual(len(processed), 1)
self.assertEqual(processed[0].aktion, "pflichtfelder_fehlen")
def test_validate_rows_sets_stildatei_none_on_style_failure(self):
manager = _DummyPruefmanager()
validator = Listenauswerter(manager, _DummyStilPruefer(ok=False))
data = {
"rows": [
{
"ident": "A1",
"Inhalt": "Thema",
"Link": "http://x",
"Provider": "WMS",
"Stildatei": "broken.qml",
}
]
}
validated, processed = validator.validate_rows(data)
self.assertEqual(len(validated["rows"]), 1)
self.assertIsNone(validated["rows"][0]["stildatei"])
self.assertEqual(len(processed), 1)
self.assertEqual(processed[0].aktion, "falsche_endung")
def test_validate_rows_handles_non_mapping_rows_edge_case(self):
manager = _DummyPruefmanager()
validator = Listenauswerter(manager, _DummyStilPruefer(ok=True))
validated, processed = validator.validate_rows({"rows": ["invalid", 123, None]})
self.assertEqual(validated, {"rows": []})
self.assertEqual(processed, [])
if __name__ == "__main__":
unittest.main()
+78 -121
View File
@@ -1,152 +1,109 @@
import unittest
from pathlib import Path
from tempfile import TemporaryDirectory
from typing import Any, cast
from unittest.mock import patch
from sn_plan41.ui.tab_a_logic import TabALogic # type: ignore
from sn_basis.functions.variable_wrapper import get_variable # type: ignore
from sn_basis.functions.sys_wrapper import file_exists # type: ignore
from sn_basis.modules.pruef_ergebnis import pruef_ergebnis
from sn_basis.functions.variable_wrapper import get_variable
from sn_plan41.ui.tab_a_logic import TabALogic
class _DummyPruefmanager:
def verarbeite(self, ergebnis):
return ergebnis
class TestTabALogic(unittest.TestCase):
# -----------------------------------------------------
# 1. Verfahrens-DB setzen und laden
# -----------------------------------------------------
def test_verfahrens_db_set_and_load(self):
logic = TabALogic()
def _make_logic(self) -> TabALogic:
return TabALogic(
pruefmanager=cast(Any, _DummyPruefmanager()),
link_pruefer=cast(Any, object()),
stil_pruefer=cast(Any, object()),
)
with TemporaryDirectory() as tmp:
db_path = Path(tmp) / "test.gpkg"
db_path.write_text("")
def test_verfahrens_db_set_and_load_roundtrip(self):
logic = self._make_logic()
logic.set_verfahrens_db("C:/tmp/v_db.gpkg")
self.assertEqual(logic.load_verfahrens_db(), "C:/tmp/v_db.gpkg")
logic.set_verfahrens_db(str(db_path))
stored = get_variable("verfahrens_db", scope="project")
self.assertEqual(stored, str(db_path))
loaded = logic.load_verfahrens_db()
self.assertEqual(loaded, str(db_path))
# -----------------------------------------------------
# 2. Verfahrens-DB löschen
# -----------------------------------------------------
def test_verfahrens_db_clear(self):
logic = TabALogic()
logic = self._make_logic()
logic.set_verfahrens_db(None)
self.assertEqual(get_variable("verfahrens_db", scope="project"), "")
stored = get_variable("verfahrens_db", scope="project")
self.assertEqual(stored, "")
# -----------------------------------------------------
# 3. Neue Verfahrens-DB anlegen
# -----------------------------------------------------
def test_create_new_verfahrens_db(self):
logic = TabALogic()
with TemporaryDirectory() as tmp:
db_path = Path(tmp) / "neu.gpkg"
result = logic.create_new_verfahrens_db(str(db_path))
self.assertTrue(result)
self.assertTrue(file_exists(db_path))
stored = get_variable("verfahrens_db", scope="project")
self.assertEqual(stored, str(db_path))
def test_create_new_verfahrens_db_with_none_path(self):
logic = TabALogic()
result = logic.create_new_verfahrens_db(None)
self.assertFalse(result)
# -----------------------------------------------------
# 4. Linkliste setzen und laden
# -----------------------------------------------------
def test_linkliste_set_and_load(self):
logic = TabALogic()
def test_linkliste_set_and_load_existing_path(self):
logic = self._make_logic()
with TemporaryDirectory() as tmp:
link_path = Path(tmp) / "links.xlsx"
link_path.write_text("dummy")
link_path.write_text("x", encoding="utf-8")
logic.set_linkliste(str(link_path))
self.assertEqual(logic.load_linkliste(), str(link_path))
stored = get_variable("linkliste", scope="project")
self.assertEqual(stored, str(link_path))
def test_linkliste_load_returns_none_when_file_missing(self):
logic = self._make_logic()
logic.set_linkliste("C:/tmp/missing.xlsx")
self.assertIsNone(logic.load_linkliste())
loaded = logic.load_linkliste()
self.assertEqual(loaded, str(link_path))
@patch("sn_plan41.ui.tab_a_logic.get_plugin_root", return_value="C:/plugins")
@patch("sn_plan41.ui.tab_a_logic.join_path", return_value="C:/plugins/sn_plan41/assets/Linkliste.xlsx")
def test_resolve_linkliste_empty_uses_standard_and_persists(self, _mock_join_path, _mock_root):
logic = self._make_logic()
resolved = logic._resolve_linkliste(None)
# -----------------------------------------------------
# 5. Linkliste löschen
# -----------------------------------------------------
def test_linkliste_clear(self):
logic = TabALogic()
self.assertEqual(resolved, "C:/plugins/sn_plan41/assets/Linkliste.xlsx")
self.assertEqual(get_variable("linkliste", scope="project"), "C:/plugins/sn_plan41/assets/Linkliste.xlsx")
logic.set_linkliste(None)
@patch("sn_plan41.ui.tab_a_logic.Dateipruefer")
def test_resolve_linkliste_returns_none_when_pruefmanager_rejects(self, mock_dateipruefer):
logic = self._make_logic()
mock_dateipruefer.return_value.pruefe.return_value = pruef_ergebnis(
ok=False,
meldung="Ungültig",
aktion="datei_nicht_gefunden",
kontext=None,
)
stored = get_variable("linkliste", scope="project")
self.assertEqual(stored, "")
resolved = logic._resolve_linkliste("C:/tmp/missing.xlsx")
self.assertIsNone(resolved)
# -----------------------------------------------------
# 6. Layer-ID speichern
# -----------------------------------------------------
def test_verfahrensgebiet_layer_id_storage(self):
logic = TabALogic()
def test_resolve_raumfilter_without_filter_returns_none(self):
logic = self._make_logic()
result = logic._resolve_raumfilter("ohne", "C:/tmp/v_db.gpkg")
self.assertIsNone(result)
class MockLayer:
def id(self):
return "layer-123"
@patch.object(TabALogic, "_get_verfahrensgebiet_layer", return_value="layer_obj")
def test_resolve_raumfilter_verfahrensgebiet_uses_layer_lookup(self, mock_get_layer):
logic = self._make_logic()
result = logic._resolve_raumfilter("Verfahrensgebiet", "C:/tmp/v_db.gpkg")
logic.save_verfahrensgebiet_layer(MockLayer())
self.assertEqual(result, "layer_obj")
mock_get_layer.assert_called_once()
stored = get_variable("verfahrensgebiet_layer", scope="project")
self.assertEqual(stored, "layer-123")
def test_extract_datenabruf_error_maps_merges_reason_maps(self):
logic = self._make_logic()
results = [
pruef_ergebnis(
ok=False,
meldung="Head failed",
aktion="url_nicht_erreichbar",
kontext={"ident": "A1", "thema": "Dienst A", "error": "Timeout"},
),
pruef_ergebnis(
ok=False,
meldung="Fetch failed",
aktion="datenabruf",
kontext={"fehler": {"Dienst B": "HTTP 500", "Dienst A": "ignored"}},
),
]
# -----------------------------------------------------
# 7. Ungültiger Layer wird ignoriert
# -----------------------------------------------------
def test_invalid_layer_is_rejected(self):
logic = TabALogic()
merged = logic._extract_datenabruf_error_maps(results)
class InvalidLayer:
pass
logic.save_verfahrensgebiet_layer(InvalidLayer())
stored = get_variable("verfahrensgebiet_layer", scope="project")
self.assertEqual(stored, "")
#-----------------------------------------------------
# 8. Layer-ID wirft Exception
#----------------------------------------------------
def test_layer_id_raises_exception(self):
logic = TabALogic()
class BadLayer:
def id(self):
raise RuntimeError("boom")
logic.save_verfahrensgebiet_layer(BadLayer())
stored = get_variable("verfahrensgebiet_layer", scope="project")
self.assertEqual(stored, "")
# -----------------------------------------------------
# 11. Layer ID wird leer zurückgegeben
# -----------------------------------------------------
def test_layer_id_returns_empty(self):
logic = TabALogic()
class EmptyLayer:
def id(self):
return ""
logic.save_verfahrensgebiet_layer(EmptyLayer())
stored = get_variable("verfahrensgebiet_layer", scope="project")
self.assertEqual(stored, "")
self.assertEqual(merged["by_ident"]["A1"], "Timeout")
self.assertEqual(merged["by_thema"]["Dienst A"], "Timeout")
self.assertEqual(merged["by_thema"]["Dienst B"], "HTTP 500")
if __name__ == "__main__":
+111
View File
@@ -0,0 +1,111 @@
import unittest
from unittest.mock import patch
from typing import Any, cast
from sn_plan41.ui.tab_a_logic import TabALogic
class _DummyPruefmanager:
def __init__(self) -> None:
self.hinweise: list[tuple[str, str]] = []
def verarbeite(self, ergebnis):
return ergebnis
def zeige_hinweis(self, titel: str, meldung: str) -> None:
self.hinweise.append((titel, meldung))
class _DummyDateiErgebnis:
def __init__(self, ok: bool = True, kontext: str = "C:/tmp/v_db.gpkg") -> None:
self.ok = ok
self.kontext = kontext
class _DummyProgress:
def __init__(self) -> None:
self.closed = False
def set_total(self, _value: int) -> None:
pass
def set_value(self, _value: int) -> None:
pass
def set_label(self, _value: str) -> None:
pass
def close(self) -> None:
self.closed = True
class _DummyProject:
def mapLayer(self, _layer_id: str):
return None
class _DummyGrabber:
pass
class TestTabAPreconditions(unittest.TestCase):
def _make_logic(self) -> tuple[TabALogic, _DummyPruefmanager]:
pruefmanager = _DummyPruefmanager()
logic = TabALogic(
pruefmanager=cast(Any, pruefmanager),
link_pruefer=cast(Any, object()),
stil_pruefer=cast(Any, object()),
)
return logic, pruefmanager
def test_get_verfahrensgebiet_layer_shows_hint_when_layer_id_missing(self):
logic, pruefmanager = self._make_logic()
with patch.object(logic, "load_verfahrensgebiet_layer_id", return_value=None):
layer = logic._get_verfahrensgebiet_layer()
self.assertIsNone(layer)
self.assertEqual(len(pruefmanager.hinweise), 1)
self.assertIn("Verfahrensgebiet", pruefmanager.hinweise[0][0])
@patch("sn_plan41.ui.tab_a_logic.QgsProject.instance", return_value=_DummyProject())
def test_get_verfahrensgebiet_layer_shows_hint_when_layer_not_in_project(self, _mock_project_instance):
logic, pruefmanager = self._make_logic()
with patch.object(logic, "load_verfahrensgebiet_layer_id", return_value="layer_404"):
layer = logic._get_verfahrensgebiet_layer()
self.assertIsNone(layer)
self.assertEqual(len(pruefmanager.hinweise), 1)
self.assertIn("Verfahrensgebiet", pruefmanager.hinweise[0][0])
@patch("sn_plan41.ui.tab_a_logic.Dateipruefer")
def test_pipeline_aborts_and_shows_hint_when_verfahrensgebiet_missing(
self,
mock_dateipruefer,
):
logic, pruefmanager = self._make_logic()
logic.data_grabber = cast(Any, _DummyGrabber())
mock_dateipruefer.return_value.pruefe.return_value = _DummyDateiErgebnis(ok=True, kontext="C:/tmp/v_db.gpkg")
progress = _DummyProgress()
with patch("sn_plan41.ui.tab_a_logic.create_progress_dialog", return_value=progress):
with patch.object(logic, "_resolve_linkliste", return_value="C:/tmp/linkliste.xlsx"):
with patch.object(logic, "load_verfahrensgebiet_layer_id", return_value=None):
result = logic._on_run_pipeline(
source="C:/tmp/v_db.gpkg",
linkliste=None,
raumfilter="Verfahrensgebiet",
)
self.assertIsNone(result)
self.assertEqual(len(pruefmanager.hinweise), 1)
self.assertIn("Verfahrensgebiet", pruefmanager.hinweise[0][0])
self.assertTrue(progress.closed)
if __name__ == "__main__":
unittest.main()
+94 -37
View File
@@ -1,56 +1,113 @@
"""
Smoke-Tests für TabA UI (sn_plan41/ui/tab_a_ui.py)
Ziel:
- UI kann erstellt werden
- Callbacks crashen nicht
- Keine Qt-Verhaltensprüfung
"""
import unittest
from unittest.mock import patch
from sn_plan41.ui.tab_a_ui import TabA #type:ignore
from sn_basis.functions.variable_wrapper import get_variable
from sn_plan41.ui.tab_a_ui import TabA
class _DummySignal:
def connect(self, _callback):
return None
class _DummyToggleButton:
def __init__(self):
self.arrow = None
self.style = ""
def setArrowType(self, arrow):
self.arrow = arrow
def setStyleSheet(self, style):
self.style = style
class _DummyWidget:
def __init__(self):
self.visible = None
def setVisible(self, visible):
self.visible = visible
class _DummyFileWidget:
def __init__(self):
self._path = ""
def setFilePath(self, path):
self._path = path
def filePath(self):
return self._path
class _DummyCombo:
def __init__(self, value="Pufferlayer"):
self._value = value
def currentText(self):
return self._value
class _DummyPruefmanager:
pass
class _DummyDataGrabber:
pass
class TestTabAUI(unittest.TestCase):
# -----------------------------------------------------
# 1. UI kann erstellt werden
# -----------------------------------------------------
def test_tab_a_ui_can_be_created(self):
tab = TabA(parent=None,build_ui=False)
def _make_tab_without_qt(self):
tab = TabA.__new__(TabA)
tab.group_button = _DummyToggleButton()
tab.group_content = _DummyWidget()
tab.optional_button = _DummyToggleButton()
tab.optional_content = _DummyWidget()
tab.file_widget = _DummyFileWidget()
tab.linkliste_widget = _DummyFileWidget()
tab._raumfilter_combo = _DummyCombo("ohne")
tab.verfahrens_db = None
tab.lokale_linkliste = None
tab.logic = None
tab.pruefmanager = None
tab.data_grabber = None
return tab
self.assertIsNotNone(tab)
self.assertEqual(tab.tab_title, "Daten")
# -----------------------------------------------------
# 2. Toggle-Callbacks crashen nicht
# -----------------------------------------------------
def test_tab_a_toggle_callbacks_do_not_crash(self):
tab = TabA(parent=None,build_ui=False)
def test_tab_a_callbacks_can_be_called_without_crash(self):
tab = self._make_tab_without_qt()
tab._toggle_group(True)
tab._toggle_group(False)
tab._toggle_optional(True)
tab._toggle_optional(False)
# -----------------------------------------------------
# 3. Datei-Callbacks akzeptieren leere Eingaben
# -----------------------------------------------------
def test_tab_a_file_callbacks_accept_empty_input(self):
tab = TabA(parent=None,build_ui=False)
tab._on_verfahrens_db_changed("")
tab._on_linkliste_changed("")
# -----------------------------------------------------
# 4. Layer-Callback akzeptiert None
# -----------------------------------------------------
def test_tab_a_layer_callback_accepts_none(self):
tab = TabA(parent=None,build_ui=False)
self.assertEqual(tab.group_content.visible, False)
self.assertEqual(tab.optional_content.visible, False)
tab._on_layer_changed(None)
def test_tab_a_raumfilter_callback_persists_value(self):
tab = self._make_tab_without_qt()
tab._on_raumfilter_changed("ohne")
self.assertEqual(get_variable("Raumfilter", scope="project"), "ohne")
@patch("sn_plan41.ui.tab_a_ui.TabALogic")
def test_set_services_initializes_logic_and_injects_data_grabber(self, mock_logic_cls):
tab = self._make_tab_without_qt()
mock_logic = mock_logic_cls.return_value
pm = _DummyPruefmanager()
dg = _DummyDataGrabber()
tab.set_services(pruefmanager=pm, data_grabber=dg)
self.assertIs(tab.pruefmanager, pm)
self.assertIs(tab.data_grabber, dg)
self.assertIs(tab.logic, mock_logic)
self.assertIs(tab.logic.data_grabber, dg)
if __name__ == "__main__":
+473
View File
@@ -0,0 +1,473 @@
"""
Tests für sn_plan41/modules/vln_api_logic.py
Alle externen Abhängigkeiten (vln_karten, QSettings, QgsProject, Netzwerk)
werden mit unittest.mock gemockt, sodass keine QGIS-Laufzeitumgebung nötig ist.
"""
import unittest
from typing import Any, Optional
from unittest.mock import MagicMock, patch, call
# ---------------------------------------------------------------------------
# Helpers
# ---------------------------------------------------------------------------
def _make_logic(api_key: Optional[str] = None, mail: Optional[str] = None):
"""Erzeugt eine VlnApiLogic-Instanz mit gemockten QSettings."""
from sn_plan41.modules.vln_api_logic import VlnApiLogic
with patch("sn_plan41.modules.vln_api_logic.QSettings") as mock_qs_cls:
mock_qs = MagicMock()
mock_qs.value.side_effect = lambda key, default="": (
api_key if key == "api_key" else (mail if key == "mail" else default)
)
mock_qs_cls.return_value = mock_qs
if api_key and VlnApiLogic.is_available():
with patch(
"sn_plan41.modules.vln_api_logic.KartenApiClient"
) as mock_client_cls:
mock_client = MagicMock()
mock_client.is_authenticated = True
mock_client.api_key = api_key
mock_client.mail = mail
mock_client_cls.return_value = mock_client
logic = VlnApiLogic()
else:
logic = VlnApiLogic()
return logic
# ---------------------------------------------------------------------------
# Tests: Verfügbarkeit
# ---------------------------------------------------------------------------
class TestVlnApiLogicAvailability(unittest.TestCase):
def test_is_available_reflects_import_state(self):
from sn_plan41.modules.vln_api_logic import VlnApiLogic
result = VlnApiLogic.is_available()
# Ergebnis hängt davon ab, ob vln_karten installiert ist —
# wir prüfen nur, dass ein bool zurückkommt
self.assertIsInstance(result, bool)
def test_is_available_false_when_vln_karten_missing(self):
"""Wenn VLN_KARTEN_AVAILABLE=False, liefert is_available() False."""
import sn_plan41.modules.vln_api_logic as module
original = module.VLN_KARTEN_AVAILABLE
try:
module.VLN_KARTEN_AVAILABLE = False
from sn_plan41.modules.vln_api_logic import VlnApiLogic
with patch.object(module, "VLN_KARTEN_AVAILABLE", False):
self.assertFalse(VlnApiLogic.is_available())
finally:
module.VLN_KARTEN_AVAILABLE = original
# ---------------------------------------------------------------------------
# Tests: Credentials-Persistenz
# ---------------------------------------------------------------------------
class TestVlnApiLogicCredentials(unittest.TestCase):
def _make(self):
from sn_plan41.modules.vln_api_logic import VlnApiLogic
with patch("sn_plan41.modules.vln_api_logic.QSettings"):
with patch("sn_plan41.modules.vln_api_logic.KartenApiClient"):
return VlnApiLogic()
def test_save_api_key_calls_qsettings(self):
logic = self._make()
with patch("sn_plan41.modules.vln_api_logic.QSettings") as mock_qs_cls:
mock_qs = MagicMock()
mock_qs_cls.return_value = mock_qs
logic.save_api_key("token123", "user@test.de")
mock_qs.setValue.assert_any_call("api_key", "token123")
mock_qs.setValue.assert_any_call("mail", "user@test.de")
mock_qs.beginGroup.assert_called_with("vln_karten")
def test_clear_api_key_calls_remove(self):
logic = self._make()
with patch("sn_plan41.modules.vln_api_logic.QSettings") as mock_qs_cls:
mock_qs = MagicMock()
mock_qs_cls.return_value = mock_qs
logic.clear_api_key()
mock_qs.remove.assert_called_with("api_key")
def test_load_stored_credentials_returns_api_key_and_mail(self):
logic = self._make()
with patch("sn_plan41.modules.vln_api_logic.QSettings") as mock_qs_cls:
mock_qs = MagicMock()
mock_qs.value.side_effect = lambda key, default="": {
"api_key": "mykey",
"mail": "user@test.de",
}.get(key, default)
mock_qs_cls.return_value = mock_qs
api_key, mail = logic.load_stored_credentials()
self.assertEqual(api_key, "mykey")
self.assertEqual(mail, "user@test.de")
def test_load_stored_credentials_returns_none_for_empty(self):
logic = self._make()
with patch("sn_plan41.modules.vln_api_logic.QSettings") as mock_qs_cls:
mock_qs = MagicMock()
mock_qs.value.return_value = ""
mock_qs_cls.return_value = mock_qs
api_key, mail = logic.load_stored_credentials()
self.assertIsNone(api_key)
self.assertIsNone(mail)
# ---------------------------------------------------------------------------
# Tests: Login / Logout
# ---------------------------------------------------------------------------
class TestVlnApiLogicLogin(unittest.TestCase):
def _make(self):
from sn_plan41.modules.vln_api_logic import VlnApiLogic
with patch("sn_plan41.modules.vln_api_logic.QSettings"):
with patch("sn_plan41.modules.vln_api_logic.KartenApiClient"):
return VlnApiLogic()
def test_login_sets_client_and_saves_key(self):
import sn_plan41.modules.vln_api_logic as module
if not module.VLN_KARTEN_AVAILABLE:
self.skipTest("vln_karten nicht verfügbar")
logic = self._make()
mock_client = MagicMock()
mock_client.api_key = "newtoken"
with patch("sn_plan41.modules.vln_api_logic.KartenApiClient", return_value=mock_client):
with patch.object(logic, "save_api_key") as mock_save:
logic.login("user@test.de", "secret")
mock_client.login.assert_called_once_with("user@test.de", "secret")
mock_save.assert_called_once_with("newtoken", "user@test.de")
def test_login_raises_runtime_error_without_qgis_modules(self):
import sn_plan41.modules.vln_api_logic as module
logic = self._make()
with patch.object(module, "VLN_KARTEN_AVAILABLE", False):
with self.assertRaises(RuntimeError):
logic.login("user@test.de", "secret")
def test_login_propagates_api_error(self):
import sn_plan41.modules.vln_api_logic as module
if not module.VLN_KARTEN_AVAILABLE:
self.skipTest("vln_karten nicht verfügbar")
logic = self._make()
mock_client = MagicMock()
mock_client.login.side_effect = module.ApiError("Ungültige Zugangsdaten")
with patch("sn_plan41.modules.vln_api_logic.KartenApiClient", return_value=mock_client):
with self.assertRaises(Exception):
logic.login("user@test.de", "wrong")
def test_logout_clears_client(self):
logic = self._make()
logic._client = MagicMock()
logic.logout()
self.assertIsNone(logic._client)
def test_is_authenticated_false_after_logout(self):
logic = self._make()
logic._client = None
self.assertFalse(logic.is_authenticated)
def test_handle_session_expired_clears_key_and_client(self):
logic = self._make()
with patch.object(logic, "clear_api_key") as mock_clear:
with patch.object(logic, "logout") as mock_logout:
logic.handle_session_expired()
mock_clear.assert_called_once()
mock_logout.assert_called_once()
# ---------------------------------------------------------------------------
# Tests: Verfahrensliste
# ---------------------------------------------------------------------------
class TestVlnApiLogicVerfahren(unittest.TestCase):
def _make_authenticated(self):
from sn_plan41.modules.vln_api_logic import VlnApiLogic
with patch("sn_plan41.modules.vln_api_logic.QSettings"):
with patch("sn_plan41.modules.vln_api_logic.KartenApiClient"):
logic = VlnApiLogic()
mock_client = MagicMock()
mock_client.is_authenticated = True
logic._client = mock_client
return logic, mock_client
def test_get_verfahren_raises_when_not_authenticated(self):
from sn_plan41.modules.vln_api_logic import VlnApiLogic
with patch("sn_plan41.modules.vln_api_logic.QSettings"):
with patch("sn_plan41.modules.vln_api_logic.KartenApiClient"):
logic = VlnApiLogic()
logic._client = None
with self.assertRaises(Exception):
logic.get_verfahren()
def test_get_verfahren_delegates_to_client(self):
logic, mock_client = self._make_authenticated()
mock_client.get_verfahren.return_value = [
{"vkz": "27010", "name": "Alpha"},
{"vkz": "27001", "name": "Beta"},
]
result = logic.get_verfahren()
mock_client.get_verfahren.assert_called_once()
self.assertEqual(len(result), 2)
# ---------------------------------------------------------------------------
# Tests: VKZ-Persistenz
# ---------------------------------------------------------------------------
class TestVlnApiLogicVkz(unittest.TestCase):
def _make(self):
from sn_plan41.modules.vln_api_logic import VlnApiLogic
with patch("sn_plan41.modules.vln_api_logic.QSettings"):
with patch("sn_plan41.modules.vln_api_logic.KartenApiClient"):
return VlnApiLogic()
def test_load_stored_vkz_reads_from_project(self):
logic = self._make()
mock_project = MagicMock()
mock_project.readEntry.return_value = ("27010", True)
with patch("sn_plan41.modules.vln_api_logic.QgsProject") as mock_qgsproj_cls:
mock_qgsproj_cls.instance.return_value = mock_project
vkz = logic.load_stored_vkz()
self.assertEqual(vkz, "27010")
mock_project.readEntry.assert_called_once_with("vln_karten", "/vkz", "")
def test_load_stored_vkz_returns_none_for_empty(self):
logic = self._make()
mock_project = MagicMock()
mock_project.readEntry.return_value = ("", True)
with patch("sn_plan41.modules.vln_api_logic.QgsProject") as mock_qgsproj_cls:
mock_qgsproj_cls.instance.return_value = mock_project
vkz = logic.load_stored_vkz()
self.assertIsNone(vkz)
def test_save_vkz_writes_to_project(self):
logic = self._make()
mock_project = MagicMock()
with patch("sn_plan41.modules.vln_api_logic.QgsProject") as mock_qgsproj_cls:
mock_qgsproj_cls.instance.return_value = mock_project
logic.save_vkz("27010")
mock_project.writeEntry.assert_called_once_with("vln_karten", "/vkz", "27010")
def test_save_vkz_does_nothing_for_none(self):
logic = self._make()
mock_project = MagicMock()
with patch("sn_plan41.modules.vln_api_logic.QgsProject") as mock_qgsproj_cls:
mock_qgsproj_cls.instance.return_value = mock_project
logic.save_vkz(None)
mock_project.writeEntry.assert_not_called()
# ---------------------------------------------------------------------------
# Tests: Plan 41 laden (Stil-Anwendung)
# ---------------------------------------------------------------------------
class TestVlnApiLogicLoadP41(unittest.TestCase):
def _make(self):
from sn_plan41.modules.vln_api_logic import VlnApiLogic
with patch("sn_plan41.modules.vln_api_logic.QSettings"):
with patch("sn_plan41.modules.vln_api_logic.KartenApiClient"):
logic = VlnApiLogic()
mock_client = MagicMock()
mock_client.is_authenticated = True
mock_client.load_layer_complete.return_value = {
"type": "FeatureCollection",
"features": [],
}
logic._client = mock_client
return logic
def test_load_p41_raises_without_vln_karten(self):
import sn_plan41.modules.vln_api_logic as module
logic = self._make()
with patch.object(module, "VLN_KARTEN_AVAILABLE", False):
with self.assertRaises(RuntimeError):
logic.load_p41("27010")
def test_load_p41_applies_styles_to_polygon_and_line_layers(self):
import sn_plan41.modules.vln_api_logic as module
if not module.VLN_KARTEN_AVAILABLE:
self.skipTest("vln_karten nicht verfügbar")
logic = self._make()
# Zwei Mock-Layer: einer Polygon (2), einer Linie (1)
mock_layer_polygon = MagicMock()
mock_layer_polygon.geometryType.return_value = module._GEOM_POLYGON
mock_layer_line = MagicMock()
mock_layer_line.geometryType.return_value = module._GEOM_LINE
with patch(
"sn_plan41.modules.vln_api_logic.feature_collection_to_layers",
return_value=[mock_layer_polygon, mock_layer_line],
):
with patch(
"sn_plan41.modules.vln_api_logic.apply_style_from_path"
) as mock_style:
with patch("sn_plan41.modules.vln_api_logic.join_path", side_effect=lambda *p: "/".join(p)):
with patch("sn_plan41.modules.vln_api_logic.get_plugin_root", return_value="/plugins"):
logic.load_p41("27010")
# Prüfen, dass der richtige Stil für jeden Geometrietyp verwendet wurde
style_calls = [str(c) for c in mock_style.call_args_list]
polygon_style_used = any(
module.STYLE_FLAECHE in c for c in style_calls
)
line_style_used = any(
module.STYLE_LINIE in c for c in style_calls
)
self.assertTrue(polygon_style_used, "Flächen-Stil wurde nicht angewendet")
self.assertTrue(line_style_used, "Linien-Stil wurde nicht angewendet")
def test_load_p41_no_style_for_point_layer(self):
import sn_plan41.modules.vln_api_logic as module
if not module.VLN_KARTEN_AVAILABLE:
self.skipTest("vln_karten nicht verfügbar")
logic = self._make()
mock_layer_point = MagicMock()
mock_layer_point.geometryType.return_value = 0 # Point
with patch(
"sn_plan41.modules.vln_api_logic.feature_collection_to_layers",
return_value=[mock_layer_point],
):
with patch(
"sn_plan41.modules.vln_api_logic.apply_style_from_path"
) as mock_style:
with patch("sn_plan41.modules.vln_api_logic.join_path", side_effect=lambda *p: "/".join(p)):
with patch("sn_plan41.modules.vln_api_logic.get_plugin_root", return_value="/plugins"):
logic.load_p41("27010")
mock_style.assert_not_called()
# ---------------------------------------------------------------------------
# Tests: Upload
# ---------------------------------------------------------------------------
class TestVlnApiLogicUpload(unittest.TestCase):
def _make(self):
from sn_plan41.modules.vln_api_logic import VlnApiLogic
with patch("sn_plan41.modules.vln_api_logic.QSettings"):
with patch("sn_plan41.modules.vln_api_logic.KartenApiClient"):
logic = VlnApiLogic()
mock_client = MagicMock()
mock_client.is_authenticated = True
logic._client = mock_client
return logic
def test_upload_returns_error_for_layer_without_api_path(self):
import sn_plan41.modules.vln_api_logic as module
if not module.VLN_KARTEN_AVAILABLE:
self.skipTest("vln_karten nicht verfügbar")
logic = self._make()
mock_layer = MagicMock()
with patch(
"sn_plan41.modules.vln_api_logic.layer_api_path", return_value=None
):
success, message = logic.upload_active_layer(mock_layer)
self.assertFalse(success)
self.assertIn("nicht", message.lower())
def test_upload_returns_error_for_none_layer(self):
import sn_plan41.modules.vln_api_logic as module
if not module.VLN_KARTEN_AVAILABLE:
self.skipTest("vln_karten nicht verfügbar")
logic = self._make()
with patch(
"sn_plan41.modules.vln_api_logic.layer_api_path", return_value=None
):
success, message = logic.upload_active_layer(None)
self.assertFalse(success)
def test_upload_returns_false_without_qgis_modules(self):
import sn_plan41.modules.vln_api_logic as module
logic = self._make()
with patch.object(module, "VLN_KARTEN_AVAILABLE", False):
success, message = logic.upload_active_layer(MagicMock())
self.assertFalse(success)
def test_upload_calls_save_feature_collection(self):
import sn_plan41.modules.vln_api_logic as module
if not module.VLN_KARTEN_AVAILABLE:
self.skipTest("vln_karten nicht verfügbar")
logic = self._make()
mock_layer = MagicMock()
mock_layer.isEditable.return_value = False
mock_layer.featureCount.return_value = 5
fc = {"type": "FeatureCollection", "features": []}
with patch("sn_plan41.modules.vln_api_logic.layer_api_path", return_value="/maps/p41/27010"):
with patch("sn_plan41.modules.vln_api_logic.plugin_layers", return_value=[mock_layer]):
with patch("sn_plan41.modules.vln_api_logic.layers_to_feature_collection", return_value=fc):
success, message = logic.upload_active_layer(mock_layer)
logic._client.save_feature_collection.assert_called_once_with("/maps/p41/27010", fc)
self.assertTrue(success)
if __name__ == "__main__":
unittest.main()
+20 -1
View File
@@ -1,4 +1,7 @@
#sn_plan41/ui/dockwidget.py
"""sn_plan41/ui/dockwidget.py Haupt-DockWidget für sn_plan41.
Verwaltet die Tabs für Linkvalidierung, Druck und Einstellungen.
"""
from sn_basis.ui.tabs.settings_tab import SettingsTab
from sn_plan41.ui.tab_a_ui import TabA
from sn_basis.ui.tabs.print_tab import PrintTab
@@ -8,9 +11,25 @@ from sn_basis.functions.message_wrapper import error
class DockWidget(BaseDockWidget):
"""Haupt-DockWidget für sn_plan41 mit Tab-Verwaltung.
Attributes:
tabs: Liste von Tab-Klassen (TabA, PrintTab, SettingsTab)
pruefmanager: Prüfmanager-Instanz für Validierung
data_grabber: DataGrabber-Instanz für Fachdatenabruf
"""
tabs = [TabA, PrintTab, SettingsTab]
def __init__(self, parent=None, subtitle="", pruefmanager=None, data_grabber=None):
"""Initialisiert das DockWidget mit Services und Tabs.
Args:
parent: Übergeordnetes Widget
subtitle: Untertitel des DockWidgets
pruefmanager: Prüfmanager-Instanz
data_grabber: DataGrabber-Instanz
"""
super().__init__(parent, subtitle)
# Services als Attribute speichern
+221 -53
View File
@@ -12,6 +12,7 @@ import os
import datetime
import json
import tempfile
import html
from sn_basis.functions.qgiscore_wrapper import (
QgsVectorFileWriter,
@@ -63,9 +64,88 @@ class TabALogic:
self.link_pruefer = link_pruefer
self.stil_pruefer = stil_pruefer
self.data_grabber: Optional[DataGrabber] = None
class _SilentPruefmanagerProxy:
"""Proxy, der Prüfergebnisse ohne UI-Meldungen verarbeitet."""
def __init__(self, outer: "TabALogic", fallback: Optional[Any]) -> None:
self._outer = outer
self._fallback = fallback
self.results: List[Any] = []
def verarbeite(self, ergebnis: Any) -> Any:
self.results.append(ergebnis)
ok = bool(getattr(ergebnis, "ok", False))
if not ok:
aktion = getattr(ergebnis, "aktion", "unbekannt")
meldung = getattr(ergebnis, "meldung", "")
self._outer._log(f"[SILENT-PRUEFMANAGER] {aktion}: {meldung}")
return ergebnis
def __getattr__(self, name: str) -> Any:
if self._fallback is not None:
return getattr(self._fallback, name)
raise AttributeError(name)
def _log(self, msg: str) -> None:
print(f"[TabALogic] {msg}")
def _create_silent_pruefmanager(self) -> "TabALogic._SilentPruefmanagerProxy":
return TabALogic._SilentPruefmanagerProxy(self, self.pruefmanager)
def _extract_datenabruf_error_maps(self, datenabruf_results: List[Any]) -> Dict[str, Dict[str, str]]:
by_ident: Dict[str, str] = {}
by_thema: Dict[str, str] = {}
for result in datenabruf_results or []:
if not result:
continue
context = getattr(result, "kontext", None)
if not isinstance(context, dict):
continue
if getattr(result, "aktion", None) == "url_nicht_erreichbar":
ident = str(context.get("ident") or "").strip()
thema = str(context.get("thema") or "").strip()
reason = str(context.get("error") or getattr(result, "meldung", "") or "unbekannter Fehler").strip()
if ident and reason:
by_ident[ident] = reason
if thema and reason:
by_thema[thema] = reason
if getattr(result, "aktion", None) == "datenabruf":
fehler_map = context.get("fehler")
if isinstance(fehler_map, dict):
for thema_key, value in fehler_map.items():
thema = str(thema_key or "").strip()
reason = str(value or "").strip()
if thema and reason and thema not in by_thema:
by_thema[thema] = reason
return {"by_ident": by_ident, "by_thema": by_thema}
def _zeige_verfahrensgebiet_hinweis(self) -> None:
if not self.pruefmanager:
return
show_hint = getattr(self.pruefmanager, "zeige_hinweis", None)
if callable(show_hint):
show_hint(
"Verfahrensgebiet fehlt",
"Kein gueltiger Verfahrensgebiet-Layer vorhanden. "
"Bitte zuerst in sn_verfahrensgebiet den Layer ueber 'Aus ALKIS laden' laden "
"oder im Dropdown einen gueltigen Layer auswaehlen.",
)
def _close_progress_dialog(self, progress: Optional[Any]) -> None:
if progress is None:
return
close = getattr(progress, "close", None)
if callable(close):
try:
close()
except Exception:
pass
# -------------------------------
# Verfahrens-Datenbank (Pfad-Management)
# -------------------------------
@@ -155,12 +235,6 @@ class TabALogic:
# -------------------------------
# Verfahrensgebiet-Layer
# -------------------------------
def save_verfahrensgebiet_layer(self, layer: QgsVectorLayer) -> None:
"""Speichert die Verfahrensgebiet-Layer-ID, unter Annahme, dass der Layer prevalidiert ist."""
layer_id = layer.id() if layer is not None else ""
set_variable("verfahrensgebiet_layer", layer_id or "", scope="project")
def load_verfahrensgebiet_layer_id(self) -> Optional[str]:
value = get_variable("verfahrensgebiet_layer", scope="project")
return value or None
@@ -217,6 +291,7 @@ class TabALogic:
linkliste_final = self._resolve_linkliste(linkliste)
if linkliste_final is None:
self._log("Linkliste kann nicht aufgelöst werden")
self._close_progress_dialog(progress)
return None
else:
self._log(f"Linkliste final: '{linkliste_final}'")
@@ -224,6 +299,7 @@ class TabALogic:
raumfilter_layer = self._resolve_raumfilter(raumfilter, final_pfad)
if raumfilter in ("Verfahrensgebiet", "Pufferlayer") and raumfilter_layer is None:
self._log(f"Raumfilter '{raumfilter}' nicht verfügbar")
self._close_progress_dialog(progress)
return None
# 4) Lade-Status initialisieren (funktioniert ab Bestätigung überschreiben/anhängen)
@@ -236,7 +312,16 @@ class TabALogic:
progress.set_label("Prüfe Eingaben...")
# 5) Daten aus Linkliste laden und prüfen
source_dict, grabber_summary = self.data_grabber.run(linkliste_final)
silent_pruefmanager = self._create_silent_pruefmanager()
local_data_grabber = DataGrabber(
silent_pruefmanager,
datei_pruefer_cls=self.data_grabber._datei_pruefer_cls,
link_pruefer=self.data_grabber.link_pruefer,
layer_pruefer=self.data_grabber.layer_pruefer,
stil_pruefer=self.data_grabber.stil_pruefer,
excel_importer_cls=self.data_grabber._excel_importer_cls,
)
source_dict, grabber_summary = local_data_grabber.run(linkliste_final)
self._log(f"DataGrabber: {grabber_summary.meldung} [{grabber_summary.aktion}]")
# DEBUG: detaillierter Status
@@ -249,6 +334,7 @@ class TabALogic:
if not source_dict.get("rows"):
self._log("Keine validen Linkliste-Einträge für Datenabruf")
print("[TabALogic] ... STOP: rows:", len(source_dict.get("rows", [])))
self._close_progress_dialog(progress)
return None
total_rows = len(source_dict.get("rows", []))
@@ -266,7 +352,8 @@ class TabALogic:
self._log("Warnung: DataGrabber meldet fehlerhafte Zeilen, fahre mit Validierungsdaten fort")
# 5) Datenabruf (aus validierten Zeilen)
datenabruf = Datenabruf(self.pruefmanager)
silent_pruefmanager = self._create_silent_pruefmanager()
datenabruf = Datenabruf(silent_pruefmanager)
result_dict, datenabruf_results = datenabruf.datenabruf(
result_dict=source_dict,
raumfilter=raumfilter,
@@ -296,7 +383,7 @@ class TabALogic:
progress.set_label("Fachdaten laden abgeschlossen. Bitte OK klicken, um den Dialog zu schließen.")
# 7) Log-Datei schreiben
self._write_markdown_log(final_pfad, source_dict, pipeline_context, load_summary)
self._write_html_log(final_pfad, source_dict, pipeline_context, load_summary)
print("=" * 60 + "\n")
return pipeline_context
@@ -310,7 +397,15 @@ class TabALogic:
aborted = False
if not rows:
self._log("Keine Dienste zum Laden")
return
return {
"row_count": 0,
"loaded_count": 0,
"skipped_outside": 0,
"aborted": False,
"row_stats": [],
"layer_call_status": {},
"raumfilter_name": pipeline_context.get("raumfilter_name", "unbekannt"),
}
final_pfad = pipeline_context.get("source") or ""
use_datenschreiber = bool(final_pfad)
@@ -340,7 +435,12 @@ class TabALogic:
raumfilter_extent = raumfilter_layer.extent()
temp_layers: List[Any] = []
layer_loader = LayerLoader(self.pruefmanager, stil_pruefer=self.stil_pruefer, layer_pruefer=self.link_pruefer)
silent_pruefmanager = self._create_silent_pruefmanager()
layer_loader = LayerLoader(silent_pruefmanager, stil_pruefer=self.stil_pruefer, layer_pruefer=self.link_pruefer)
error_maps = self._extract_datenabruf_error_maps(pipeline_context.get("datenabruf_results", []))
error_by_ident = error_maps.get("by_ident", {})
error_by_thema = error_maps.get("by_thema", {})
# Statistiken für Log: Raumfilter-Info pro Dienst
row_stats: List[Dict[str, Any]] = []
@@ -357,6 +457,7 @@ class TabALogic:
daten_map = (pipeline_context.get("result_dict") or {}).get("daten", {})
fetched_features = daten_map.get(ident, []) if isinstance(daten_map, dict) else []
fetched_count = len(fetched_features) if isinstance(fetched_features, list) else None
base_reason = error_by_ident.get(ident) or error_by_thema.get(thema)
if progress is not None:
progress.set_label(f"Lade Dienst {idx}/{total}: {thema}")
@@ -385,6 +486,8 @@ class TabALogic:
if not layer:
layer_call_status[thema] = "layer_nicht_ladbar"
self._log(f"[DEBUG] Layeraufruf fehlgeschlagen: thema='{thema}'")
reason = base_reason or "Layer konnte nicht geladen werden (Dienst nicht erreichbar oder Link fehlerhaft)"
self._log(f"[DEBUG] Dienst nicht geladen: {thema} | Grund: {reason}")
row_stats.append({
"dienst": thema,
"provider": provider,
@@ -394,7 +497,7 @@ class TabALogic:
"total_features": None,
"filtered_features": None,
"status": "layer_nicht_ladbar",
"raumfilter": raumfilter_name,
"reason": reason,
})
continue
@@ -448,6 +551,7 @@ class TabALogic:
layer_call_status[thema] = "raumfilter_ausserhalb"
self._log(f"Dienst {thema} ist außerhalb des Raumfilters")
skipped_outside += 1
reason = "Keine Objekte innerhalb des Raumfilters"
row_stats.append({
"dienst": thema,
"provider": provider,
@@ -457,7 +561,7 @@ class TabALogic:
"total_features": total_features,
"filtered_features": 0,
"status": "außerhalb",
"raumfilter": raumfilter_name,
"reason": reason,
})
continue
@@ -473,7 +577,7 @@ class TabALogic:
"total_features": total_features,
"filtered_features": filtered_features,
"status": "geladen",
"raumfilter": raumfilter_name,
"reason": "geladen",
})
layer_call_status[thema] = "geladen"
self._log(f"[DEBUG] Dienst geladen: thema='{thema}', provider='{provider}', filtered_features={filtered_features}")
@@ -671,75 +775,118 @@ class TabALogic:
self._log(f"[DEBUG] Fehler beim Erzeugen lokaler Featureschicht für {thema}: {exc}")
return None
def _write_markdown_log(
def _write_html_log(
self,
final_pfad: str,
source_dict: DataDict,
pipeline_context: Dict[str, Any],
load_summary: Dict[str, Any],
) -> None:
"""Schreibt den Pipeline-Log (Markdown)."""
"""Schreibt den Pipeline-Log als HTML-Datei."""
lines = [
"# Plan41 Fachdaten-Ladevorgang",
"",
f"**Datum**: {datetime.datetime.now().isoformat()}",
f"**Verfahrens-DB**: {final_pfad or 'temporär'}",
f"**Linkliste**: {pipeline_context.get('linkliste')}",
"",
"## Zusammenfassung",
"",
f"- **Zeilen gesamt**: {load_summary.get('row_count', 0)}",
f"- **Geladene Dienste**: {load_summary.get('loaded_count', 0)}",
f"- **Außerhalb Raumfilter**: {load_summary.get('skipped_outside', 0)}",
f"- **Abgebrochen**: {load_summary.get('aborted', False)}",
f"- **Raumfilter**: {load_summary.get('raumfilter_name', 'unbekannt')}",
f"- **Raumfilter-Typ**: {pipeline_context.get('raumfilter_name', 'unbekannt')}",
"",
"## Dienstliste",
"",
"| Dienst | Provider | Linkadresse | Aufrufstatus | Ergebnisstatus |",
"|---|---|---|---|---|",
"<!doctype html>",
"<html lang='de'>",
"<head>",
" <meta charset='utf-8'>",
" <title>Plan41 Fachdaten-Ladevorgang</title>",
" <style>",
" body { font-family: Arial, sans-serif; margin: 20px; color: #222; }",
" h1, h2 { margin-bottom: 8px; }",
" .meta p { margin: 4px 0; }",
" table { border-collapse: collapse; width: 100%; margin: 12px 0 24px; }",
" th, td { border: 1px solid #ccc; padding: 6px 8px; text-align: left; vertical-align: top; }",
" th { background: #f2f2f2; }",
" .ok { color: #1b5e20; font-weight: 600; }",
" .warn { color: #8d6e00; font-weight: 600; }",
" .err { color: #b71c1c; font-weight: 600; }",
" </style>",
"</head>",
"<body>",
"<h1>Plan41 Fachdaten-Ladevorgang</h1>",
"<div class='meta'>",
f" <p><strong>Datum:</strong> {datetime.datetime.now().isoformat()}</p>",
f" <p><strong>Verfahrens-DB:</strong> {final_pfad or 'temporär'}</p>",
f" <p><strong>Linkliste:</strong> {pipeline_context.get('linkliste')}</p>",
f" <p><strong>Raumfilter:</strong> {load_summary.get('raumfilter_name', 'unbekannt')}</p>",
"</div>",
"<h2>Zusammenfassung</h2>",
"<ul>",
f" <li>Zeilen gesamt: {load_summary.get('row_count', 0)}</li>",
f" <li>Geladene Dienste: {load_summary.get('loaded_count', 0)}</li>",
f" <li>Außerhalb Raumfilter: {load_summary.get('skipped_outside', 0)}</li>",
f" <li>Abgebrochen: {load_summary.get('aborted', False)}</li>",
"</ul>",
"<h2>Dienstliste</h2>",
"<table>",
"<thead><tr><th>Dienst</th><th>Provider</th><th>Linkadresse</th><th>Aufrufstatus</th></tr></thead>",
"<tbody>",
]
status_by_dienst = {
str(stat.get("dienst", "")): str(stat.get("status", "n/a"))
for stat in load_summary.get("row_stats", [])
}
aufrufstatus_by_dienst = {
str(key): str(value)
for key, value in (load_summary.get("layer_call_status", {}) or {}).items()
}
aufrufstatus_labels = {
"layeraufruf_start": "Layer-Aufruf gestartet",
"layeraufruf_ok": "Layer-Aufruf erfolgreich",
"geladen": "Geladen",
"layer_nicht_ladbar": "Nicht ladbar",
"raumfilter_ausserhalb": "Außerhalb Raumfilter",
"abbruch_vor_layeraufruf": "Abbruch vor Layer-Aufruf",
"abbruch_nach_layeraufruf": "Abbruch nach Layer-Aufruf",
"abbruch_nach_raumfilter": "Abbruch nach Raumfilter",
"nicht_aufgerufen": "Nicht aufgerufen",
}
status_labels = {
"geladen": "Geladen",
"außerhalb": "Außerhalb Raumfilter",
"layer_nicht_ladbar": "Nicht ladbar",
}
for row in source_dict.get('rows', []):
dienst = row.get('Inhalt') or row.get('ident') or ''
provider = row.get('Provider') or ''
link = row.get('Link') or ''
aufrufstatus = aufrufstatus_by_dienst.get(str(dienst), "nicht_aufgerufen")
ergebnisstatus = status_by_dienst.get(str(dienst), "n/a")
lines.append(f"| {dienst} | {provider} | {link} | {aufrufstatus} | {ergebnisstatus} |")
aufrufstatus_text = aufrufstatus_labels.get(str(aufrufstatus), str(aufrufstatus))
lines.append(
f"<tr><td>{html.escape(str(dienst))}</td><td>{html.escape(str(provider))}</td><td>{html.escape(str(link))}</td><td>{html.escape(str(aufrufstatus_text))}</td></tr>"
)
lines.extend([
"",
"## Raumfilter-Statistik",
"",
"| Dienst | Provider | Linkadresse | Datenabruf-Objekte | Gesamt-Objekte | Gefilterte Objekte | Raumfilter | Status |",
"|---|---|---|---|---|---|---|---|",
"</tbody>",
"</table>",
"<h2>Raumfilter-Statistik</h2>",
"<table>",
"<thead><tr><th>Dienst</th><th>Datenabruf-Objekte</th><th>Gesamt-Objekte</th><th>Gefilterte Objekte</th><th>Status</th></tr></thead>",
"<tbody>",
])
for stat in load_summary.get('row_stats', []):
status = str(stat.get('status', 'n/a'))
status_label = status_labels.get(status, status)
reason = str(stat.get('reason', '') or '')
status_text = status_label if not reason else f"{status_label}: {reason}"
lines.append(
f"| {stat.get('dienst', '')} | {stat.get('provider', '')} | {stat.get('link', '')} | {stat.get('datenabruf_features', 'n/a')} | {stat.get('total_features', 'n/a')} | {stat.get('filtered_features', 'n/a')} | {stat.get('raumfilter', '')} | {stat.get('status', 'n/a')} |"
f"<tr><td>{html.escape(str(stat.get('dienst', '')))}</td><td>{html.escape(str(stat.get('datenabruf_features', 'n/a')))}</td><td>{html.escape(str(stat.get('total_features', 'n/a')))}</td><td>{html.escape(str(stat.get('filtered_features', 'n/a')))}</td><td>{html.escape(status_text)}</td></tr>"
)
markdown = "\n".join(lines)
lines.extend([
"</tbody>",
"</table>",
"</body>",
"</html>",
])
html_text = "\n".join(lines)
if final_pfad:
log_dir = os.path.dirname(final_pfad)
os.makedirs(log_dir, exist_ok=True)
log_file = os.path.join(log_dir, "plan41_lade_log.md")
log_file = os.path.join(log_dir, "plan41_lade_log.html")
try:
with open(log_file, "w", encoding="utf-8") as fh:
fh.write(markdown)
fh.write(html_text)
self.pruefmanager.verarbeite(
pruef_ergebnis(
@@ -754,15 +901,33 @@ class TabALogic:
self.pruefmanager.verarbeite(
pruef_ergebnis(
ok=False,
meldung=f"Fehler beim Schreiben des Logle (md): {exc}",
meldung=f"Fehler beim Schreiben des Logs (html): {exc}",
aktion="log_schreiben_fehlgeschlagen",
kontext={"error": str(exc)},
)
)
warning("Lade-Log", f"Konnte Datei nicht schreiben: {exc}", duration=10)
else:
# temporärer Modus: nur anzeigen
info("Lade-Log (temporär)", markdown, duration=20)
try:
tmp_dir = os.path.join(tempfile.gettempdir(), "sn_plan41")
os.makedirs(tmp_dir, exist_ok=True)
timestamp = datetime.datetime.now().strftime("%Y%m%d_%H%M%S")
log_file = os.path.join(tmp_dir, f"plan41_lade_log_{timestamp}.html")
with open(log_file, "w", encoding="utf-8") as fh:
fh.write(html_text)
self._log(f"Lade-Log (temporär) gespeichert: {log_file}")
if hasattr(os, "startfile"):
try:
os.startfile(log_file)
except Exception as exc:
self._log(f"Konnte temporäre Log-Datei nicht öffnen: {exc}")
info("Lade-Log (temporär)", f"Lade-Protokoll gespeichert: {log_file}", duration=20)
except Exception as exc:
warning("Lade-Log", f"Konnte temporäre Log-Datei nicht schreiben: {exc}", duration=10)
def _clone_layer_with_extent(self, layer: QgsVectorLayer, extent, thema: str) -> QgsVectorLayer | None:
@@ -875,15 +1040,18 @@ class TabALogic:
if not layer_id:
self._log("❌ Keine Layer-ID gespeichert")
self._zeige_verfahrensgebiet_hinweis()
return None
layer = QgsProject.instance().mapLayer(layer_id)
if not layer:
self._log("❌ Layer-ID existiert nicht im Projekt")
self._zeige_verfahrensgebiet_hinweis()
return None
if not self.is_valid_verfahrensgebiet_layer(layer):
self._log("❌ Layer ist kein gültiger Vektorlayer")
self._zeige_verfahrensgebiet_hinweis()
return None
self._log(f"Verfahrensgebiet-Layer OK: '{layer.name()}'")
+366 -51
View File
@@ -9,7 +9,9 @@ from typing import Optional
from sn_basis.functions.qt_wrapper import (
QWidget,
QVBoxLayout,
QHBoxLayout,
QLabel,
QLineEdit,
QPushButton,
QToolButton,
QFileDialog,
@@ -32,7 +34,8 @@ from sn_basis.modules.DataGrabber import DataGrabber
from sn_basis.modules.Dateipruefer import Dateipruefer
from sn_plan41.ui.tab_a_logic import TabALogic
from sn_basis.modules.linkpruefer import Linkpruefer
from sn_basis.modules.stilpruefer import Stilpruefer
from sn_basis.modules.stilpruefer import Stilpruefer
from sn_plan41.modules.vln_api_logic import VlnApiLogic
# Konstanten
RAUMFILTER_VAR = "Raumfilter"
@@ -78,7 +81,11 @@ class TabA(QWidget):
# UI-Referenzen
self._raumfilter_combo: Optional[QComboBox] = None
# VLN-API
self.vln_logic: Optional[VlnApiLogic] = None
self._vln_restoring: bool = False
self._build_ui()
self._restore_state()
@@ -92,14 +99,17 @@ class TabA(QWidget):
self.pruefmanager = pruefmanager
self.data_grabber = data_grabber
self.logic = TabALogic(
pruefmanager=self.pruefmanager,
link_pruefer=Linkpruefer(),
stil_pruefer=Stilpruefer(),
)
# DataGrabber in die Logik injizieren
pruefmanager=self.pruefmanager,
link_pruefer=Linkpruefer(),
stil_pruefer=Stilpruefer(),
)
self.logic.data_grabber = self.data_grabber
# VLN-API-Logik initialisieren
self.vln_logic = VlnApiLogic(self.pruefmanager)
self._update_vln_ui_state()
self._restore_vln_state()
def _build_ui(self) -> None:
"""Erstellt die komplette UI-Hierarchie mit allen Gruppen."""
main_layout = QVBoxLayout()
@@ -166,16 +176,7 @@ class TabA(QWidget):
self.optional_content.setVisible(False)
main_layout.addWidget(self.optional_content)
# === LAYER-AUSWAHL + RAUMFILTER ===
layer_label = QLabel("Verfahrensgebiet-Layer auswählen")
layer_label.setStyleSheet("font-weight: bold; margin-top: 6px;")
main_layout.addWidget(layer_label)
self.layer_combo = QgsMapLayerComboBox()
self.layer_combo.setFilters(QgsMapLayerProxyModel.VectorLayer)
self.layer_combo.layerChanged.connect(self._on_layer_changed)
main_layout.addWidget(self.layer_combo)
# === RAUMFILTER ===
main_layout.addWidget(QLabel("Raumfilter"))
self._raumfilter_combo = QComboBox(self)
self._raumfilter_combo.setToolTip("Wählt die räumliche Bezugsfläche für die Datenextraktion.")
@@ -189,7 +190,84 @@ class TabA(QWidget):
self.btn_pipeline.clicked.connect(self._on_load_fachdaten)
main_layout.addWidget(self.btn_pipeline)
# === VLN API / PLAN 41 ===
self._vln_group_button = QToolButton()
self._vln_group_button.setText("VLN API / Plan 41")
self._vln_group_button.setCheckable(True)
self._vln_group_button.setChecked(False)
self._vln_group_button.setToolButtonStyle(ToolButtonTextBesideIcon)
self._vln_group_button.setArrowType(ArrowRight)
self._vln_group_button.setStyleSheet("font-weight: bold; margin-top: 8px;")
self._vln_group_button.toggled.connect(self._toggle_vln_group)
main_layout.addWidget(self._vln_group_button)
self._vln_group_content = QWidget()
self._vln_group_content.setSizePolicy(SizePolicyPreferred, SizePolicyMaximum)
vln_layout = QVBoxLayout()
vln_layout.setSpacing(4)
vln_layout.setContentsMargins(10, 4, 4, 8)
# Status
self._vln_status_label = QLabel("Nicht angemeldet")
self._vln_status_label.setStyleSheet("color: gray; font-style: italic;")
vln_layout.addWidget(self._vln_status_label)
# E-Mail und Passwort
vln_layout.addWidget(QLabel("E-Mail:"))
self._vln_mail_edit = QLineEdit()
self._vln_mail_edit.setPlaceholderText("mail@beispiel.de")
vln_layout.addWidget(self._vln_mail_edit)
vln_layout.addWidget(QLabel("Passwort:"))
self._vln_pass_edit = QLineEdit()
try:
self._vln_pass_edit.setEchoMode(QLineEdit.EchoMode.Password)
except AttributeError:
self._vln_pass_edit.setEchoMode(QLineEdit.Password)
vln_layout.addWidget(self._vln_pass_edit)
# Login / Logout Buttons
btn_row = QHBoxLayout()
self._btn_vln_login = QPushButton("Anmelden")
self._btn_vln_login.clicked.connect(self._on_vln_login)
self._btn_vln_logout = QPushButton("Abmelden")
self._btn_vln_logout.clicked.connect(self._on_vln_logout)
btn_row.addWidget(self._btn_vln_login)
btn_row.addWidget(self._btn_vln_logout)
vln_layout.addLayout(btn_row)
# Verfahren
vln_layout.addWidget(QLabel("Verfahren:"))
self._vln_verfahren_combo = QComboBox()
self._vln_verfahren_combo.setToolTip("Verfahren (Teilnehmergemeinschaft) wählen")
self._vln_verfahren_combo.setEnabled(False)
self._vln_verfahren_combo.currentIndexChanged.connect(
self._on_vln_verfahren_changed
)
vln_layout.addWidget(self._vln_verfahren_combo)
# Plan 41 laden
self._btn_p41_laden = QPushButton("Plan 41 (Wege- und Gewässerplan) laden")
self._btn_p41_laden.setToolTip(
"Lädt Flächen- und Linienlayer für das gewählte Verfahren vom Server"
)
self._btn_p41_laden.setEnabled(False)
self._btn_p41_laden.clicked.connect(self._on_p41_laden)
vln_layout.addWidget(self._btn_p41_laden)
# Upload
self._btn_upload = QPushButton("Aktiven Layer hochladen")
self._btn_upload.setToolTip(
"Lädt alle Plan-41-Layer des aktiven Verfahrens zum Server hoch"
)
self._btn_upload.setEnabled(False)
self._btn_upload.clicked.connect(self._on_upload_active)
vln_layout.addWidget(self._btn_upload)
self._vln_group_content.setLayout(vln_layout)
self._vln_group_content.setVisible(False)
main_layout.addWidget(self._vln_group_content)
main_layout.addStretch(1)
self.setLayout(main_layout)
@@ -213,21 +291,281 @@ class TabA(QWidget):
self.lokale_linkliste = link
except Exception:
pass
# Raumfilter (schon im _build_ui behandelt)
# Layer
def _restore_vln_state(self) -> None:
"""Stellt die zuletzt gewählte VKZ aus der Projektdatei wieder her."""
if self.vln_logic is None or not self.vln_logic.is_authenticated:
return
try:
layer_id = get_variable("tab_a_layer_id", scope="project")
if layer_id:
layer = QgsProject.instance().mapLayer(layer_id)
if layer and self.layer_combo:
self.layer_combo.setLayer(layer)
self._pufferlayer = layer
self._populate_verfahren_combo(restore_vkz=True)
except Exception:
pass
# Raumfilter (schon im _build_ui behandelt)
# === UI CALLBACKS ===
def _toggle_vln_group(self, checked: bool) -> None:
self._vln_group_button.setArrowType(ArrowDown if checked else ArrowRight)
self._vln_group_content.setVisible(checked)
def _update_vln_ui_state(self) -> None:
"""Passt alle VLN-Controls an den aktuellen Authentifizierungsstatus an."""
if self.vln_logic is None:
authenticated = False
available = False
else:
authenticated = self.vln_logic.is_authenticated
available = self.vln_logic.is_available()
if not available:
self._vln_status_label.setText(
"Plugin 'vln_karten' nicht installiert"
)
self._vln_status_label.setStyleSheet("color: red; font-style: italic;")
self._btn_vln_login.setEnabled(False)
elif authenticated:
mail = (self.vln_logic.mail or "API-Key") if self.vln_logic else ""
self._vln_status_label.setText("Angemeldet: %s" % mail)
self._vln_status_label.setStyleSheet(
"color: green; font-style: italic;"
)
self._btn_vln_login.setEnabled(False)
else:
self._vln_status_label.setText("Nicht angemeldet")
self._vln_status_label.setStyleSheet("color: gray; font-style: italic;")
self._btn_vln_login.setEnabled(True)
self._btn_vln_logout.setEnabled(authenticated)
self._vln_verfahren_combo.setEnabled(authenticated)
vkz_chosen = (
authenticated
and self._vln_verfahren_combo.currentData() is not None
)
self._btn_p41_laden.setEnabled(vkz_chosen)
self._btn_upload.setEnabled(authenticated)
def _populate_verfahren_combo(self, restore_vkz: bool = False) -> None:
"""Füllt die Verfahren-Combo und wählt ggf. die gespeicherte VKZ."""
if self.vln_logic is None:
return
verfahren = self.vln_logic.get_verfahren()
self._vln_restoring = True
self._vln_verfahren_combo.clear()
self._vln_verfahren_combo.addItem("— Verfahren wählen —", None)
for v in verfahren:
label = (
"%s%s" % (v["vkz"], v["name"])
if v["name"]
else v["vkz"]
)
self._vln_verfahren_combo.addItem(label, v["vkz"])
self._vln_restoring = False
if restore_vkz:
stored_vkz = self.vln_logic.load_stored_vkz()
if stored_vkz:
idx = self._vln_verfahren_combo.findData(stored_vkz)
if idx >= 0:
self._vln_verfahren_combo.setCurrentIndex(idx)
self._vln_verfahren_combo.setEnabled(True)
self._update_vln_ui_state()
def _on_vln_login(self) -> None:
"""Führt den API-Login durch."""
if self.vln_logic is None:
return
mail = self._vln_mail_edit.text().strip()
password = self._vln_pass_edit.text()
if not mail or not password:
QMessageBox.warning(
self,
"Anmeldung",
"Bitte E-Mail-Adresse und Passwort eingeben.",
)
return
try:
self.vln_logic.login(mail, password)
except Exception as exc:
QMessageBox.warning(self, "Anmeldung fehlgeschlagen", str(exc))
return
self._vln_pass_edit.clear()
try:
self._populate_verfahren_combo(restore_vkz=True)
except Exception as exc:
QMessageBox.warning(
self,
"Verfahrensliste",
"Anmeldung erfolgreich, aber Verfahrensliste konnte nicht "
"geladen werden: %s" % exc,
)
self._update_vln_ui_state()
def _on_vln_logout(self) -> None:
"""Meldet den Benutzer lokal ab."""
if self.vln_logic is None:
return
self.vln_logic.logout()
self._vln_restoring = True
self._vln_verfahren_combo.clear()
self._vln_verfahren_combo.setEnabled(False)
self._vln_restoring = False
self._update_vln_ui_state()
def _on_vln_verfahren_changed(self, _index: int) -> None:
"""Persistiert die gewählte VKZ."""
if self._vln_restoring or self.vln_logic is None:
return
vkz = self._vln_verfahren_combo.currentData()
self.vln_logic.save_vkz(vkz)
self._update_vln_ui_state()
def _on_p41_laden(self) -> None:
"""Lädt den Plan-41-Datensatz für die gewählte VKZ."""
if self.vln_logic is None:
return
vkz = self._vln_verfahren_combo.currentData()
if not vkz:
QMessageBox.warning(
self, "Plan 41 laden", "Bitte zuerst ein Verfahren wählen."
)
return
# Bereits geladene Layer prüfen
existing = self.vln_logic.get_p41_layers(vkz)
if existing:
try:
answer = QMessageBox.question(
self,
"Layer ersetzen",
"Plan 41 für VKZ %s ist bereits geladen.\n"
"Beim Neuladen werden die bestehenden Layer ersetzt. Fortfahren?"
% vkz,
)
# Qt6: StandardButton.Yes, Qt5: QMessageBox.Yes
yes = getattr(
getattr(QMessageBox, "StandardButton", QMessageBox),
"Yes",
QMessageBox.Yes if hasattr(QMessageBox, "Yes") else None,
)
if answer != yes:
return
except Exception:
pass
self.vln_logic.remove_p41_layers(vkz)
try:
layers = self.vln_logic.load_p41(vkz)
except Exception as exc:
# AuthError: Sitzung abgelaufen
try:
from sn_plan41.modules.vln_api_client import AuthError as _AuthError
if isinstance(exc, _AuthError):
self.vln_logic.handle_session_expired()
self._on_vln_logout()
QMessageBox.warning(
self,
"Sitzung abgelaufen",
"Der API-Key ist nicht mehr gültig — bitte neu anmelden.",
)
return
except ImportError:
pass
QMessageBox.warning(self, "Laden fehlgeschlagen", str(exc))
return
total = sum(l.featureCount() for l in layers)
detail = ", ".join(
"%s: %d" % (l.name(), l.featureCount()) for l in layers
)
if total == 0:
QMessageBox.warning(
self,
"Plan 41 laden",
"Keine Objekte vorhanden — ein leerer Layer wurde angelegt.",
)
else:
try:
from sn_basis.functions.message_wrapper import info
info(
"Plan 41 geladen",
"%d Layer geladen (%s)." % (len(layers), detail),
)
except Exception:
pass
def _on_upload_active(self) -> None:
"""Lädt den aktiven Layer (und Geschwister-Layer) zum Server hoch."""
if self.vln_logic is None:
return
# Zusammenfassung für Bestaetigungs-Dialog ermitteln
try:
from sn_basis.functions.qgisui_wrapper import iface as _iface
active_layer = _iface.activeLayer() if _iface else None
except Exception:
active_layer = None
summary = self.vln_logic.upload_summary(active_layer)
if summary is None:
QMessageBox.warning(
self,
"Hochladen nicht möglich",
"Der aktive Layer wurde nicht über 'vln_karten' geladen.",
)
return
try:
answer = QMessageBox.question(
self,
"Zum Server hochladen",
"%s für VKZ %s übertragen?\n\n%s\n\n"
"%d Objekte; der bisherige Bestand dieser VKZ wird ersetzt."
% (
summary["dataset_label"],
summary["vkz"],
summary["listing"],
summary["total"],
),
)
yes = getattr(
getattr(QMessageBox, "StandardButton", QMessageBox),
"Yes",
QMessageBox.Yes if hasattr(QMessageBox, "Yes") else None,
)
if answer != yes:
return
except Exception:
return
try:
success, message = self.vln_logic.upload_active_layer(active_layer)
except Exception as exc:
try:
from sn_plan41.modules.vln_api_client import AuthError as _AuthError
if isinstance(exc, _AuthError):
self.vln_logic.handle_session_expired()
self._on_vln_logout()
QMessageBox.warning(
self,
"Sitzung abgelaufen",
"Der API-Key ist nicht mehr gültig — bitte neu anmelden.",
)
return
except ImportError:
pass
QMessageBox.warning(self, "Hochladen fehlgeschlagen", str(exc))
return
if success:
try:
from sn_basis.functions.message_wrapper import info
info("Upload erfolgreich", message)
except Exception:
pass
else:
QMessageBox.warning(self, "Hochladen fehlgeschlagen", message)
def _toggle_group(self, checked: bool) -> None:
"""Zeigt/verbirgt Verfahrens-DB-Gruppe."""
self.group_button.setArrowType(ArrowDown if checked else ArrowRight)
@@ -249,20 +587,6 @@ class TabA(QWidget):
self.lokale_linkliste = path
set_variable("tab_a_linkliste", path, scope="project")
def _on_layer_changed(self, layer) -> None:
"""Persistiert Layer-Auswahl und registriert Verfahrensgebiet."""
self._pufferlayer = layer
if not layer:
return
# UI-State speichern
set_variable("tab_a_layer_id", layer.id(), scope="project")
# 🔹 NEU: Verfahrensgebiet explizit registrieren
if self.logic:
self.logic.save_verfahrensgebiet_layer(layer)
def _on_raumfilter_changed(self, value: str) -> None:
"""Persistieret Raumfilter-Auswahl."""
@@ -296,15 +620,6 @@ class TabA(QWidget):
source = self.file_widget.filePath()
raumfilter = self._raumfilter_combo.currentText()
linkliste = self.linkliste_widget.filePath()
if self.logic and self.layer_combo:
layer = self.layer_combo.currentLayer()
else:
layer = None
if layer and layer.name() == "Verfahrensgebiet":
self.logic.save_verfahrensgebiet_layer(layer)
if self.logic:
try:
self.logic._on_run_pipeline(source, linkliste, raumfilter)
+15
View File
@@ -1,9 +1,24 @@
"""sn_plan41/ui/tabs/tab_b.py Beispiel-Tab für zusätzliche Funktionen.
Ein Tab für zukünftige Erweiterungen.
"""
from qgis.PyQt.QtWidgets import QWidget, QVBoxLayout, QLabel, QTextEdit
class TabB(QWidget):
"""Beispiel-Tab für sn_plan41.
Attributes:
tab_title: Anzeigetitel des Tabs ("Tab B")
"""
tab_title = "Tab B"
def __init__(self, parent=None):
"""Initialisiert den Tab mit Beispielinhalt.
Args:
parent: Übergeordnetes Widget
"""
super().__init__(parent)
layout = QVBoxLayout()
layout.addWidget(QLabel("Plugin2 Tab B"))