Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit c6b68d5

Browse files
committedNov 27, 2024·
Refactor get_plan_json.
Changed lambda call to use QNetworkRequest and created the required QNetworkProxy. Changed settings to store Proxy host and port. Added lambda url to settings.
1 parent 7c913db commit c6b68d5

File tree

6 files changed

+178
-130
lines changed

6 files changed

+178
-130
lines changed
 

‎arho_feature_template/core/plan_manager.py

+87-44
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,34 @@
11
import json
22

3-
import requests # type: ignore
43
from qgis.core import QgsExpressionContextUtils, QgsProject, QgsVectorLayer
4+
from qgis.PyQt.QtCore import QByteArray, QUrl
5+
from qgis.PyQt.QtNetwork import QNetworkAccessManager, QNetworkProxy, QNetworkReply, QNetworkRequest
56
from qgis.PyQt.QtWidgets import QDialog, QMessageBox
67
from qgis.utils import iface
78

89
from arho_feature_template.core.update_plan import LandUsePlan, update_selected_plan
910
from arho_feature_template.gui.load_plan_dialog import LoadPlanDialog
1011
from arho_feature_template.gui.serialize_plan import SerializePlan
1112
from arho_feature_template.utils.db_utils import get_existing_database_connection_names
12-
from arho_feature_template.utils.misc_utils import get_active_plan_id, get_lambda_settings, handle_unsaved_changes
13+
from arho_feature_template.utils.misc_utils import get_active_plan_id, get_settings, handle_unsaved_changes
1314

1415

1516
class PlanManager:
1617
HTTP_STATUS_OK = 200
1718

1819
def __init__(self):
20+
# Init network manager
21+
self.network_manager = QNetworkAccessManager()
22+
proxy_host, proxy_port, self.lambda_url = get_settings()
23+
24+
# SOCKS5 Proxy
25+
proxy = QNetworkProxy()
26+
proxy.setType(QNetworkProxy.Socks5Proxy)
27+
proxy.setHostName(proxy_host)
28+
proxy.setPort(int(proxy_port))
29+
self.network_manager.setProxy(proxy)
30+
1931
self.kaava_layer = self.get_layer_by_name("Kaava")
20-
lambda_host, lambda_port = get_lambda_settings()
21-
self.lambda_url = f"https://{lambda_host}:{lambda_port}/v0/ryhti"
2232

2333
def get_layer_by_name(self, layer_name):
2434
"""Retrieve a layer by name from the project."""
@@ -119,8 +129,8 @@ def get_plan_json(self):
119129
"""Serializes plan and plan outline to JSON"""
120130
dialog = SerializePlan()
121131
if dialog.exec_() == QDialog.Accepted:
122-
json_plan_path = dialog.plan_widget.filePath()
123-
json_plan_outline_path = dialog.plan_outline_widget.filePath()
132+
json_plan_path = dialog.plan_path_edit.text()
133+
json_plan_outline_path = dialog.plan_outline_path_edit.text()
124134

125135
plan_id = get_active_plan_id()
126136

@@ -129,43 +139,76 @@ def get_plan_json(self):
129139
return
130140

131141
payload = {"action": "get_plans", "plan_uuid": plan_id}
142+
payload_bytes = QByteArray(json.dumps(payload).encode("utf-8"))
143+
144+
request = QNetworkRequest(QUrl(self.lambda_url))
145+
request.setHeader(QNetworkRequest.ContentTypeHeader, "application/json")
146+
147+
reply = self.network_manager.post(request, payload_bytes)
148+
149+
# Connect the finished signal to a lambda to pass extra arguments
150+
reply.finished.connect(lambda: self._handle_response(reply, json_plan_path, json_plan_outline_path))
151+
152+
def _handle_response(self, reply: QNetworkReply, json_plan_path: str, json_plan_outline_path: str):
153+
"""Handle the API response and process the plan and outline data."""
154+
if reply.error() != QNetworkReply.NoError:
155+
error_string = reply.errorString()
156+
QMessageBox.critical(None, "Virhe API kutsussa", f"Virhe: {error_string}")
157+
return
158+
159+
try:
160+
response_data = reply.readAll().data().decode('utf-8')
161+
response_json = json.loads(response_data)
162+
163+
details = response_json.get("details")
164+
if not details:
165+
QMessageBox.warning(None, "Varoitus", "Vastauksesta puuttuu 'details' kenttä.")
166+
return
167+
168+
# Extract plan and write it to file
169+
plan_id = get_active_plan_id()
170+
if not plan_id:
171+
QMessageBox.critical(None, "Virhe", "Ei aktiivista kaavaa.")
172+
return
132173

