11
11
from arho_feature_template .core .lambda_service import LambdaService
12
12
from arho_feature_template .core .models import (
13
13
FeatureTemplateLibrary ,
14
+ Plan ,
14
15
PlanFeature ,
15
16
RegulationGroupCategory ,
16
17
RegulationGroupLibrary ,
22
23
from arho_feature_template .gui .dialogs .plan_feature_form import PlanFeatureForm
23
24
from arho_feature_template .gui .dialogs .serialize_plan import SerializePlan
24
25
from arho_feature_template .gui .docks .new_feature_dock import NewFeatureDock
26
+ from arho_feature_template .gui .tools .inspect_plan_features_tool import InspectPlanFeatures
25
27
from arho_feature_template .project .layers .code_layers import PlanRegulationGroupTypeLayer
26
28
from arho_feature_template .project .layers .plan_layers import (
27
29
LandUseAreaLayer ,
49
51
if TYPE_CHECKING :
50
52
from qgis .core import QgsFeature
51
53
52
- from arho_feature_template .core .models import Plan , Regulation , RegulationGroup
54
+ from arho_feature_template .core .models import Regulation , RegulationGroup
53
55
54
56
logger = logging .getLogger (__name__ )
55
57
56
58
FEATURE_LAYER_NAME_TO_CLASS_MAP : dict [str , type [PlanFeatureLayer ]] = {
57
59
LandUsePointLayer .name : LandUsePointLayer ,
58
- OtherAreaLayer .name : OtherAreaLayer ,
59
60
OtherPointLayer .name : OtherPointLayer ,
60
- LandUseAreaLayer .name : LandUseAreaLayer ,
61
61
LineLayer .name : LineLayer ,
62
+ OtherAreaLayer .name : OtherAreaLayer ,
63
+ LandUseAreaLayer .name : LandUseAreaLayer ,
62
64
}
63
65
64
66
@@ -95,6 +97,19 @@ def __init__(self):
95
97
self .feature_digitize_map_tool = None
96
98
self .initialize_feature_digitize_map_tool ()
97
99
100
+ # Initialize plan feature inspect tool
101
+ self .inspect_plan_feature_tool = InspectPlanFeatures (
102
+ iface .mapCanvas (), list (FEATURE_LAYER_NAME_TO_CLASS_MAP .values ())
103
+ )
104
+ self .inspect_plan_feature_tool .edit_feature_requested .connect (self .edit_plan_feature )
105
+
106
+ def toggle_identify_plan_features (self , activate : bool ): # noqa: FBT001
107
+ if activate :
108
+ self .previous_map_tool = iface .mapCanvas ().mapTool ()
109
+ iface .mapCanvas ().setMapTool (self .inspect_plan_feature_tool )
110
+ else :
111
+ iface .mapCanvas ().setMapTool (self .previous_map_tool )
112
+
98
113
def initialize_feature_digitize_map_tool (self , layer : QgsVectorLayer | None = None ):
99
114
# Get matcing capture mode for given layer
100
115
if layer is None :
@@ -140,6 +155,22 @@ def add_new_plan(self):
140
155
self .digitize_map_tool .setLayer (plan_layer )
141
156
iface .mapCanvas ().setMapTool (self .digitize_map_tool )
142
157
158
+ def edit_plan (self ):
159
+ plan_layer = PlanLayer .get_from_project ()
160
+ if not plan_layer :
161
+ return
162
+
163
+ active_plan_id = QgsExpressionContextUtils .projectScope (QgsProject .instance ()).variable ("active_plan_id" )
164
+ feature = PlanLayer .get_feature_by_id (active_plan_id , no_geometries = False )
165
+ if feature is None :
166
+ iface .messageBar ().pushWarning ("" , "No active/open plan found!" )
167
+ return
168
+ plan_model = PlanLayer .model_from_feature (feature )
169
+
170
+ attribute_form = PlanAttributeForm (plan_model , self .regulation_group_libraries )
171
+ if attribute_form .exec_ ():
172
+ feature = save_plan (attribute_form .model )
173
+
143
174
def add_new_plan_feature (self ):
144
175
if not handle_unsaved_changes ():
145
176
return
@@ -166,11 +197,10 @@ def _plan_geom_digitized(self, feature: QgsFeature):
166
197
if not plan_layer :
167
198
return
168
199
169
- attribute_form = PlanAttributeForm (self .regulation_group_libraries )
200
+ plan_model = Plan (geom = feature .geometry ())
201
+ attribute_form = PlanAttributeForm (plan_model , self .regulation_group_libraries )
170
202
if attribute_form .exec_ ():
171
- plan_attributes = attribute_form .get_plan_attributes ()
172
- plan_attributes .geom = feature .geometry ()
173
- feature = save_plan (plan_attributes )
203
+ feature = save_plan (attribute_form .model )
174
204
plan_to_be_activated = feature ["id" ]
175
205
else :
176
206
plan_to_be_activated = self .previous_active_plan_id
@@ -200,6 +230,18 @@ def _plan_feature_geom_digitized(self, feature: QgsFeature):
200
230
if attribute_form .exec_ ():
201
231
save_plan_feature (attribute_form .model )
202
232
233
+ def edit_plan_feature (self , feature : QgsFeature , layer_name : str ):
234
+ layer_class = FEATURE_LAYER_NAME_TO_CLASS_MAP [layer_name ]
235
+ plan_feature = layer_class .model_from_feature (feature )
236
+
237
+ # Geom editing handled with basic QGIS vertex editing?
238
+ title = plan_feature .name if plan_feature .name else layer_name
239
+ attribute_form = PlanFeatureForm (
240
+ plan_feature , title , [* self .regulation_group_libraries , regulation_group_library_from_active_plan ()]
241
+ )
242
+ if attribute_form .exec_ ():
243
+ save_plan_feature (attribute_form .model )
244
+
203
245
def set_active_plan (self , plan_id : str | None ):
204
246
"""Update the project layers based on the selected land use plan.
205
247
@@ -342,59 +384,86 @@ def _save_feature(feature: QgsFeature, layer: QgsVectorLayer, id_: int | None, e
342
384
layer .commitChanges (stopEditing = False )
343
385
344
386
345
- def save_plan (plan_data : Plan ) -> QgsFeature :
346
- plan_layer = PlanLayer .get_from_project ()
347
- in_edit_mode = plan_layer .isEditable ()
348
- if not in_edit_mode :
349
- plan_layer .startEditing ()
387
+ def _delete_feature (feature : QgsFeature , layer : QgsVectorLayer , delete_text : str = "" ):
388
+ if not layer .isEditable ():
389
+ layer .startEditing ()
390
+ layer .beginEditCommand (delete_text )
350
391
351
- edit_message = "Kaavan lisäys" if plan_data .id_ is None else "Kaavan muokkaus"
352
- plan_layer .beginEditCommand (edit_message )
392
+ layer .deleteFeature (feature .id ())
353
393
354
- # plan_data.organisation_id = "99e20d66-9730-4110-815f-5947d3f8abd3"
355
- plan_feature = PlanLayer . feature_from_model ( plan_data )
394
+ layer . endEditCommand ()
395
+ layer . commitChanges ( stopEditing = False )
356
396
357
- if plan_data .id_ is None :
358
- plan_layer .addFeature (plan_feature )
359
- else :
360
- plan_layer .updateFeature (plan_feature )
361
397
362
- plan_layer .endEditCommand ()
363
- plan_layer .commitChanges (stopEditing = False )
398
+ def save_plan (plan : Plan ) -> QgsFeature :
399
+ feature = PlanLayer .feature_from_model (plan )
400
+ layer = PlanLayer .get_from_project ()
401
+
402
+ editing = plan .id_ is not None
403
+ _save_feature (
404
+ feature = feature ,
405
+ layer = layer ,
406
+ id_ = plan .id_ ,
407
+ edit_text = "Kaavan muokkaus" if editing else "Kaavan luominen" ,
408
+ )
409
+
410
+ # Check for deleted general regulations
411
+ if editing :
412
+ for association in RegulationGroupAssociationLayer .get_dangling_associations (
413
+ plan .general_regulations , feature ["id" ], PlanLayer .name
414
+ ):
415
+ _delete_feature (
416
+ association ,
417
+ RegulationGroupAssociationLayer .get_from_project (),
418
+ "Kaavamääräysryhmän assosiaation poisto" ,
419
+ )
364
420
365
- if plan_data .general_regulations :
366
- for regulation_group in plan_data .general_regulations :
367
- plan_id = plan_feature ["id" ]
421
+ # Save general regulations
422
+ if plan .general_regulations :
423
+ for regulation_group in plan .general_regulations :
424
+ plan_id = feature ["id" ]
368
425
regulation_group_feature = save_regulation_group (regulation_group , plan_id )
369
426
save_regulation_group_association (regulation_group_feature ["id" ], PlanLayer .name , plan_id )
370
427
371
- return plan_feature
428
+ return feature
372
429
373
430
374
431
def save_plan_feature (plan_feature : PlanFeature , plan_id : str | None = None ) -> QgsFeature :
375
- if not plan_feature .layer_name :
432
+ layer_name = plan_feature .layer_name
433
+ if not layer_name :
376
434
msg = "Cannot save plan feature without a target layer"
377
435
raise ValueError (msg )
378
- layer_class = FEATURE_LAYER_NAME_TO_CLASS_MAP .get (plan_feature . layer_name )
436
+ layer_class = FEATURE_LAYER_NAME_TO_CLASS_MAP .get (layer_name )
379
437
if not layer_class :
380
- msg = f"Could not find plan feature layer class for layer name { plan_feature . layer_name } "
438
+ msg = f"Could not find plan feature layer class for layer name { layer_name } "
381
439
raise ValueError (msg )
382
440
383
441
feature = layer_class .feature_from_model (plan_feature , plan_id )
384
442
layer = layer_class .get_from_project ()
385
443
444
+ editing = plan_feature .id_ is not None
386
445
_save_feature (
387
446
feature = feature ,
388
447
layer = layer ,
389
448
id_ = plan_feature .id_ ,
390
- edit_text = "Kaavakohteen lisäys " if plan_feature . id_ is None else "Kaavakohteen muokkaus " ,
449
+ edit_text = "Kaavakohteen muokkaus " if editing else "Kaavakohteen lisäys " ,
391
450
)
392
451
393
- # Handle regulation groups
394
- if plan_feature .regulation_groups :
395
- for group in plan_feature .regulation_groups :
396
- regulation_group_feature = save_regulation_group (group )
397
- save_regulation_group_association (regulation_group_feature ["id" ], plan_feature .layer_name , feature ["id" ])
452
+ # Check for deleted regulation groups
453
+ if editing :
454
+ for association in RegulationGroupAssociationLayer .get_dangling_associations (
455
+ plan_feature .regulation_groups , feature ["id" ], layer_name
456
+ ):
457
+ _delete_feature (
458
+ association ,
459
+ RegulationGroupAssociationLayer .get_from_project (),
460
+ "Kaavamääräysryhmän assosiaation poisto" ,
461
+ )
462
+
463
+ # Save regulation groups
464
+ for group in plan_feature .regulation_groups :
465
+ regulation_group_feature = save_regulation_group (group )
466
+ save_regulation_group_association (regulation_group_feature ["id" ], layer_name , feature ["id" ])
398
467
399
468
return feature
400
469
@@ -423,14 +492,14 @@ def save_regulation_group_as_config(regulation_group: RegulationGroup):
423
492
pass
424
493
425
494
426
- def save_regulation_group_association (regulation_group_id : str , layer_name : str , feature_id : str ) -> QgsFeature :
495
+ def save_regulation_group_association (regulation_group_id : str , layer_name : str , feature_id : str ):
496
+ if RegulationGroupAssociationLayer .association_exists (regulation_group_id , layer_name , feature_id ):
497
+ return
427
498
feature = RegulationGroupAssociationLayer .feature_from (regulation_group_id , layer_name , feature_id )
428
499
layer = RegulationGroupAssociationLayer .get_from_project ()
429
500
430
501
_save_feature (feature = feature , layer = layer , id_ = None , edit_text = "Kaavamääräysryhmän assosiaation lisäys" )
431
502
432
- return feature
433
-
434
503
435
504
def save_regulation (regulation : Regulation ) -> QgsFeature :
436
505
feature = PlanRegulationLayer .feature_from_model (regulation )
0 commit comments