Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Kaavakohteiden ja kaavan muokkaaminen #112

Merged
merged 6 commits into from
Jan 21, 2025
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 63 additions & 14 deletions arho_feature_template/core/plan_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
from arho_feature_template.gui.dialogs.plan_feature_form import PlanFeatureForm
from arho_feature_template.gui.dialogs.serialize_plan import SerializePlan
from arho_feature_template.gui.docks.new_feature_dock import NewFeatureDock
from arho_feature_template.gui.tools.inspect_plan_features_tool import InspectPlanFeatures
from arho_feature_template.project.layers.code_layers import PlanRegulationGroupTypeLayer
from arho_feature_template.project.layers.plan_layers import (
LandUseAreaLayer,
Expand Down Expand Up @@ -55,10 +56,10 @@

FEATURE_LAYER_NAME_TO_CLASS_MAP: dict[str, type[PlanFeatureLayer]] = {
LandUsePointLayer.name: LandUsePointLayer,
OtherAreaLayer.name: OtherAreaLayer,
OtherPointLayer.name: OtherPointLayer,
LandUseAreaLayer.name: LandUseAreaLayer,
LineLayer.name: LineLayer,
OtherAreaLayer.name: OtherAreaLayer,
LandUseAreaLayer.name: LandUseAreaLayer,
}


Expand Down Expand Up @@ -95,6 +96,19 @@ def __init__(self):
self.feature_digitize_map_tool = None
self.initialize_feature_digitize_map_tool()

# Initialize plan feature inspect tool
self.inspect_plan_feature_tool = InspectPlanFeatures(
iface.mapCanvas(), list(FEATURE_LAYER_NAME_TO_CLASS_MAP.values())
)
self.inspect_plan_feature_tool.edit_feature_requested.connect(self.edit_plan_feature)

def toggle_identify_plan_features(self, activate: bool): # noqa: FBT001
if activate:
self.previous_map_tool = iface.mapCanvas().mapTool()
iface.mapCanvas().setMapTool(self.inspect_plan_feature_tool)
else:
iface.mapCanvas().setMapTool(self.previous_map_tool)

def initialize_feature_digitize_map_tool(self, layer: QgsVectorLayer | None = None):
# Get matcing capture mode for given layer
if layer is None:
Expand Down Expand Up @@ -200,6 +214,18 @@ def _plan_feature_geom_digitized(self, feature: QgsFeature):
if attribute_form.exec_():
save_plan_feature(attribute_form.model)

def edit_plan_feature(self, feature: QgsFeature, layer_name: str):
layer_class = FEATURE_LAYER_NAME_TO_CLASS_MAP[layer_name]
plan_feature = layer_class.model_from_feature(feature)

# Geom editing handled with basic QGIS vertex editing?
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()]
)
if attribute_form.exec_():
save_plan_feature(attribute_form.model)