133-
try:
134-
response = requests.post(
135-
self.lambda_url, json=payload, headers={"Content-Type": "application/json"}, timeout=15
174+
plan_json = details.get(plan_id)
175+
if not plan_json:
176+
QMessageBox.warning(None, "Varoitus", f"Aktiiviselle kaavalle (id: {plan_id}) ei löydy tietoja.")
177+
return
178+
179+
with open(json_plan_path, "w", encoding="utf-8") as full_file:
180+
json.dump(plan_json, full_file, ensure_ascii=False, indent=2)
181+
182+
# Process the geographicalArea for the outline
183+
geographical_area = plan_json.get("geographicalArea")
184+
if geographical_area:
185+
try:
186+
# Build the structured outline JSON and write to file
187+
outline_json = {
188+
"type": "Feature",
189+
"properties": {
190+
"name": "Example Polygon"
191+
},
192+
"srid": geographical_area.get("srid"),
193+
"geometry": geographical_area.get("geometry"),
194+
}
195+
196+
with open(json_plan_outline_path, "w", encoding="utf-8") as outline_file:
197+
json.dump(outline_json, outline_file, ensure_ascii=False, indent=2)
198+
199+
QMessageBox.information(None, "Success", "Kaava ja sen ulkorja tallennettu onnistuneesti.")
200+
except KeyError as e:
201+
QMessageBox.critical(
202+
None,
203+
"Virhe",
204+
f"'geographicalArea' ei sisällä vaadittuja tietoja: {e}",
205+
)
206+
else:
207+
QMessageBox.warning(
208+
None, "Varoitus", "Kenttä 'geographicalArea' puuttuu kaavan tiedoista."
136209
)
137-
if response.status_code == self.HTTP_STATUS_OK:
138-
response_json = response.json()
139-
140-
# Extract the "details" part for the full JSON
141-
details = response_json.get("details")
142-
if details:
143-
# Extract the plan_json
144-
plan_json = details.get(plan_id)
145-
146-
if plan_json:
147-
with open(json_plan_path, "w", encoding="utf-8") as full_file:
148-
json.dump(plan_json, full_file, ensure_ascii=False, indent=2)
149-
150-
# Extract and save the plan outline
151-
geographical_area = plan_json.get("geographicalArea")
152-
if geographical_area:
153-
with open(json_plan_outline_path, "w", encoding="utf-8") as outline_file:
154-
json.dump(
155-
{"geographicalArea": geographical_area},
156-
outline_file,
157-
ensure_ascii=False,
158-
indent=2,
159-
)
160-
161-
else:
162-
QMessageBox.warning(
163-
None, "Warning", "The geographicalArea field is missing in the plan details."
164-
)
165-
else:
166-
QMessageBox.warning(None, "Warning", "No plan data found for the specified plan ID.")
167-
else:
168-
QMessageBox.warning(None, "Warning", "No details found in the response JSON.")
169-
170-
except requests.RequestException as e:
171-
QMessageBox.critical(None, "Request Error", f"An error occurred: {e!s}")
210+
except json.JSONDecodeError as e:
211+
QMessageBox.critical(None, "Virhe", f"Vastaus JSON:in purkaminen epäonnistui: {e}")
212+
213+
# Clean up the reply
214+
reply.deleteLater()

‎arho_feature_template/gui/plugin_settings.py

+9-6
Original file line numberDiff line numberDiff line change
@@ -22,16 +22,19 @@ def load_settings(self):
2222
"""Load settings from QSettings with default values."""
2323
settings = QSettings("ArhoFeatureTemplate")
2424

25-
lambda_host = settings.value("lambda_host", "localhost")
26-
lambda_port = settings.value("lambda_port", "5435")
25+
proxy_host = settings.value("proxy_host", "localhost")
26+
proxy_port = settings.value("proxy_port", "5443")
27+
lambda_url = settings.value("lambda_url", "https://t5w26iqnsf.execute-api.eu-central-1.amazonaws.com/v0/ryhti")
2728

28-
self.hostInput.setText(lambda_host)
29-
self.portInput.setText(lambda_port)
29+
self.hostInput.setText(proxy_host)
30+
self.portInput.setText(proxy_port)
31+
self.lambdaInput.setText(lambda_url)
3032

3133
def save_settings(self):
3234
"""Save settings to QSettings."""
3335
settings = QSettings("ArhoFeatureTemplate")
34-
settings.setValue("lambda_host", self.hostInput.text())
35-
settings.setValue("lambda_port", self.portInput.text())
36+
settings.setValue("proxy_host", self.hostInput.text())
37+
settings.setValue("proxy_port", self.portInput.text())
38+
settings.setValue("lambda_url", self.lambdaInput.text())
3639

3740
self.accept()

‎arho_feature_template/gui/plugin_settings.ui

+12-2
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
<item>
1818
<widget class="QLabel" name="labelHost">
1919
<property name="text">
20-
<string>Lambdan isäntä:</string>
20+
<string>Proxy isäntä:</string>
2121
</property>
2222
</widget>
2323
</item>
@@ -27,13 +27,23 @@
2727
<item>
2828
<widget class="QLabel" name="labelPort">
2929
<property name="text">
30-
<string>Lambdan portti:</string>
30+
<string>Proxy portti:</string>
3131
</property>
3232
</widget>
3333
</item>
3434
<item>
3535
<widget class="QLineEdit" name="portInput"/>
3636
</item>
37+
<item>
38+
<widget class="QLabel" name="labelLambda">
39+
<property name="text">
40+
<string>Lambdan osoite:</string>
41+
</property>
42+
</widget>
43+
</item>
44+
<item>
45+
<widget class="QLineEdit" name="lambdaInput"/>
46+
</item>
3747
<item>
3848
<widget class="QPushButton" name="saveButton">
3949
<property name="text">
+24-9
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
from importlib import resources
22

33
from qgis.PyQt import uic
4-
from qgis.PyQt.QtWidgets import QDialog, QDialogButtonBox
4+
from qgis.PyQt.QtWidgets import QDialog, QDialogButtonBox, QFileDialog, QLineEdit, QPushButton
55

66
ui_path = resources.files(__package__) / "serialize_plan.ui"
77
FormClass, _ = uic.loadUiType(ui_path)
@@ -12,22 +12,37 @@ def __init__(self):
1212
super().__init__()
1313
self.setupUi(self)
1414

15-
# Connect the buttons and initialize
15+
self.plan_outline_path_edit = self.findChild(QLineEdit, "plan_outline_path_edit")
16+
self.plan_path_edit = self.findChild(QLineEdit, "plan_path_edit")
17+
self.plan_outline_select_button = self.findChild(QPushButton, "plan_outline_select_button")
18+
self.plan_select_button = self.findChild(QPushButton, "plan_select_button")
19+
20+
self.plan_outline_select_button.clicked.connect(self.select_plan_outline_file)
21+
self.plan_select_button.clicked.connect(self.select_plan_file)
22+
23+
# Disable Save button initially
1624
self.buttonBox.button(QDialogButtonBox.Save).setEnabled(False)
1725
self.buttonBox.accepted.connect(self.accept)
1826
self.buttonBox.rejected.connect(self.reject)
1927

20-
# Connect to file widgets' signal to check inputs
21-
self.plan_widget.fileChanged.connect(self.check_inputs)
22-
self.plan_outline_widget.fileChanged.connect(self.check_inputs)
28+
def select_plan_outline_file(self):
29+
file_path, _ = QFileDialog.getSaveFileName(self, "Valitse kaavan ulkorajan tallennuspolku", "", "JSON Files (*.json)")
30+
if file_path:
31+
self.plan_outline_path_edit.setText(file_path)
32+
self.check_inputs()
33+
34+
def select_plan_file(self):
35+
file_path, _ = QFileDialog.getSaveFileName(self, "Valitse kaavan tallennuspolku", "", "JSON Files (*.json)")
36+
if file_path:
37+
self.plan_path_edit.setText(file_path)
38+
self.check_inputs()
2339

2440
def check_inputs(self):
25-
# Enable save button if both file paths are set
26-
if self.plan_widget.filePath() and self.plan_outline_widget.filePath():
41+
# Enable Save button if both text fields have paths
42+
if self.plan_outline_path_edit.text() and self.plan_path_edit.text():
2743
self.buttonBox.button(QDialogButtonBox.Save).setEnabled(True)
2844
else:
2945
self.buttonBox.button(QDialogButtonBox.Save).setEnabled(False)
3046

3147
def get_paths(self):
32-
# Retrieve the paths from the QgsFileWidgets
33-
return self.plan_widget.filePath(), self.plan_outline_widget.filePath()
48+
return self.plan_outline_path_edit.text(), self.plan_path_edit.text()
+40-64
Original file line numberDiff line numberDiff line change
@@ -1,113 +1,89 @@
11
<?xml version="1.0" encoding="UTF-8"?>
22
<ui version="4.0">
3-
<class>SerializePlan</class>
3+
<class>Dialog</class>
44
<widget class="QDialog" name="Dialog">
55
<property name="geometry">
66
<rect>
77
<x>0</x>
88
<y>0</y>
9-
<width>395</width>
10-
<height>204</height>
9+
<width>558</width>
10+
<height>193</height>
1111
</rect>
1212
</property>
1313
<property name="windowTitle">
1414
<string>Tallenna kaava JSON</string>
1515
</property>
1616
<widget class="QDialogButtonBox" name="buttonBox">
17-
<property name="enabled">
18-
<bool>true</bool>
19-
</property>
2017
<property name="geometry">
2118
<rect>
2219
<x>20</x>
23-
<y>160</y>
24-
<width>341</width>
20+
<y>150</y>
21+
<width>521</width>
2522
<height>32</height>
2623
</rect>
2724
</property>
28-
<property name="orientation">
29-
<enum>Qt::Horizontal</enum>
30-
</property>
3125
<property name="standardButtons">
3226
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Save</set>
3327
</property>
3428
<property name="centerButtons">
3529
<bool>true</bool>
3630
</property>
3731
</widget>
38-
<widget class="QWidget" name="verticalLayoutWidget">
32+
<widget class="QWidget" name="layoutWidget">
3933
<property name="geometry">
4034
<rect>
41-
<x>30</x>
42-
<y>30</y>
43-
<width>341</width>
44-
<height>111</height>
35+
<x>20</x>
36+
<y>20</y>
37+
<width>521</width>
38+
<height>120</height>
4539
</rect>
4640
</property>
47-
<layout class="QVBoxLayout" name="verticalLayout">
48-
<item>
41+
<layout class="QGridLayout" name="gridLayout">
42+
<item row="0" column="0">
4943
<widget class="QLabel" name="plan_outline_label">
5044
<property name="text">
5145
<string>Kaavan ulkorajan tallennuspolku:</string>
5246
</property>
5347
</widget>
5448
</item>
55-
<item>
56-
<widget class="QgsFileWidget" name="plan_widget"/>
49+
<item row="0" column="1">
50+
<widget class="QLineEdit" name="plan_outline_path_edit">
51+
<property name="readOnly">
52+
<bool>true</bool>
53+
</property>
54+
</widget>
55+
</item>
56+
<item row="0" column="2">
57+
<widget class="QPushButton" name="plan_outline_select_button">
58+
<property name="text">
59+
<string>Valitse...</string>
60+
</property>
61+
</widget>
5762
</item>
58-
<item>
63+
<item row="1" column="0">
5964
<widget class="QLabel" name="plan_label">
6065
<property name="text">
6166
<string>Kaavan tallennuspolku:</string>
6267
</property>
6368
</widget>
6469
</item>
65-
<item>
66-
<widget class="QgsFileWidget" name="plan_outline_widget"/>
70+
<item row="1" column="1">
71+
<widget class="QLineEdit" name="plan_path_edit">
72+
<property name="readOnly">
73+
<bool>true</bool>
74+
</property>
75+
</widget>
76+
</item>
77+
<item row="1" column="2">
78+
<widget class="QPushButton" name="plan_select_button">
79+
<property name="text">
80+
<string>Valitse...</string>
81+
</property>
82+
</widget>
6783
</item>
6884
</layout>
6985
</widget>
7086
</widget>
71-
<customwidgets>
72-
<customwidget>
73-
<class>QgsFileWidget</class>
74-
<extends>QWidget</extends>
75-
<header>qgsfilewidget.h</header>
76-
</customwidget>
77-
</customwidgets>
7887
<resources/>
79-
<connections>
80-
<connection>
81-
<sender>buttonBox</sender>
82-
<signal>accepted()</signal>
83-
<receiver>SerializePlan</receiver>
84-
<slot>accept()</slot>
85-
<hints>
86-
<hint type="sourcelabel">
87-
<x>248</x>
88-
<y>254</y>
89-
</hint>
90-
<hint type="destinationlabel">
91-
<x>157</x>
92-
<y>274</y>
93-
</hint>
94-
</hints>
95-
</connection>
96-
<connection>
97-
<sender>buttonBox</sender>
98-
<signal>rejected()</signal>
99-
<receiver>SerializePlan</receiver>
100-
<slot>reject()</slot>
101-
<hints>
102-
<hint type="sourcelabel">
103-
<x>316</x>
104-
<y>260</y>
105-
</hint>
106-
<hint type="destinationlabel">
107-
<x>286</x>
108-
<y>274</y>
109-
</hint>
110-
</hints>
111-
</connection>
112-
</connections>
88+
<connections/>
11389
</ui>

‎arho_feature_template/utils/misc_utils.py

+6-5
Original file line numberDiff line numberDiff line change
@@ -64,9 +64,10 @@ def get_active_plan_id():
6464
return QgsExpressionContextUtils.projectScope(QgsProject.instance()).variable("active_plan_id")
6565

6666

67-
def get_lambda_settings():
68-
"""Retrieve Lambda settings, using defaults if not set."""
67+
def get_settings():
68+
"""Retrieve stored settings, using defaults if not set."""
6969
settings = QSettings("ArhoFeatureTemplate")
70-
lambda_host = settings.value("lambda_host", "localhost")
71-
lambda_port = settings.value("lambda_port", "5443")
72-
return lambda_host, lambda_port
70+
proxy_host = settings.value("proxy_host", "localhost")
71+
proxy_port = settings.value("proxy_port", "5443")
72+
lambda_url = settings.value("lambda_url", "https://t5w26iqnsf.execute-api.eu-central-1.amazonaws.com/v0/ryhti")
73+
return proxy_host, proxy_port, lambda_url

0 commit comments

Comments
 (0)
Please sign in to comment.