diff --git a/arho_feature_template/core/plan_manager.py b/arho_feature_template/core/plan_manager.py index b5b2ebb..232ac70 100644 --- a/arho_feature_template/core/plan_manager.py +++ b/arho_feature_template/core/plan_manager.py @@ -5,20 +5,12 @@ from arho_feature_template.core.update_plan import LandUsePlan, update_selected_plan from arho_feature_template.gui.load_plan_dialog import LoadPlanDialog from arho_feature_template.utils.db_utils import get_existing_database_connection_names -from arho_feature_template.utils.misc_utils import handle_unsaved_changes +from arho_feature_template.utils.misc_utils import get_layer_by_name, handle_unsaved_changes class PlanManager: def __init__(self): - self.kaava_layer = self.get_layer_by_name("Kaava") - - def get_layer_by_name(self, layer_name): - """Retrieve a layer by name from the project.""" - layers = QgsProject.instance().mapLayersByName(layer_name) - if layers: - return layers[0] - iface.messageBar().pushMessage("Error", f"Layer '{layer_name}' not found", level=3) - return None + self.kaava_layer = get_layer_by_name("Kaava") def add_new_plan(self): """Initiate the process to add a new plan to the Kaava layer.""" diff --git a/arho_feature_template/core/plan_regulation_config.py b/arho_feature_template/core/plan_regulation_config.py index dd00842..fe2edce 100644 --- a/arho_feature_template/core/plan_regulation_config.py +++ b/arho_feature_template/core/plan_regulation_config.py @@ -8,16 +8,15 @@ from typing import TYPE_CHECKING, cast import yaml -from qgis.core import QgsProject from qgis.utils import iface from arho_feature_template.qgis_plugin_tools.tools.resources import resources_path +from arho_feature_template.utils.misc_utils import get_layer_by_name if TYPE_CHECKING: from numbers import Number from typing import Literal - from qgis.core import QgsMapLayer from qgis.gui import QgisInterface iface: QgisInterface = cast("QgisInterface", iface) # type: ignore[no-redef] @@ -56,16 +55,6 @@ class Unit(Enum): DECIBEL = "dB" -# TODO: Same as in PlanManager, should refactor -def get_layer_by_name(layer_name: str) -> QgsMapLayer | None: - """Retrieve a layer by name from the project.""" - layers = QgsProject.instance().mapLayersByName(layer_name) - if layers: - return layers[0] - iface.messageBar().pushMessage("Error", f"Layer '{layer_name}' not found", level=3) - return None - - def get_name_mapping_for_plan_regulations(layer_name: str) -> dict[str, dict[str, str]] | None: layer = get_layer_by_name(layer_name) if not layer: @@ -188,7 +177,9 @@ class PlanRegulationDefinition: regulation_config: PlanRegulationConfig default_value: str | Number | None - additional_info: dict[str, str | Number | None] # NOTE: Correct typing for additional information values? + additional_information: list[ + dict[str, str | Number | None] + ] # NOTE: Correct typing for additional information values? regulation_number: int | None attached_files: list[Path] @@ -197,7 +188,7 @@ def from_dict(cls, data: dict) -> PlanRegulationDefinition: return cls( regulation_config=data["config"], default_value=data.get("default_value"), - additional_info=data.get("additional_info", {}), + additional_information=data.get("additional_information", []), regulation_number=data.get("regulation_number"), attached_files=data.get("attached_files", []), ) diff --git a/arho_feature_template/gui/plan_regulation_widget.py b/arho_feature_template/gui/plan_regulation_widget.py index 36a23c7..6f0fdbd 100644 --- a/arho_feature_template/gui/plan_regulation_widget.py +++ b/arho_feature_template/gui/plan_regulation_widget.py @@ -2,7 +2,7 @@ from collections import defaultdict from importlib import resources -from typing import TYPE_CHECKING +from typing import TYPE_CHECKING, cast from qgis.core import QgsApplication from qgis.gui import QgsDoubleSpinBox, QgsFileWidget, QgsSpinBox @@ -20,6 +20,7 @@ ) from arho_feature_template.core.plan_regulation_config import PlanRegulationConfig, Unit, ValueType +from arho_feature_template.utils.misc_utils import get_additional_information_name if TYPE_CHECKING: from numbers import Number @@ -28,7 +29,7 @@ from arho_feature_template.core.plan_regulation_group_config import PlanRegulationDefinition -ui_path = resources.files(__package__) / "new_plan_regulation_widget.ui" +ui_path = resources.files(__package__) / "plan_regulation_widget.ui" FormClass, _ = uic.loadUiType(ui_path) @@ -41,6 +42,9 @@ TEXT_VALUE_FIELD = "text_value" REGULATION_TYPE_ADDITIONAL_INFORMATION_ID = "regulation_type_additional_information_id" +# TO BE REPLACED +ADDITIONAL_INFORMATION_TYPES_WITH_INPUT = ["kayttotarkoituskohdistus"] + class PlanRegulationWidget(QWidget, FormClass): # type: ignore """A widget representation of a plan regulation.""" @@ -73,7 +77,18 @@ def __init__(self, config: PlanRegulationConfig, parent=None): self.init_buttons() def populate_from_definition(self, definition: PlanRegulationDefinition): - pass + # Additional information + for info in definition.additional_information: + info_type: str = cast("str", info["type"]) + layout = self.add_additional_info(info_type) + if info_type in ADDITIONAL_INFORMATION_TYPES_WITH_INPUT: + info_value_widget = QLineEdit() + layout.addWidget(info_value_widget) + value = info.get("value") + if value: + info_value_widget.setText(value) + + # TODO: Other saved information from PlanRegulationDefinition def init_value_fields(self): layout = QHBoxLayout() @@ -186,10 +201,14 @@ def add_versioned_text_input(self, layout: QHBoxLayout): layout.addWidget(text_widget) self.form_layout.addRow("Kieliversioitu teksti", layout) - def add_additional_info(self, info_type): - info_type_label = QLineEdit(info_type) + def add_additional_info(self, info_type: str) -> QHBoxLayout: + layout = QHBoxLayout() + info_name = get_additional_information_name(info_type) + info_type_label = QLineEdit(info_name) info_type_label.setReadOnly(True) - self.form_layout.addRow("Lisätiedonlaji", info_type_label) + layout.addWidget(info_type_label) + self.form_layout.addRow("Lisätiedonlaji", layout) + return layout def add_regulation_number(self): if not self.regulation_number_added: diff --git a/arho_feature_template/utils/misc_utils.py b/arho_feature_template/utils/misc_utils.py index b9fe118..708ea3d 100644 --- a/arho_feature_template/utils/misc_utils.py +++ b/arho_feature_template/utils/misc_utils.py @@ -1,12 +1,54 @@ +from __future__ import annotations + import os +from typing import TYPE_CHECKING, cast from qgis.core import QgsExpressionContextUtils, QgsProject, QgsVectorLayer from qgis.PyQt.QtCore import QSettings from qgis.PyQt.QtWidgets import QMessageBox +from qgis.utils import iface + +if TYPE_CHECKING: + from typing import Literal + + from qgis.core import QgsMapLayer + from qgis.gui import QgisInterface + + iface: QgisInterface = cast("QgisInterface", iface) # type: ignore[no-redef] PLUGIN_PATH = os.path.dirname(os.path.dirname(__file__)) +# NOTE: Consider creating "layer_utils.py" or similar for layer related utils in the future +def get_layer_by_name(layer_name: str) -> QgsMapLayer | None: + """ + Retrieve a layer by name from the project. + + If multiple layers with the same name exist, returns the first one. Returns None + if layer with a matching name is not found. + """ + layers = QgsProject.instance().mapLayersByName(layer_name) + if layers: + return layers[0] + iface.messageBar().pushWarning("Error", f"Layer '{layer_name}' not found") + return None + + +def get_additional_information_name(info_type: str, language: Literal["fin", "eng", "swe"] = "fin") -> str: + """ + Retrieve name of input additional information type from associated QGIS layer. + + Returns input `info_type` if name is not found. + """ + type_of_additional_information_layer_name = "Lisätiedonlaji" + layer = get_layer_by_name(type_of_additional_information_layer_name) + if layer: + for feature in layer.getFeatures(): + if feature["value"] == info_type: + return feature["name"][language] + return info_type + + def check_layer_changes() -> bool: """Check if there are unsaved changes in any QGIS layers.""" project = QgsProject.instance()