diff --git a/arho_feature_template/core/models.py b/arho_feature_template/core/models.py
index 8b12e67..e236430 100644
--- a/arho_feature_template/core/models.py
+++ b/arho_feature_template/core/models.py
@@ -146,6 +146,15 @@ def from_config_file(cls, config_fp: Path) -> RegulationGroupLibrary:
],
)
+ def get_short_names(self) -> set[str]:
+ """Returns set of non-empty short names (letter codes) of regulation groups part of the library."""
+ return {
+ regulation_group.short_name
+ for category in self.regulation_group_categories
+ for regulation_group in category.regulation_groups
+ if regulation_group.short_name
+ }
+
@dataclass
class RegulationLibrary:
diff --git a/arho_feature_template/core/plan_manager.py b/arho_feature_template/core/plan_manager.py
index 10f8088..b5c1f75 100644
--- a/arho_feature_template/core/plan_manager.py
+++ b/arho_feature_template/core/plan_manager.py
@@ -104,8 +104,7 @@ def __init__(self):
self.regulation_groups_dock.new_regulation_group_requested.connect(self.create_new_regulation_group)
self.regulation_groups_dock.edit_regulation_group_requested.connect(self.edit_regulation_group)
self.regulation_groups_dock.delete_regulation_group_requested.connect(self.delete_regulation_group)
- if get_active_plan_id():
- self.regulation_groups_dock.initialize_regulation_groups(regulation_group_library_from_active_plan())
+ self.update_active_plan_regulation_group_library()
self.regulation_groups_dock.hide()
# Initialize digitize tools
@@ -156,6 +155,10 @@ def initialize_libraries(self):
]
self.new_feature_dock.initialize_feature_template_libraries(self.feature_template_libraries)
+ def update_active_plan_regulation_group_library(self):
+ self.active_plan_regulation_group_library = regulation_group_library_from_active_plan()
+ self.regulation_groups_dock.update_regulation_groups(self.active_plan_regulation_group_library)
+
def create_new_regulation_group(self):
self._open_regulation_group_form(RegulationGroup())
@@ -163,17 +166,17 @@ def edit_regulation_group(self, regulation_group: RegulationGroup):
self._open_regulation_group_form(regulation_group)
def _open_regulation_group_form(self, regulation_group: RegulationGroup):
- regulation_group_form = PlanRegulationGroupForm(regulation_group)
+ regulation_group_form = PlanRegulationGroupForm(regulation_group, self.active_plan_regulation_group_library)
if regulation_group_form.exec_():
if regulation_group_form.save_as_config:
save_regulation_group_as_config(regulation_group_form.model)
else:
save_regulation_group(regulation_group_form.model)
- self.regulation_groups_dock.initialize_regulation_groups(regulation_group_library_from_active_plan())
+ self.update_active_plan_regulation_group_library()
def delete_regulation_group(self, group: RegulationGroup):
delete_regulation_group(group)
- self.regulation_groups_dock.initialize_regulation_groups(regulation_group_library_from_active_plan())
+ self.update_active_plan_regulation_group_library()
def toggle_identify_plan_features(self, activate: bool): # noqa: FBT001
if activate:
@@ -240,7 +243,7 @@ def edit_plan(self):
attribute_form = PlanAttributeForm(plan_model, self.regulation_group_libraries)
if attribute_form.exec_():
feature = save_plan(attribute_form.model)
- self.regulation_groups_dock.initialize_regulation_groups(regulation_group_library_from_active_plan())
+ self.update_active_plan_regulation_group_library()
def edit_lifecycles(self):
plan_layer = PlanLayer.get_from_project()
@@ -311,11 +314,11 @@ def _plan_feature_geom_digitized(self, feature: QgsFeature):
plan_feature.geom = feature.geometry()
attribute_form = PlanFeatureForm(
- plan_feature, title, [*self.regulation_group_libraries, regulation_group_library_from_active_plan()]
+ plan_feature, title, self.regulation_group_libraries, self.active_plan_regulation_group_library
)
if attribute_form.exec_():
save_plan_feature(attribute_form.model)
- self.regulation_groups_dock.initialize_regulation_groups(regulation_group_library_from_active_plan())
+ self.update_active_plan_regulation_group_library()
def edit_plan_feature(self, feature: QgsFeature, layer_name: str):
layer_class = FEATURE_LAYER_NAME_TO_CLASS_MAP[layer_name]
@@ -323,11 +326,11 @@ def edit_plan_feature(self, feature: QgsFeature, layer_name: str):
title = plan_feature.name if plan_feature.name else layer_name
attribute_form = PlanFeatureForm(
- plan_feature, title, [*self.regulation_group_libraries, regulation_group_library_from_active_plan()]
+ plan_feature, title, self.regulation_group_libraries, self.active_plan_regulation_group_library
)
if attribute_form.exec_():
save_plan_feature(attribute_form.model)
- self.regulation_groups_dock.initialize_regulation_groups(regulation_group_library_from_active_plan())
+ self.update_active_plan_regulation_group_library()
def set_active_plan(self, plan_id: str | None):
"""Update the project layers based on the selected land use plan.
@@ -352,8 +355,7 @@ def set_active_plan(self, plan_id: str | None):
if previously_in_edit_mode:
plan_layer.startEditing()
- # Update regulation group dock
- self.regulation_groups_dock.initialize_regulation_groups(regulation_group_library_from_active_plan())
+ self.update_active_plan_regulation_group_library()
def load_land_use_plan(self):
"""Load an existing land use plan using a dialog selection."""
@@ -456,6 +458,11 @@ def unload(self):
def regulation_group_library_from_active_plan() -> RegulationGroupLibrary:
+ if not get_active_plan_id():
+ return RegulationGroupLibrary(
+ name="Käytössä olevat kaavamääräysryhmät", version=None, description=None, regulation_group_categories=[]
+ )
+
id_of_general_regulation_group_type = PlanRegulationGroupTypeLayer.get_attribute_value_by_another_attribute_value(
"id", "value", "generalRegulations"
)
diff --git a/arho_feature_template/gui/dialogs/plan_feature_form.py b/arho_feature_template/gui/dialogs/plan_feature_form.py
index d945fd8..1c1e24d 100644
--- a/arho_feature_template/gui/dialogs/plan_feature_form.py
+++ b/arho_feature_template/gui/dialogs/plan_feature_form.py
@@ -10,6 +10,7 @@
QDialog,
QDialogButtonBox,
QLineEdit,
+ QMessageBox,
QScrollArea,
QSizePolicy,
QSpacerItem,
@@ -39,7 +40,11 @@ class PlanFeatureForm(QDialog, FormClass): # type: ignore
"""Parent class for feature forms for adding and modifying feature attribute data."""
def __init__(
- self, plan_feature: PlanFeature, form_title: str, regulation_group_libraries: list[RegulationGroupLibrary]
+ self,
+ plan_feature: PlanFeature,
+ form_title: str,
+ regulation_group_libraries: list[RegulationGroupLibrary],
+ active_plan_regulation_groups_library: RegulationGroupLibrary,
):
super().__init__()
self.setupUi(self)
@@ -57,7 +62,9 @@ def __init__(
self.regulation_groups_tree_layout: QVBoxLayout
# INIT
- self.regulation_group_libraries = regulation_group_libraries
+ self.existing_group_short_names = active_plan_regulation_groups_library.get_short_names()
+ self.active_plan_regulation_groups_library = active_plan_regulation_groups_library
+ self.regulation_group_libraries = [*regulation_group_libraries, active_plan_regulation_groups_library]
self.plan_regulation_group_libraries_combobox.addItems(
library.name for library in self.regulation_group_libraries
)
@@ -97,6 +104,44 @@ def _remove_spacer(self):
self.plan_regulation_group_scrollarea_contents.layout().removeItem(self.scroll_area_spacer)
self.scroll_area_spacer = None
+ def _check_regulation_group_short_names(self) -> bool:
+ seen_names = set()
+ existing_names = set()
+ duplicate_names = set()
+
+ for reg_group_widget in self.regulation_group_widgets:
+ short_name = reg_group_widget.short_name.text()
+ if not short_name:
+ continue
+
+ if short_name in self.existing_group_short_names:
+ existing_names.add(short_name)
+ if short_name in seen_names:
+ duplicate_names.add(short_name)
+ seen_names.add(short_name)
+
+ def format_names(names, last_item_conjucation: str = "ja"):
+ names = list(names)
+ formatted_names = ", ".join(f"'{name}'" for name in names[:-1])
+ formatted_names += f" {last_item_conjucation} " if len(names) > 1 else ""
+ formatted_names += f"'{names[-1]}'" if names else ""
+ return formatted_names
+
+ if existing_names:
+ if len(existing_names) == 1:
+ msg = f"Kaavamääräysryhmä lyhyellä nimellä {format_names(existing_names)} on jo olemassa."
+ else:
+ msg = f"Kaavamääräysryhmät lyhyillä nimillä {format_names(existing_names)} ovat jo olemassa."
+ QMessageBox.critical(self, "Virhe", msg)
+ return False
+
+ if duplicate_names:
+ msg = f"Lomakkeella on useita kaavamääräysryhmiä, joilla on lyhyt nimi {format_names(duplicate_names, 'tai')}."
+ QMessageBox.critical(self, "Virhe", msg)
+ return False
+
+ return True
+
def add_selected_plan_regulation_group(self, item: QTreeWidgetItem, column: int):
if not item.parent():
return
@@ -113,7 +158,9 @@ def add_plan_regulation_group(self, definition: RegulationGroup):
self._add_spacer()
def open_plan_regulation_group_form(self, regulation_group_widget: RegulationGroupWidget):
- group_as_form = PlanRegulationGroupForm(regulation_group_widget.into_model())
+ group_as_form = PlanRegulationGroupForm(
+ regulation_group_widget.into_model(), self.active_plan_regulation_groups_library
+ )
if group_as_form.exec_():
regulation_group_widget.from_model(group_as_form.model)
@@ -146,5 +193,6 @@ def into_model(self) -> PlanFeature:
)
def _on_ok_clicked(self):
- self.model = self.into_model()
- self.accept()
+ if self._check_regulation_group_short_names():
+ self.model = self.into_model()
+ self.accept()
diff --git a/arho_feature_template/gui/dialogs/plan_regulation_group_form.py b/arho_feature_template/gui/dialogs/plan_regulation_group_form.py
index 4053060..a7bf234 100644
--- a/arho_feature_template/gui/dialogs/plan_regulation_group_form.py
+++ b/arho_feature_template/gui/dialogs/plan_regulation_group_form.py
@@ -12,6 +12,7 @@
QDialogButtonBox,
QHBoxLayout,
QLabel,
+ QMessageBox,
QSizePolicy,
QTextBrowser,
QTreeWidgetItem,
@@ -23,6 +24,7 @@
Regulation,
RegulationConfig,
RegulationGroup,
+ RegulationGroupLibrary,
RegulationLibrary,
)
from arho_feature_template.gui.components.plan_proposition_widget import PropositionWidget
@@ -45,7 +47,9 @@
class PlanRegulationGroupForm(QDialog, FormClass): # type: ignore
"""Form to create a new plan regulation group."""
- def __init__(self, regulation_group: RegulationGroup):
+ def __init__(
+ self, regulation_group: RegulationGroup, active_plan_regulation_groups_library: RegulationGroupLibrary
+ ):
super().__init__()
self.setupUi(self)
@@ -74,6 +78,7 @@ def __init__(self, regulation_group: RegulationGroup):
self.regulation_widgets: list[RegulationWidget] = []
self.proposition_widgets: list[PropositionWidget] = []
self.save_as_config = False
+ self.existing_group_short_names = active_plan_regulation_groups_library.get_short_names()
# Initialize regulation library
self.regulations_selection_widget = TreeWithSearchWidget()
@@ -137,6 +142,14 @@ def _initalize_regulation_from_config(self, config: RegulationConfig, parent: QT
for child_config in config.child_regulations:
self._initalize_regulation_from_config(child_config, item)
+ def _check_short_name(self) -> bool:
+ short_name = self.short_name.text()
+ if short_name and short_name in self.existing_group_short_names:
+ msg = f"Kaavamääräysryhmä lyhyellä nimellä '{short_name}' on jo olemassa."
+ QMessageBox.critical(self, "Virhe", msg)
+ return False
+ return True
+
def update_selected_regulation(self, item: QTreeWidgetItem, column: int):
config: RegulationConfig = item.data(column, Qt.UserRole) # Retrieve the associated config
self.regulation_info.setText(config.description)
@@ -190,5 +203,6 @@ def into_model(self) -> RegulationGroup:
)
def _on_ok_clicked(self):
- self.model = self.into_model()
- self.accept()
+ if self._check_short_name():
+ self.model = self.into_model()
+ self.accept()
diff --git a/arho_feature_template/gui/docks/regulation_groups_dock.py b/arho_feature_template/gui/docks/regulation_groups_dock.py
index 6e525a6..b388dd7 100644
--- a/arho_feature_template/gui/docks/regulation_groups_dock.py
+++ b/arho_feature_template/gui/docks/regulation_groups_dock.py
@@ -64,7 +64,7 @@ def connect_buttons(self):
self.edit_btn.clicked.connect(self.on_edit_btn_clicked)
self.delete_btn.clicked.connect(self.on_delete_btn_clicked)
- def initialize_regulation_groups(self, regulation_group_library: RegulationGroupLibrary):
+ def update_regulation_groups(self, regulation_group_library: RegulationGroupLibrary):
self.regulation_group_list.clear()
for category in regulation_group_library.regulation_group_categories: