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

Sekalaista refaktorointia #165

Merged
merged 5 commits into from
Feb 4, 2025
Merged
Show file tree
Hide file tree
Changes from all 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
2 changes: 0 additions & 2 deletions arho_feature_template/core/exceptions.py

This file was deleted.

32 changes: 15 additions & 17 deletions arho_feature_template/core/plan_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import logging
from typing import TYPE_CHECKING

from qgis.core import QgsExpressionContextUtils, QgsProject, QgsVectorLayer, QgsWkbTypes
from qgis.core import QgsProject, QgsVectorLayer, QgsWkbTypes
from qgis.gui import QgsMapToolDigitizeFeature
from qgis.PyQt.QtWidgets import QDialog, QMessageBox

Expand Down Expand Up @@ -55,6 +55,7 @@
get_active_plan_id,
handle_unsaved_changes,
iface,
set_active_plan_id,
)

if TYPE_CHECKING:
Expand Down Expand Up @@ -160,7 +161,7 @@ def edit_regulation_group(self, regulation_group: RegulationGroup):
def _open_regulation_group_form(self, regulation_group: RegulationGroup):
regulation_group_form = PlanRegulationGroupForm(regulation_group)
if regulation_group_form.exec_():
if regulation_group_form.save_as_config is True:
if regulation_group_form.save_as_config:
save_regulation_group_as_config(regulation_group_form.model)
else:
save_regulation_group(regulation_group_form.model)
Expand Down Expand Up @@ -190,8 +191,8 @@ def initialize_feature_digitize_map_tool(self, layer: QgsVectorLayer | None = No

# Disconnect signals first to not trigger them unwantedly
if self.feature_digitize_map_tool:
self.feature_digitize_map_tool.digitizingCompleted.disconnect()
self.feature_digitize_map_tool.digitizingFinished.disconnect()
disconnect_signal(self.feature_digitize_map_tool.digitizingCompleted)
disconnect_signal(self.feature_digitize_map_tool.digitizingFinished)

# Reinitialize and reconnect signals
self.feature_digitize_map_tool = PlanFeatureDigitizeMapTool(mode)
Expand Down Expand Up @@ -227,8 +228,7 @@ def edit_plan(self):
if not plan_layer:
return

active_plan_id = QgsExpressionContextUtils.projectScope(QgsProject.instance()).variable("active_plan_id")
feature = PlanLayer.get_feature_by_id(active_plan_id, no_geometries=False)
feature = PlanLayer.get_feature_by_id(get_active_plan_id(), no_geometries=False)
if feature is None:
iface.messageBar().pushWarning("", "No active/open plan found!")
return
Expand Down Expand Up @@ -328,7 +328,7 @@ def set_active_plan(self, plan_id: str | None):
if previously_in_edit_mode:
plan_layer.rollBack()

QgsExpressionContextUtils.setProjectVariable(QgsProject.instance(), "active_plan_id", plan_id)
set_active_plan_id(plan_id)
for layer in plan_layers:
layer.apply_filter(plan_id)

Expand Down Expand Up @@ -494,19 +494,18 @@ def save_plan(plan: Plan) -> QgsFeature:
feature = PlanLayer.feature_from_model(plan)
layer = PlanLayer.get_from_project()

editing = plan.id_ is not None
_save_feature(
feature=feature,
layer=layer,
id_=plan.id_,
edit_text="Kaavan muokkaus" if editing else "Kaavan luominen",
edit_text="Kaavan muokkaus" if plan.id_ is not None else "Kaavan luominen",
)

plan_id = feature["id"]
if editing:
if plan.id_ is not None:
# Check for deleted general regulations
for association in RegulationGroupAssociationLayer.get_dangling_associations(
plan.general_regulations, plan_id, PlanLayer.name
plan.general_regulations, plan.id_, PlanLayer.name
):
_delete_feature(
association,
Expand All @@ -516,7 +515,7 @@ def save_plan(plan: Plan) -> QgsFeature:

# Check for documents to be deleted
doc_layer = DocumentLayer.get_from_project()
for doc_feature in DocumentLayer.get_documents_to_delete(plan.documents, plan):
for doc_feature in DocumentLayer.get_documents_to_delete(plan.documents, plan.id_):
_delete_feature(doc_feature, doc_layer, "Asiakirjan poisto")

# Save general regulations
Expand Down Expand Up @@ -577,26 +576,25 @@ def save_regulation_group(regulation_group: RegulationGroup, plan_id: str | None
feature = RegulationGroupLayer.feature_from_model(regulation_group, plan_id)
layer = RegulationGroupLayer.get_from_project()

editing = regulation_group.id_ is not None
_save_feature(
feature=feature,
layer=layer,
id_=regulation_group.id_,
edit_text="Kaavamääräysryhmän muokkaus" if editing else "Kaavamääräysryhmän lisäys",
edit_text="Kaavamääräysryhmän muokkaus" if regulation_group.id_ is not None else "Kaavamääräysryhmän lisäys",
)

if editing:
if regulation_group.id_ is not None:
# Check for regulations to be deleted
regulation_layer = PlanRegulationLayer.get_from_project()
for reg_feature in PlanRegulationLayer.get_regulations_to_delete(
regulation_group.regulations, regulation_group
regulation_group.regulations, regulation_group.id_
):
_delete_feature(reg_feature, regulation_layer, "Kaavamääräyksen poisto")

# Check for propositions to be deleted
proposition_layer = PlanPropositionLayer.get_from_project()
for prop_feature in PlanPropositionLayer.get_propositions_to_delete(
regulation_group.propositions, regulation_group
regulation_group.propositions, regulation_group.id_
):
_delete_feature(prop_feature, proposition_layer, "Kaavasuosituksen poisto")

Expand Down
4 changes: 4 additions & 0 deletions arho_feature_template/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,7 @@ def __init__(self):
class FeatureNotFoundError(Exception):
def __init__(self, id_: str, layer_name: str):
super().__init__(f"Feature with ID '{id_}' not found for layer {layer_name}")


class UnexpectedNoneError(Exception):
"""Internal QGIS errors that should not be happened"""
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, cast
from typing import TYPE_CHECKING

from qgis.core import QgsApplication
from qgis.PyQt import uic
Expand All @@ -10,6 +10,7 @@
from qgis.PyQt.QtWidgets import QHBoxLayout, QLabel, QSizePolicy, QWidget

from arho_feature_template.core.models import PlanFeature, Proposition, Regulation, RegulationGroup
from arho_feature_template.exceptions import LayerNameNotFoundError
from arho_feature_template.gui.components.plan_proposition_widget import PropositionWidget
from arho_feature_template.gui.components.plan_regulation_widget import RegulationWidget
from arho_feature_template.project.layers.code_layers import PlanRegulationGroupTypeLayer
Expand Down Expand Up @@ -50,7 +51,11 @@ def __init__(self, regulation_group: RegulationGroup, plan_feature: PlanFeature)
self.link_label_text: QLabel | None = None

self.plan_feature = plan_feature
self.layer_name = cast(str, plan_feature.layer_name)
if not plan_feature.layer_name:
msg = "Layer name not found when creating regulation group widget!"
raise LayerNameNotFoundError(msg)
self.layer_name = plan_feature.layer_name

self.from_model(regulation_group)
self.regulation_group.type_code_id = PlanRegulationGroupTypeLayer.get_id_by_feature_layer_name(self.layer_name)

Expand Down Expand Up @@ -79,11 +84,16 @@ def from_model(self, regulation_group: RegulationGroup):
self.unset_existing_regulation_group_style()

if regulation_group.id_:
other_linked_features_count = len(
RegulationGroupAssociationLayer.get_associations_for_regulation_group_exclude_feature(
cast(str, regulation_group.id_), cast(str, self.plan_feature.id_), self.layer_name
if self.plan_feature.id_ is None:
other_linked_features_count = len(
list(RegulationGroupAssociationLayer.get_associations_for_regulation_group(regulation_group.id_))
)
else:
other_linked_features_count = len(
RegulationGroupAssociationLayer.get_associations_for_regulation_group_exclude_feature(
regulation_group.id_, self.plan_feature.id_, self.layer_name
)
)
)
if other_linked_features_count > 0:
# Set indicators that regulation group exists in the plan already and is assigned for other features
self.set_existing_regulation_group_style(other_linked_features_count)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ def initialize_text_input_widget(
editable: bool, # noqa: FBT001
):
if default_value:
widget.setText(str(default_value))
widget.setText(default_value)

if not editable:
widget.setReadOnly(True)
Expand Down
2 changes: 1 addition & 1 deletion arho_feature_template/gui/dialogs/load_plan_dialog.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
QTableView,
)

from arho_feature_template.core.exceptions import UnexpectedNoneError
from arho_feature_template.exceptions import UnexpectedNoneError
from arho_feature_template.utils.misc_utils import get_active_plan_id

ui_path = resources.files(__package__) / "load_plan_dialog.ui"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,11 +106,7 @@ def __init__(self, regulation_group: RegulationGroup):

if self.regulation_group.id_:
feat_count = len(
list(
RegulationGroupAssociationLayer.get_associations_for_regulation_group(
str(self.regulation_group.id_)
)
)
list(RegulationGroupAssociationLayer.get_associations_for_regulation_group(self.regulation_group.id_))
)
tooltip = (
"Kaavamääräysryhmä on tallennettu kaavaan. Ryhmän tietojen muokkaaminen vaikuttaa "
Expand Down
3 changes: 1 addition & 2 deletions arho_feature_template/gui/docks/validation_dock.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,9 @@

from qgis.gui import QgsDockWidget
from qgis.PyQt import uic
from qgis.utils import iface

from arho_feature_template.core.lambda_service import LambdaService
from arho_feature_template.utils.misc_utils import get_active_plan_id
from arho_feature_template.utils.misc_utils import get_active_plan_id, iface

if TYPE_CHECKING:
from qgis.PyQt.QtWidgets import QProgressBar, QPushButton
Expand Down
Empty file.
31 changes: 0 additions & 31 deletions arho_feature_template/models/plan_model_.py

This file was deleted.

11 changes: 3 additions & 8 deletions arho_feature_template/plugin.py
Original file line number Diff line number Diff line change
@@ -1,24 +1,19 @@
from __future__ import annotations

from typing import TYPE_CHECKING, Callable, cast
from typing import Callable

from qgis.core import QgsApplication
from qgis.PyQt.QtCore import QCoreApplication, Qt, QTranslator
from qgis.PyQt.QtGui import QIcon
from qgis.PyQt.QtWidgets import QAction, QWidget
from qgis.utils import iface

from arho_feature_template.core.plan_manager import PlanManager
from arho_feature_template.gui.dialogs.plugin_settings import PluginSettings
from arho_feature_template.gui.docks.validation_dock import ValidationDock
from arho_feature_template.qgis_plugin_tools.tools.custom_logging import setup_logger, teardown_logger
from arho_feature_template.qgis_plugin_tools.tools.i18n import setup_translation
from arho_feature_template.qgis_plugin_tools.tools.resources import plugin_name, resources_path

if TYPE_CHECKING:
from qgis.gui import QgisInterface

iface: QgisInterface = cast("QgisInterface", iface) # type: ignore[no-redef]
from arho_feature_template.utils.misc_utils import disconnect_signal, iface


class Plugin:
Expand Down Expand Up @@ -262,7 +257,7 @@ def open_settings(self):
def unload(self) -> None:
"""Removes the plugin menu item and icon from QGIS GUI."""
# Handle signals
self.plan_manager.new_feature_dock.visibilityChanged.disconnect()
disconnect_signal(self.plan_manager.new_feature_dock.visibilityChanged)
iface.mapCanvas().mapToolSet.disconnect()
iface.projectRead.disconnect()

Expand Down
27 changes: 9 additions & 18 deletions arho_feature_template/project/layers/plan_layers.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,7 @@
from textwrap import dedent
from typing import Any, ClassVar, Generator

from qgis.core import QgsExpressionContextUtils, QgsFeature, QgsProject, QgsVectorLayerUtils
from qgis.utils import iface
from qgis.core import QgsFeature, QgsVectorLayerUtils

from arho_feature_template.core.models import (
AdditionalInformation,
Expand All @@ -24,7 +23,7 @@
from arho_feature_template.exceptions import FeatureNotFoundError, LayerEditableError, LayerNotFoundError
from arho_feature_template.project.layers import AbstractLayer
from arho_feature_template.project.layers.code_layers import PlanRegulationTypeLayer
from arho_feature_template.utils.misc_utils import LANGUAGE, get_active_plan_id
from arho_feature_template.utils.misc_utils import LANGUAGE, get_active_plan_id, iface

logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -198,11 +197,7 @@ def feature_from_model(cls, model: RegulationGroup, plan_id: str | None = None)
feature["short_name"] = model.short_name if model.short_name else None
feature["name"] = {LANGUAGE: model.name if model.name else None}
feature["type_of_plan_regulation_group_id"] = model.type_code_id
feature["plan_id"] = (
plan_id
if plan_id
else QgsExpressionContextUtils.projectScope(QgsProject.instance()).variable("active_plan_id")
)
feature["plan_id"] = plan_id if plan_id else get_active_plan_id()
feature["id"] = model.id_ if model.id_ else feature["id"]
return feature

Expand Down Expand Up @@ -405,13 +400,11 @@ def regulations_with_group_id(cls, group_id: str) -> Generator[QgsFeature]:
return cls.get_features_by_attribute_value("plan_regulation_group_id", group_id)

@classmethod
def get_regulations_to_delete(
cls, regulations: list[Regulation], regulation_group: RegulationGroup
) -> list[QgsFeature]:
def get_regulations_to_delete(cls, regulations: list[Regulation], group_id: str) -> list[QgsFeature]:
updated_regulation_ids = [regulation.id_ for regulation in regulations]
return [
reg
for reg in cls.get_features_by_attribute_value("plan_regulation_group_id", str(regulation_group.id_))
for reg in cls.get_features_by_attribute_value("plan_regulation_group_id", group_id)
if reg["id"] not in updated_regulation_ids
]

Expand Down Expand Up @@ -458,13 +451,11 @@ def propositions_with_group_id(cls, group_id: str) -> Generator[QgsFeature]:
return cls.get_features_by_attribute_value("plan_regulation_group_id", group_id)

@classmethod
def get_propositions_to_delete(
cls, propositions: list[Proposition], regulation_group: RegulationGroup
) -> list[QgsFeature]:
def get_propositions_to_delete(cls, propositions: list[Proposition], group_id: str) -> list[QgsFeature]:
updated_proposition_ids = [proposition.id_ for proposition in propositions]
return [
prop
for prop in cls.get_features_by_attribute_value("plan_regulation_group_id", str(regulation_group.id_))
for prop in cls.get_features_by_attribute_value("plan_regulation_group_id", group_id)
if prop["id"] not in updated_proposition_ids
]

Expand Down Expand Up @@ -512,11 +503,11 @@ def model_from_feature(cls, feature: QgsFeature) -> Document:
)

@classmethod
def get_documents_to_delete(cls, documents: list[Document], plan: Plan) -> list[QgsFeature]:
def get_documents_to_delete(cls, documents: list[Document], plan_id: str) -> list[QgsFeature]:
updated_document_ids = [doc.id_ for doc in documents]
return [
doc
for doc in cls.get_features_by_attribute_value("plan_id", str(plan.id_))
for doc in cls.get_features_by_attribute_value("plan_id", plan_id)
if doc["id"] not in updated_document_ids
]

Expand Down
2 changes: 1 addition & 1 deletion arho_feature_template/utils/db_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

from qgis.core import QgsProviderRegistry

from arho_feature_template.core.exceptions import UnexpectedNoneError
from arho_feature_template.exceptions import UnexpectedNoneError

LOGGER = logging.getLogger("LandUsePlugin")

Expand Down
5 changes: 5 additions & 0 deletions arho_feature_template/utils/misc_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,11 @@ def handle_unsaved_changes() -> bool:
return True


def set_active_plan_id(plan_id: str | None):
"""Store the given plan ID as the active plan ID as a project variable."""
QgsExpressionContextUtils.setProjectVariable(QgsProject.instance(), "active_plan_id", plan_id)


def get_active_plan_id():
"""Retrieve the active plan ID stored as a project variable."""
return QgsExpressionContextUtils.projectScope(QgsProject.instance()).variable("active_plan_id")
Expand Down
Loading