Skip to content

Commit 54ac1e0

Browse files
Mtk112LKajan
authored andcommitted
Refactored new_plan, and load_existing_land_use_plan
Added handling of unsaved changes to creating new plan.
1 parent 66d4197 commit 54ac1e0

File tree

3 files changed

+113
-101
lines changed

3 files changed

+113
-101
lines changed

arho_feature_template/core/new_plan.py

-63
This file was deleted.
+107
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
from qgis.core import QgsProject, QgsVectorLayer
2+
from qgis.PyQt.QtWidgets import QDialog, QMessageBox
3+
from qgis.utils import iface
4+
5+
from arho_feature_template.core.update_plan import LandUsePlan, update_selected_plan
6+
from arho_feature_template.gui.load_plan_dialog import LoadPlanDialog
7+
from arho_feature_template.utils.db_utils import get_existing_database_connection_names
8+
from arho_feature_template.utils.misc_utils import handle_unsaved_changes
9+
10+
11+
class PlanManager:
12+
def __init__(self):
13+
self.kaava_layer = self.get_layer_by_name("Kaava")
14+
15+
def get_layer_by_name(self, layer_name):
16+
"""Retrieve a layer by name from the project."""
17+
layers = QgsProject.instance().mapLayersByName(layer_name)
18+
if layers:
19+
return layers[0]
20+
iface.messageBar().pushMessage("Error", f"Layer '{layer_name}' not found", level=3)
21+
return None
22+
23+
def add_new_plan(self):
24+
"""Initiate the process to add a new plan to the Kaava layer."""
25+
if not handle_unsaved_changes():
26+
return
27+
28+
self.clear_all_filters()
29+
30+
if not self.kaava_layer:
31+
return
32+
33+
if not self.kaava_layer.isEditable():
34+
self.kaava_layer.startEditing()
35+
36+
iface.setActiveLayer(self.kaava_layer)
37+
iface.actionAddFeature().trigger()
38+
39+
# Connect the featureAdded signal to a callback method
40+
self.kaava_layer.featureAdded.connect(self.feature_added)
41+
42+
def feature_added(self):
43+
"""Callback for when a new feature is added to the Kaava layer."""
44+
if not self.kaava_layer:
45+
return
46+
47+
# Disconnect the signal to avoid repeated triggers
48+
self.kaava_layer.featureAdded.disconnect()
49+
50+
feature_ids_before_commit = self.kaava_layer.allFeatureIds()
51+
52+
if self.kaava_layer.isEditable():
53+
if not self.kaava_layer.commitChanges():
54+
iface.messageBar().pushMessage("Error", "Failed to commit changes to the layer.", level=3)
55+
return
56+
else:
57+
iface.messageBar().pushMessage("Error", "Layer is not editable.", level=3)
58+
return
59+
60+
feature_ids_after_commit = self.kaava_layer.allFeatureIds()
61+
new_feature_id = next((fid for fid in feature_ids_after_commit if fid not in feature_ids_before_commit), None)
62+
63+
if new_feature_id is not None:
64+
new_feature = self.kaava_layer.getFeature(new_feature_id)
65+
if new_feature.isValid():
66+
feature_id_value = new_feature["id"]
67+
update_selected_plan(LandUsePlan(feature_id_value))
68+
else:
69+
iface.messageBar().pushMessage("Error", "Invalid feature retrieved.", level=3)
70+
else:
71+
iface.messageBar().pushMessage("Error", "No new feature was added.", level=3)
72+
73+
def load_land_use_plan(self):
74+
"""Load an existing land use plan using a dialog selection."""
75+
connections = get_existing_database_connection_names()
76+
77+
if not connections:
78+
QMessageBox.critical(None, "Error", "No database connections found.")
79+
return
80+
81+
if not handle_unsaved_changes():
82+
return
83+
84+
dialog = LoadPlanDialog(None, connections)
85+
86+
if dialog.exec_() == QDialog.Accepted:
87+
selected_plan_id = dialog.get_selected_plan_id()
88+
self.commit_all_editable_layers()
89+
90+
if not selected_plan_id:
91+
QMessageBox.critical(None, "Error", "No plan was selected.")
92+
return
93+
94+
plan = LandUsePlan(selected_plan_id)
95+
update_selected_plan(plan)
96+
97+
def clear_all_filters(self):
98+
"""Clear filters for all vector layers in the project."""
99+
for layer in QgsProject.instance().mapLayers().values():
100+
if isinstance(layer, QgsVectorLayer):
101+
layer.setSubsetString("")
102+
103+
def commit_all_editable_layers(self):
104+
"""Commit all changes in any editable layers."""
105+
for layer in QgsProject.instance().mapLayers().values():
106+
if isinstance(layer, QgsVectorLayer) and layer.isEditable():
107+
layer.commitChanges()