def set_active_plan(self, plan_id: str | None):
"""Update the project layers based on the selected land use plan.

Expand Down Expand Up @@ -342,6 +368,17 @@ def _save_feature(feature: QgsFeature, layer: QgsVectorLayer, id_: int | None, e
layer.commitChanges(stopEditing=False)


def _delete_feature(feature: QgsFeature, layer: QgsVectorLayer, delete_text: str = ""):
if not layer.isEditable():
layer.startEditing()
layer.beginEditCommand(delete_text)

layer.deleteFeature(feature.id())

layer.endEditCommand()
layer.commitChanges(stopEditing=False)


def save_plan(plan_data: Plan) -> QgsFeature:
plan_layer = PlanLayer.get_from_project()
in_edit_mode = plan_layer.isEditable()
Expand Down Expand Up @@ -372,29 +409,41 @@ def save_plan(plan_data: Plan) -> QgsFeature:


def save_plan_feature(plan_feature: PlanFeature, plan_id: str | None = None) -> QgsFeature:
if not plan_feature.layer_name:
layer_name = plan_feature.layer_name
if not layer_name:
msg = "Cannot save plan feature without a target layer"
raise ValueError(msg)
layer_class = FEATURE_LAYER_NAME_TO_CLASS_MAP.get(plan_feature.layer_name)
layer_class = FEATURE_LAYER_NAME_TO_CLASS_MAP.get(layer_name)
if not layer_class:
msg = f"Could not find plan feature layer class for layer name {plan_feature.layer_name}"
msg = f"Could not find plan feature layer class for layer name {layer_name}"
raise ValueError(msg)

feature = layer_class.feature_from_model(plan_feature, plan_id)
layer = layer_class.get_from_project()

editing = plan_feature.id_ is not None
_save_feature(
feature=feature,
layer=layer,
id_=plan_feature.id_,
edit_text="Kaavakohteen lisäys" if plan_feature.id_ is None else "Kaavakohteen muokkaus",
edit_text="Kaavakohteen muokkaus" if editing else "Kaavakohteen lisäys",
)

# Handle regulation groups
if plan_feature.regulation_groups:
for group in plan_feature.regulation_groups:
regulation_group_feature = save_regulation_group(group)
save_regulation_group_association(regulation_group_feature["id"], plan_feature.layer_name, feature["id"])
# Check for deleted regulation groups
if editing:
for association in RegulationGroupAssociationLayer.get_dangling_associations(
plan_feature.regulation_groups, feature["id"], layer_name
):
_delete_feature(
association,
RegulationGroupAssociationLayer.get_from_project(),
"Kaavamääräysryhmän assosiaation poisto",
)

# Save regulation groups
for group in plan_feature.regulation_groups:
regulation_group_feature = save_regulation_group(group)
save_regulation_group_association(regulation_group_feature["id"], layer_name, feature["id"])

return feature

Expand Down Expand Up @@ -423,14 +472,14 @@ def save_regulation_group_as_config(regulation_group: RegulationGroup):
pass


def save_regulation_group_association(regulation_group_id: str, layer_name: str, feature_id: str) -> QgsFeature:
def save_regulation_group_association(regulation_group_id: str, layer_name: str, feature_id: str):
feature = RegulationGroupAssociationLayer.feature_from(regulation_group_id, layer_name, feature_id)
if not feature:
return
layer = RegulationGroupAssociationLayer.get_from_project()

_save_feature(feature=feature, layer=layer, id_=None, edit_text="Kaavamääräysryhmän assosiaation lisäys")

return feature


def save_regulation(regulation: Regulation) -> QgsFeature:
feature = PlanRegulationLayer.feature_from_model(regulation)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,6 @@
if TYPE_CHECKING:
from qgis.PyQt.QtWidgets import QFormLayout, QFrame, QLabel, QLineEdit, QPushButton

from arho_feature_template.gui.components.code_combobox import CodeComboBox

ui_path = resources.files(__package__) / "plan_regulation_group_widget.ui"
FormClass, _ = uic.loadUiType(ui_path)

Expand All @@ -26,11 +24,7 @@ class RegulationGroupWidget(QWidget, FormClass): # type: ignore

delete_signal = pyqtSignal(QWidget)

def __init__(
self,
regulation_group_data: RegulationGroup,
general_regulation: bool = False, # noqa: FBT001, FBT002
):
def __init__(self, regulation_group_data: RegulationGroup, layer_name: str):
super().__init__()
self.setupUi(self)

Expand All @@ -40,40 +34,15 @@ def __init__(
self.short_name: QLineEdit
self.short_name_label: QLabel
self.del_btn: QPushButton
self.type_of_regulation_group_label: QLabel
self.type_of_regulation_group: CodeComboBox
self.regulation_group_details_layout: QFormLayout
# NOTE: Maybe user input is not needed and wanted for type of plan regulation group and it would be defined
# by the plan feature directly (and hidden from user)

# INIT
self.is_general_regulation = general_regulation
self.regulation_group_data = regulation_group_data
self.regulation_widgets: list[RegulationWidget] = [
self.add_regulation_widget(regulation) for regulation in self.regulation_group_data.regulations
]

# If regulation group type code is defined, delete selection for user
if self.is_general_regulation:
regulation_group_data.type_code_id = PlanRegulationGroupTypeLayer.get_id_of_regulation_type(
"generalRegulations"
)
# Remove short name row
self.regulation_group_details_layout.removeWidget(self.short_name_label)
self.regulation_group_details_layout.removeWidget(self.short_name)
self.short_name_label.deleteLater()
self.short_name.deleteLater()

if regulation_group_data.type_code_id:
# Remove type of plan regulation group row
self.regulation_group_details_layout.removeWidget(self.type_of_regulation_group_label)
self.regulation_group_details_layout.removeWidget(self.type_of_regulation_group)
self.type_of_regulation_group_label.deleteLater()
self.type_of_regulation_group.deleteLater()
else:
self.type_of_regulation_group.populate_from_code_layer(PlanRegulationGroupTypeLayer)
self.type_of_regulation_group.removeItem(0) # Remove NULL from combobox as underground data is required

regulation_group_data.type_code_id = PlanRegulationGroupTypeLayer.get_id_by_feature_layer_name(layer_name)
self.name.setText(self.regulation_group_data.name if self.regulation_group_data.name else "")
self.short_name.setText(self.regulation_group_data.short_name if self.regulation_group_data.short_name else "")
self.del_btn.setIcon(QgsApplication.getThemeIcon("mActionDeleteSelected.svg"))
Expand All @@ -92,11 +61,9 @@ def delete_regulation_widget(self, regulation_widget: RegulationWidget):

def into_model(self) -> RegulationGroup:
return RegulationGroup(
type_code_id=self.regulation_group_data.type_code_id
if self.regulation_group_data.type_code_id
else self.type_of_regulation_group.value(),
type_code_id=self.regulation_group_data.type_code_id,
name=self.name.text(),
short_name=None if self.is_general_regulation else self.short_name.text(),
short_name=None if not self.short_name.text() else self.short_name.text(),
color_code=self.regulation_group_data.color_code,
regulations=[widget.into_model() for widget in self.regulation_widgets],
id_=self.regulation_group_data.id_,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>420</width>
<height>160</height>
<height>129</height>
</rect>
</property>
<property name="sizePolicy">
Expand Down Expand Up @@ -117,34 +117,6 @@
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="type_of_regulation_group_label">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>Tyyppi</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="CodeComboBox" name="type_of_regulation_group"/>
</item>
<item row="1" column="0">
<widget class="QLabel" name="short_name_label">
<property name="text">
Expand All @@ -162,13 +134,6 @@
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>CodeComboBox</class>
<extends>QComboBox</extends>
<header>arho_feature_template.gui.components.code_combobox</header>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>
2 changes: 1 addition & 1 deletion arho_feature_template/gui/dialogs/plan_attribute_form.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ def add_selected_plan_regulation_group(self, item: QTreeWidgetItem, column: int)
self.add_plan_regulation_group(regulation_group)

def add_plan_regulation_group(self, regulation_group: RegulationGroup):
regulation_group_widget = RegulationGroupWidget(regulation_group, general_regulation=True)
regulation_group_widget = RegulationGroupWidget(regulation_group, layer_name="Kaava")
regulation_group_widget.delete_signal.connect(self.remove_plan_regulation_group)
self._remove_spacer()
self.plan_regulation_group_scrollarea_contents.layout().addWidget(regulation_group_widget)
Expand Down
7 changes: 4 additions & 3 deletions arho_feature_template/gui/dialogs/plan_feature_form.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from __future__ import annotations

from importlib import resources
from typing import TYPE_CHECKING
from typing import TYPE_CHECKING, cast

from qgis.PyQt import uic
from qgis.PyQt.QtCore import Qt
Expand Down Expand Up @@ -76,7 +76,8 @@ def __init__(

# Initialize attributes from template
self.plan_feature = plan_feature
self.layer_name = plan_feature.layer_name # Should have a layer name
self.layer_name = plan_feature.layer_name # Should always have a layer name

if plan_feature.name:
self.feature_name.setText(plan_feature.name)
if plan_feature.description:
Expand All @@ -102,7 +103,7 @@ def add_selected_plan_regulation_group(self, item: QTreeWidgetItem, column: int)
self.add_plan_regulation_group(regulation_group)

def add_plan_regulation_group(self, definition: RegulationGroup):
regulation_group_widget = RegulationGroupWidget(definition)
regulation_group_widget = RegulationGroupWidget(definition, cast(str, self.layer_name))
regulation_group_widget.delete_signal.connect(self.remove_plan_regulation_group)
self._remove_spacer()
self.plan_regulation_group_scrollarea_contents.layout().addWidget(regulation_group_widget)
Expand Down
Empty file.
Loading
Loading