arho_feature_template/plugin.py

+6-38
Original file line numberDiff line numberDiff line change
@@ -2,21 +2,16 @@
22

33
from typing import TYPE_CHECKING, Callable, cast
44

5-
from qgis.core import QgsProject, QgsVectorLayer
65
from qgis.PyQt.QtCore import QCoreApplication, Qt, QTranslator
76
from qgis.PyQt.QtGui import QIcon
8-
from qgis.PyQt.QtWidgets import QAction, QDialog, QMessageBox, QWidget
7+
from qgis.PyQt.QtWidgets import QAction, QWidget
98
from qgis.utils import iface
109

1110
from arho_feature_template.core.feature_template_library import FeatureTemplater, TemplateGeometryDigitizeMapTool
12-
from arho_feature_template.core.new_plan import NewPlan
13-
from arho_feature_template.core.update_plan import LandUsePlan, update_selected_plan
14-
from arho_feature_template.gui.load_plan_dialog import LoadPlanDialog
11+
from arho_feature_template.core.plan_manager import PlanManager
1512
from arho_feature_template.qgis_plugin_tools.tools.custom_logging import setup_logger, teardown_logger
1613
from arho_feature_template.qgis_plugin_tools.tools.i18n import setup_translation
1714
from arho_feature_template.qgis_plugin_tools.tools.resources import plugin_name
18-
from arho_feature_template.utils.db_utils import get_existing_database_connection_names
19-
from arho_feature_template.utils.misc_utils import handle_unsaved_changes
2015

2116
if TYPE_CHECKING:
2217
from qgis.gui import QgisInterface, QgsMapTool
@@ -32,6 +27,7 @@ class Plugin:
3227
def __init__(self) -> None:
3328
setup_logger(Plugin.name)
3429
self.digitizing_tool = None
30+
self.plan_manager = PlanManager()
3531

3632
# initialize locale
3733
locale, file_path = setup_translation()
@@ -127,7 +123,6 @@ def add_action(
127123

128124
def initGui(self) -> None: # noqa N802
129125
self.templater = FeatureTemplater()
130-
self.new_plan = NewPlan()
131126

132127
# plan_icon_path = os.path.join(PLUGIN_PATH, "resources/icons/city.png") # A placeholder icon
133128
# load_icon_path = os.path.join(PLUGIN_PATH, "resources/icons/folder.png") # A placeholder icon
@@ -172,37 +167,10 @@ def on_map_tool_changed(self, new_tool: QgsMapTool, old_tool: QgsMapTool) -> Non
172167
self.template_dock_action.setChecked(False)
173168

174169
def add_new_plan(self):
175-
self.new_plan.add_new_plan()
170+
self.plan_manager.add_new_plan()
176171

177-
def load_existing_land_use_plan(self) -> None:
178-
"""Open existing land use plan."""
179-
180-
connections = get_existing_database_connection_names()
181-
182-
if not connections:
183-
QMessageBox.critical(None, "Error", "No database connections found.")
184-
return
185-
186-
if not handle_unsaved_changes():
187-
return
188-
189-
dialog = LoadPlanDialog(None, connections)
190-
191-
if dialog.exec_() == QDialog.Accepted:
192-
selected_plan_id = dialog.get_selected_plan_id()
193-
194-
project = QgsProject.instance()
195-
for layer in project.mapLayers().values():
196-
if isinstance(layer, QgsVectorLayer) and layer.isEditable():
197-
layer.commitChanges()
198-
199-
if not selected_plan_id:
200-
QMessageBox.critical(None, "Error", "No plan was selected.")
201-
return
202-
203-
plan = LandUsePlan(selected_plan_id)
204-
205-
update_selected_plan(plan)
172+
def load_existing_land_use_plan(self):
173+
self.plan_manager.load_land_use_plan()
206174

207175
def unload(self) -> None:
208176
"""Removes the plugin menu item and icon from QGIS GUI."""

0 commit comments

Comments
 (0)