diff --git a/ORStools/ORStoolsPlugin.py b/ORStools/ORStoolsPlugin.py
index 33fa4b5c..2156bf8a 100644
--- a/ORStools/ORStoolsPlugin.py
+++ b/ORStools/ORStoolsPlugin.py
@@ -33,7 +33,7 @@
import os.path
from .gui import ORStoolsDialog
-from .proc import provider
+from .proc import provider, ENDPOINTS, DEFAULT_SETTINGS
class ORStools:
@@ -89,19 +89,19 @@ def unload(self) -> None:
def add_default_provider_to_settings(self):
s = QgsSettings()
settings = s.value("ORStools/config")
- if not settings:
- def_settings = {
- "providers": [
- {
- "ENV_VARS": {
- "ORS_QUOTA": "X-Ratelimit-Limit",
- "ORS_REMAINING": "X-Ratelimit-Remaining",
- },
- "base_url": "https://api.openrouteservice.org",
- "key": "",
- "name": "openrouteservice",
- "timeout": 60,
- }
- ]
- }
- s.setValue("ORStools/config", def_settings)
+
+ settings_keys = ["ENV_VARS", "base_url", "key", "name", "endpoints"]
+
+ # Add any new settings here for backwards compatibility
+ if settings:
+ changed = False
+ for i, prov in enumerate(settings["providers"]):
+ if any([i not in prov for i in settings_keys]):
+ changed = True
+ # Add here, like the endpoints
+ prov["endpoints"] = ENDPOINTS
+ settings["providers"][i] = prov
+ if changed:
+ s.setValue("ORStools/config", settings)
+ else:
+ s.setValue("ORStools/config", DEFAULT_SETTINGS)
diff --git a/ORStools/gui/ORStoolsDialogConfig.py b/ORStools/gui/ORStoolsDialogConfig.py
index edffcd50..9e5e724c 100644
--- a/ORStools/gui/ORStoolsDialogConfig.py
+++ b/ORStools/gui/ORStoolsDialogConfig.py
@@ -29,13 +29,19 @@
from qgis.gui import QgsCollapsibleGroupBox
-from PyQt5 import QtWidgets
+from qgis.PyQt import QtWidgets
from qgis.PyQt.QtCore import QMetaObject
-from qgis.PyQt.QtWidgets import QDialog, QInputDialog, QLineEdit, QDialogButtonBox
+from qgis.PyQt.QtWidgets import (
+ QDialog,
+ QInputDialog,
+ QLineEdit,
+ QDialogButtonBox,
+)
from qgis.PyQt.QtGui import QIntValidator
from ORStools.utils import configmanager
from .ORStoolsDialogConfigUI import Ui_ORStoolsDialogConfigBase
+from ..proc import ENDPOINTS, DEFAULT_SETTINGS
class ORStoolsDialogConfigMain(QDialog, Ui_ORStoolsDialogConfigBase):
@@ -63,23 +69,55 @@ def __init__(self, parent=None) -> None:
self.buttonBox.button(QDialogButtonBox.Ok).setText(self.tr("Save"))
def accept(self) -> None:
- """When the OK Button is clicked, in-memory temp_config is updated and written to config.yml"""
+ """When the OK Button is clicked, in-memory temp_config is updated and written to settings"""
collapsible_boxes = self.providers.findChildren(QgsCollapsibleGroupBox)
+ collapsible_boxes = [
+ i for i in collapsible_boxes if "_provider_endpoints" not in i.objectName()
+ ]
for idx, box in enumerate(collapsible_boxes):
current_provider = self.temp_config["providers"][idx]
+
current_provider["key"] = box.findChild(
QtWidgets.QLineEdit, box.title() + "_key_text"
).text()
+
current_provider["base_url"] = box.findChild(
QtWidgets.QLineEdit, box.title() + "_base_url_text"
).text()
+
timeout_input = box.findChild(QtWidgets.QLineEdit, box.title() + "_timeout_text")
# https://doc.qt.io/qt-5/qvalidator.html#State-enum
+
if timeout_input.validator().State() != 2:
self._adjust_timeout_input(timeout_input)
+
current_provider["timeout"] = int(timeout_input.text())
+ endpoint_box = box.findChild(
+ QgsCollapsibleGroupBox, f"{box.title()}_provider_endpoints"
+ )
+ current_provider["endpoints"] = {
+ "directions": endpoint_box.findChild(
+ QtWidgets.QLineEdit, box.title() + "_directions_endpoint"
+ ).text(),
+ "isochrones": endpoint_box.findChild(
+ QtWidgets.QLineEdit, box.title() + "_isochrones_endpoint"
+ ).text(),
+ "matrix": endpoint_box.findChild(
+ QtWidgets.QLineEdit, box.title() + "_matrix_endpoint"
+ ).text(),
+ "optimization": endpoint_box.findChild(
+ QtWidgets.QLineEdit, box.title() + "_optimization_endpoint"
+ ).text(),
+ "export": endpoint_box.findChild(
+ QtWidgets.QLineEdit, box.title() + "_export_endpoint"
+ ).text(),
+ "snapping": endpoint_box.findChild(
+ QtWidgets.QLineEdit, box.title() + "_snapping_endpoint"
+ ).text(),
+ }
+
configmanager.write_config(self.temp_config)
self.close()
@@ -109,6 +147,7 @@ def _build_ui(self) -> None:
provider_entry["base_url"],
provider_entry["key"],
provider_entry["timeout"],
+ provider_entry["endpoints"],
new=False,
)
@@ -128,7 +167,7 @@ def _add_provider(self) -> None:
self, self.tr("New ORS provider"), self.tr("Enter a name for the provider")
)
if ok:
- self._add_box(provider_name, "http://localhost:8082/ors", "", 60, new=True)
+ self._add_box(provider_name, "http://localhost:8082/ors", "", 60, ENDPOINTS, new=True)
def _remove_provider(self) -> None:
"""Remove list of providers from list."""
@@ -158,25 +197,15 @@ def _collapse_boxes(self) -> None:
for box in collapsible_boxes:
box.setCollapsed(True)
- def _add_box(self, name: str, url: str, key: str, timeout: int, new: bool = False) -> None:
+ def _add_box(
+ self, name: str, url: str, key: str, timeout: int, endpoints: dict, new: bool = False
+ ) -> None:
"""
Adds a provider box to the QWidget layout and self.temp_config.
-
- :param name: provider name
- :type name: str
-
- :param url: provider's base url
- :type url: str
-
- :param key: user's API key
- :type key: str
-
- :param new: Specifies whether user wants to insert provider or the GUI is being built.
- :type new: boolean
"""
if new:
self.temp_config["providers"].append(
- dict(name=name, base_url=url, key=key, timeout=timeout)
+ dict(name=name, base_url=url, key=key, timeout=timeout, endpoints=endpoints)
)
provider = QgsCollapsibleGroupBox(self.providers)
@@ -184,32 +213,87 @@ def _add_box(self, name: str, url: str, key: str, timeout: int, new: bool = Fals
provider.setTitle(name)
gridLayout_3 = QtWidgets.QGridLayout(provider)
gridLayout_3.setObjectName(name + "_grid")
+
+ # API Key section
key_label = QtWidgets.QLabel(provider)
key_label.setObjectName(name + "_key_label")
key_label.setText(self.tr("API Key"))
gridLayout_3.addWidget(key_label, 0, 0, 1, 1)
+
key_text = QtWidgets.QLineEdit(provider)
key_text.setObjectName(name + "_key_text")
key_text.setText(key)
gridLayout_3.addWidget(key_text, 1, 0, 1, 4)
+
+ # Base URL section
base_url_label = QtWidgets.QLabel(provider)
base_url_label.setObjectName("base_url_label")
base_url_label.setText(self.tr("Base URL"))
gridLayout_3.addWidget(base_url_label, 2, 0, 1, 1)
+
base_url_text = QtWidgets.QLineEdit(provider)
base_url_text.setObjectName(name + "_base_url_text")
base_url_text.setText(url)
gridLayout_3.addWidget(base_url_text, 3, 0, 1, 4)
+ # Timeout section
timeout_label = QtWidgets.QLabel(provider)
timeout_label.setObjectName("timeout_label")
timeout_label.setText(self.tr("Request timeout in seconds (1 - 3600)"))
gridLayout_3.addWidget(timeout_label, 4, 0, 1, 1)
+
timeout_text = QtWidgets.QLineEdit(provider)
timeout_text.setObjectName(name + "_timeout_text")
timeout_text.setText(str(timeout))
timeout_text.setValidator(QIntValidator(1, 3600, timeout_text))
gridLayout_3.addWidget(timeout_text, 5, 0, 1, 4)
+ # Service Endpoints section
+ endpoint_box = QgsCollapsibleGroupBox(provider)
+ endpoint_box.setObjectName(name + "_provider_endpoints")
+ endpoint_box.setTitle(self.tr("Service Endpoints"))
+ endpoint_layout = QtWidgets.QGridLayout(endpoint_box)
+ gridLayout_3.addWidget(endpoint_box, 6, 0, 1, 4)
+
+ row = 0
+ for endpoint_name, endpoint_value in endpoints.items():
+ endpoint_label = QtWidgets.QLabel(endpoint_box)
+ endpoint_label.setText(self.tr(endpoint_name.capitalize()))
+ endpoint_layout.addWidget(endpoint_label, row, 0, 1, 1)
+
+ endpoint_lineedit = QtWidgets.QLineEdit(endpoint_box)
+ endpoint_lineedit.setText(endpoint_value)
+ endpoint_lineedit.setObjectName(f"{name}_{endpoint_name}_endpoint")
+
+ endpoint_layout.addWidget(endpoint_lineedit, row, 1, 1, 3)
+
+ row += 1
+
+ # Add reset buttons at the bottom
+ button_layout = QtWidgets.QHBoxLayout()
+
+ reset_url_button = QtWidgets.QPushButton(self.tr("Reset URL"), provider)
+ reset_url_button.setObjectName(name + "_reset_url_button")
+ reset_url_button.clicked.connect(
+ lambda _, t=base_url_text: t.setText(DEFAULT_SETTINGS["providers"][0]["base_url"])
+ )
+ button_layout.addWidget(reset_url_button)
+
+ reset_endpoints_button = QtWidgets.QPushButton(self.tr("Reset Endpoints"), provider)
+ reset_endpoints_button.setObjectName(name + "_reset_endpoints_button")
+ reset_endpoints_button.clicked.connect(self._reset_endpoints)
+ button_layout.addWidget(reset_endpoints_button)
+
+ gridLayout_3.addLayout(button_layout, 7, 0, 1, 4)
+
self.verticalLayout.addWidget(provider)
provider.setSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
+
+ def _reset_endpoints(self) -> None:
+ """Resets the endpoints to their original values."""
+ for line_edit_remove in self.providers.findChildren(QLineEdit):
+ name = line_edit_remove.objectName()
+ if name.endswith("endpoint"):
+ endpoint_name = name.split("_")[1]
+ endpoint_value = ENDPOINTS[endpoint_name]
+ line_edit_remove.setText(endpoint_value)
diff --git a/ORStools/gui/ORStoolsDialogConfigUI.py b/ORStools/gui/ORStoolsDialogConfigUI.py
index e6975c98..f42a9bde 100644
--- a/ORStools/gui/ORStoolsDialogConfigUI.py
+++ b/ORStools/gui/ORStoolsDialogConfigUI.py
@@ -2,16 +2,19 @@
# Form implementation generated from reading ui file 'ORStools/gui/ORStoolsDialogConfigUI.ui'
#
-# Created by: PyQt5 UI code generator 5.9.2
+# Created by: PyQt5 UI code generator 5.15.10
#
-# WARNING! All changes made in this file will be lost!
+# WARNING: Any manual changes made to this file will be lost when pyuic5 is
+# run again. Do not edit this file unless you know what you are doing.
+
from PyQt5 import QtCore, QtGui, QtWidgets
+
class Ui_ORStoolsDialogConfigBase(object):
def setupUi(self, ORStoolsDialogConfigBase):
ORStoolsDialogConfigBase.setObjectName("ORStoolsDialogConfigBase")
- ORStoolsDialogConfigBase.resize(414, 67)
+ ORStoolsDialogConfigBase.resize(414, 100)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Expanding)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
@@ -20,6 +23,16 @@ def setupUi(self, ORStoolsDialogConfigBase):
self.gridLayout = QtWidgets.QGridLayout(ORStoolsDialogConfigBase)
self.gridLayout.setSizeConstraint(QtWidgets.QLayout.SetMinAndMaxSize)
self.gridLayout.setObjectName("gridLayout")
+ self.buttonBox = QtWidgets.QDialogButtonBox(ORStoolsDialogConfigBase)
+ self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Ok)
+ self.buttonBox.setObjectName("buttonBox")
+ self.gridLayout.addWidget(self.buttonBox, 1, 2, 1, 1)
+ self.provider_add = QtWidgets.QPushButton(ORStoolsDialogConfigBase)
+ self.provider_add.setObjectName("provider_add")
+ self.gridLayout.addWidget(self.provider_add, 1, 0, 1, 1)
+ self.provider_remove = QtWidgets.QPushButton(ORStoolsDialogConfigBase)
+ self.provider_remove.setObjectName("provider_remove")
+ self.gridLayout.addWidget(self.provider_remove, 1, 1, 1, 1)
self.providers = QtWidgets.QWidget(ORStoolsDialogConfigBase)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
@@ -31,16 +44,6 @@ def setupUi(self, ORStoolsDialogConfigBase):
self.verticalLayout.setSizeConstraint(QtWidgets.QLayout.SetDefaultConstraint)
self.verticalLayout.setObjectName("verticalLayout")
self.gridLayout.addWidget(self.providers, 0, 0, 1, 3)
- self.buttonBox = QtWidgets.QDialogButtonBox(ORStoolsDialogConfigBase)
- self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Cancel|QtWidgets.QDialogButtonBox.Ok)
- self.buttonBox.setObjectName("buttonBox")
- self.gridLayout.addWidget(self.buttonBox, 1, 2, 1, 1)
- self.provider_add = QtWidgets.QPushButton(ORStoolsDialogConfigBase)
- self.provider_add.setObjectName("provider_add")
- self.gridLayout.addWidget(self.provider_add, 1, 0, 1, 1)
- self.provider_remove = QtWidgets.QPushButton(ORStoolsDialogConfigBase)
- self.provider_remove.setObjectName("provider_remove")
- self.gridLayout.addWidget(self.provider_remove, 1, 1, 1, 1)
self.retranslateUi(ORStoolsDialogConfigBase)
QtCore.QMetaObject.connectSlotsByName(ORStoolsDialogConfigBase)
@@ -50,4 +53,3 @@ def retranslateUi(self, ORStoolsDialogConfigBase):
ORStoolsDialogConfigBase.setWindowTitle(_translate("ORStoolsDialogConfigBase", "Provider Settings"))
self.provider_add.setText(_translate("ORStoolsDialogConfigBase", "Add"))
self.provider_remove.setText(_translate("ORStoolsDialogConfigBase", "Remove"))
-
diff --git a/ORStools/gui/ORStoolsDialogConfigUI.ui b/ORStools/gui/ORStoolsDialogConfigUI.ui
index 4850b501..f3efa28f 100644
--- a/ORStools/gui/ORStoolsDialogConfigUI.ui
+++ b/ORStools/gui/ORStoolsDialogConfigUI.ui
@@ -7,7 +7,7 @@
0
0
414
- 67
+ 100
@@ -23,25 +23,10 @@
QLayout::SetMinAndMaxSize
- -
-
-
-
- 0
- 0
-
-
-
-
- QLayout::SetDefaultConstraint
-
-
-
-
-
- QDialogButtonBox::Cancel|QDialogButtonBox::Ok
+ QDialogButtonBox::Ok
@@ -59,6 +44,21 @@
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ QLayout::SetDefaultConstraint
+
+
+
+
diff --git a/ORStools/proc/__init__.py b/ORStools/proc/__init__.py
index 1edf9987..87e79c3f 100644
--- a/ORStools/proc/__init__.py
+++ b/ORStools/proc/__init__.py
@@ -26,3 +26,28 @@
* *
***************************************************************************/
"""
+
+ENDPOINTS = {
+ "directions": "directions",
+ "isochrones": "isochrones",
+ "matrix": "matrix",
+ "optimization": "optimization",
+ "snapping": "snapping",
+ "export": "export",
+}
+
+DEFAULT_SETTINGS = {
+ "providers": [
+ {
+ "ENV_VARS": {
+ "ORS_QUOTA": "X-Ratelimit-Limit",
+ "ORS_REMAINING": "X-Ratelimit-Remaining",
+ },
+ "base_url": "https://api.openrouteservice.org",
+ "key": "",
+ "name": "openrouteservice",
+ "timeout": 60,
+ "endpoints": ENDPOINTS,
+ }
+ ]
+}
diff --git a/ORStools/proc/base_processing_algorithm.py b/ORStools/proc/base_processing_algorithm.py
index 0cdbb106..f9274f4c 100644
--- a/ORStools/proc/base_processing_algorithm.py
+++ b/ORStools/proc/base_processing_algorithm.py
@@ -179,6 +179,11 @@ def option_parameters(self) -> [QgsProcessingParameterDefinition]:
),
]
+ def get_endpoint_names_from_provider(self, provider: str) -> dict:
+ providers = configmanager.read_config()["providers"]
+ ors_provider = providers[provider]
+ return ors_provider["endpoints"]
+
@classmethod
def _get_ors_client_from_provider(
cls, provider: str, feedback: QgsProcessingFeedback
diff --git a/ORStools/proc/directions_lines_proc.py b/ORStools/proc/directions_lines_proc.py
index b0e52e6b..392134bf 100644
--- a/ORStools/proc/directions_lines_proc.py
+++ b/ORStools/proc/directions_lines_proc.py
@@ -186,7 +186,10 @@ def processAlgorithm(
try:
if optimization_mode is not None:
params = get_params_optimize(line, profile, optimization_mode)
- response = ors_client.request("/optimization", {}, post_json=params)
+ endpoint = self.get_endpoint_names_from_provider(parameters[self.IN_PROVIDER])[
+ "optimization"
+ ]
+ response = ors_client.request(f"{endpoint}/", {}, post_json=params)
sink.addFeature(
directions_core.get_output_features_optimization(
@@ -221,8 +224,11 @@ def processAlgorithm(
params = directions_core.build_default_parameters(
preference, point_list=line, options=options, extra_info=extra_info
)
+ endpoint = self.get_endpoint_names_from_provider(parameters[self.IN_PROVIDER])[
+ "directions"
+ ]
response = ors_client.request(
- "/v2/directions/" + profile + "/geojson", {}, post_json=params
+ f"/v2/{endpoint}/{profile}/geojson", {}, post_json=params
)
if extra_info:
diff --git a/ORStools/proc/directions_points_layer_proc.py b/ORStools/proc/directions_points_layer_proc.py
index f3544b08..e17fa1e6 100644
--- a/ORStools/proc/directions_points_layer_proc.py
+++ b/ORStools/proc/directions_points_layer_proc.py
@@ -228,7 +228,10 @@ def sort(f):
)
params = get_params_optimize(points, profile, optimization_mode)
- response = ors_client.request("/optimization", {}, post_json=params)
+ endpoint = self.get_endpoint_names_from_provider(parameters[self.IN_PROVIDER])[
+ "optimization"
+ ]
+ response = ors_client.request(f"{endpoint}/", {}, post_json=params)
sink.addFeature(
directions_core.get_output_features_optimization(
@@ -263,8 +266,11 @@ def sort(f):
params = directions_core.build_default_parameters(
preference, point_list=points, options=options, extra_info=extra_info
)
+ endpoint = self.get_endpoint_names_from_provider(parameters[self.IN_PROVIDER])[
+ "directions"
+ ]
response = ors_client.request(
- "/v2/directions/" + profile + "/geojson", {}, post_json=params
+ f"/v2/{endpoint}/{profile}/geojson", {}, post_json=params
)
if extra_info:
diff --git a/ORStools/proc/directions_points_layers_proc.py b/ORStools/proc/directions_points_layers_proc.py
index 8b09e755..b97d323c 100644
--- a/ORStools/proc/directions_points_layers_proc.py
+++ b/ORStools/proc/directions_points_layers_proc.py
@@ -236,8 +236,11 @@ def sort_end(f):
)
try:
+ endpoint = self.get_endpoint_names_from_provider(parameters[self.IN_PROVIDER])[
+ "directions"
+ ]
response = ors_client.request(
- "/v2/directions/" + profile + "/geojson", {}, post_json=params
+ f"/v2/{endpoint}/{profile}/geojson", {}, post_json=params
)
except (exceptions.ApiError, exceptions.InvalidKey, exceptions.GenericServerError) as e:
msg = f"Route from {values[0]} to {values[1]} caused a {e.__class__.__name__}:\n{str(e)}"
diff --git a/ORStools/proc/export_proc.py b/ORStools/proc/export_proc.py
index 9d190800..14d6a017 100644
--- a/ORStools/proc/export_proc.py
+++ b/ORStools/proc/export_proc.py
@@ -108,7 +108,8 @@ def processAlgorithm(
# Make request and catch ApiError
try:
- response = ors_client.request("/v2/export/" + profile, {}, post_json=params)
+ endpoint = self.get_endpoint_names_from_provider(parameters[self.IN_PROVIDER])["export"]
+ response = ors_client.request(f"/v2/{endpoint}/{profile}", {}, post_json=params)
nodes_dict = {item["nodeId"]: item["location"] for item in response["nodes"]}
edges = response["edges"]
for edge in edges:
diff --git a/ORStools/proc/isochrones_layer_proc.py b/ORStools/proc/isochrones_layer_proc.py
index 1284dc20..6db28764 100644
--- a/ORStools/proc/isochrones_layer_proc.py
+++ b/ORStools/proc/isochrones_layer_proc.py
@@ -194,7 +194,10 @@ def processAlgorithm(
# If feature causes error, report and continue with next
try:
# Populate features from response
- response = ors_client.request("/v2/isochrones/" + profile, {}, post_json=params)
+ endpoint = self.get_endpoint_names_from_provider(parameters[self.IN_PROVIDER])[
+ "isochrones"
+ ]
+ response = ors_client.request(f"/v2/{endpoint}/{profile}", {}, post_json=params)
for isochrone in self.isochrones.get_features(response, params["id"]):
sink.addFeature(isochrone)
diff --git a/ORStools/proc/isochrones_point_proc.py b/ORStools/proc/isochrones_point_proc.py
index 380726a3..331f00b1 100644
--- a/ORStools/proc/isochrones_point_proc.py
+++ b/ORStools/proc/isochrones_point_proc.py
@@ -151,7 +151,10 @@ def processAlgorithm(
)
try:
- response = ors_client.request("/v2/isochrones/" + profile, {}, post_json=params)
+ endpoint = self.get_endpoint_names_from_provider(parameters[self.IN_PROVIDER])[
+ "isochrones"
+ ]
+ response = ors_client.request(f"/v2/{endpoint}/{profile}", {}, post_json=params)
# Populate features from response
for isochrone in self.isochrones.get_features(response, params["id"]):
diff --git a/ORStools/proc/matrix_proc.py b/ORStools/proc/matrix_proc.py
index fdc52e61..b3fbff78 100644
--- a/ORStools/proc/matrix_proc.py
+++ b/ORStools/proc/matrix_proc.py
@@ -175,7 +175,8 @@ def processAlgorithm(
# Make request and catch ApiError
try:
- response = ors_client.request("/v2/matrix/" + profile, {}, post_json=params)
+ endpoint = self.get_endpoint_names_from_provider(parameters[self.IN_PROVIDER])["matrix"]
+ response = ors_client.request(f"/v2/{endpoint}/{profile}", {}, post_json=params)
except (exceptions.ApiError, exceptions.InvalidKey, exceptions.GenericServerError) as e:
msg = f"{e.__class__.__name__}: {str(e)}"
diff --git a/tests/test_gui.py b/tests/test_gui.py
index d59d4fde..cfce0d7b 100644
--- a/tests/test_gui.py
+++ b/tests/test_gui.py
@@ -1,3 +1,6 @@
+from qgis.PyQt.QtWidgets import QLineEdit
+from qgis._core import QgsSettings
+from qgis.gui import QgsCollapsibleGroupBox
from qgis.testing import unittest
from qgis.PyQt.QtTest import QTest
@@ -10,6 +13,7 @@
)
import pytest
+from .test_proc import TestProc
from tests.utils.utilities import get_qgis_app
CANVAS: QgsMapCanvas
@@ -20,6 +24,7 @@
class TestGui(unittest.TestCase):
def test_without_live_preview(self):
from ORStools.gui.ORStoolsDialog import ORStoolsDialog
+ from ORStools.gui.ORStoolsDialogConfig import ORStoolsDialogConfigMain
from ORStools.utils import maptools
CRS = QgsCoordinateReferenceSystem.fromEpsgId(3857)
@@ -30,6 +35,13 @@ def test_without_live_preview(self):
self.assertEqual(CANVAS.width(), 600)
self.assertEqual(CANVAS.height(), 400)
+ # Set and reset config to test whether the reset works
+ dlg_config = ORStoolsDialogConfigMain()
+ provider = dlg_config.providers.findChildren(QgsCollapsibleGroupBox)[0]
+
+ line_edit = provider.findChild(QLineEdit, "openrouteservice_directions_endpoint")
+ line_edit.setText("thisisnotanendpoint")
+
dlg = ORStoolsDialog(IFACE)
dlg.open()
self.assertTrue(dlg.isVisible())
@@ -245,3 +257,104 @@ def map_dclick(self, x, y, side):
side,
Qt.NoModifier,
)
+
+ def test_ORStoolsDialogConfig_endpoints(self):
+ from ORStools.gui.ORStoolsDialogConfig import ORStoolsDialogConfigMain
+
+ CRS = QgsCoordinateReferenceSystem.fromEpsgId(3857)
+ CANVAS.setExtent(QgsRectangle(258889, 7430342, 509995, 7661955))
+ CANVAS.setDestinationCrs(CRS)
+ CANVAS.setFrameStyle(0)
+ CANVAS.resize(600, 400)
+ self.assertEqual(CANVAS.width(), 600)
+ self.assertEqual(CANVAS.height(), 400)
+
+ # Set and reset config to test whether the reset works
+ dlg_config = ORStoolsDialogConfigMain()
+ provider = dlg_config.providers.findChildren(QgsCollapsibleGroupBox)[0]
+
+ # set endpoint of directions to non-existent value
+ line_edit = provider.findChild(QLineEdit, "openrouteservice_directions_endpoint")
+ line_edit.setText("thisisnotanendpoint")
+ dlg_config.accept()
+
+ settings_directions_endpoint = QgsSettings().value("ORStools/config")["providers"][0][
+ "endpoints"
+ ]["directions"]
+
+ self.assertEqual(settings_directions_endpoint, "thisisnotanendpoint")
+
+ proc = TestProc()
+ proc.setUpClass()
+
+ self.assertRaises(StopIteration, proc.test_directions_points_layer)
+
+ # reset endpoints
+ dlg_config._reset_endpoints()
+
+ dlg_config._reset_endpoints()
+ dlg_config.accept()
+
+ settings_directions_endpoint = QgsSettings().value("ORStools/config")["providers"][0][
+ "endpoints"
+ ]["directions"]
+
+ self.assertEqual(settings_directions_endpoint, "directions")
+
+ layer = proc.test_directions_points_layer()
+
+ self.assertEqual(
+ "POINT(8.67251100000000008 49.39887900000000087)",
+ next(layer.getFeatures()).geometry().asPolyline()[0].asWkt(),
+ )
+
+ def test_ORStoolsDialogConfig_url(self):
+ from ORStools.gui.ORStoolsDialogConfig import ORStoolsDialogConfigMain
+
+ CRS = QgsCoordinateReferenceSystem.fromEpsgId(3857)
+ CANVAS.setExtent(QgsRectangle(258889, 7430342, 509995, 7661955))
+ CANVAS.setDestinationCrs(CRS)
+ CANVAS.setFrameStyle(0)
+ CANVAS.resize(600, 400)
+ self.assertEqual(CANVAS.width(), 600)
+ self.assertEqual(CANVAS.height(), 400)
+
+ # Set and reset config to test whether the reset works
+ dlg_config = ORStoolsDialogConfigMain()
+ provider = dlg_config.providers.findChildren(QgsCollapsibleGroupBox)[0]
+
+ # set endpoint of directions to non-existent value
+ line_edit = provider.findChild(QLineEdit, "openrouteservice_base_url_text")
+ line_edit.setText("thisisnotaurl")
+ dlg_config.accept()
+
+ settings_directions_endpoint = QgsSettings().value("ORStools/config")["providers"][0][
+ "base_url"
+ ]
+
+ self.assertEqual(settings_directions_endpoint, "thisisnotaurl")
+
+ proc = TestProc()
+ proc.setUpClass()
+
+ self.assertRaises(Exception, proc.test_directions_points_layer)
+
+ # reset url
+ url_reset_button = dlg_config.findChild(QPushButton, "openrouteservice_reset_url_button")
+ url_reset_button.clicked.emit()
+
+ dlg_config._reset_endpoints()
+ dlg_config.accept()
+
+ settings_directions_endpoint = QgsSettings().value("ORStools/config")["providers"][0][
+ "endpoints"
+ ]["directions"]
+
+ self.assertEqual(settings_directions_endpoint, "directions")
+
+ layer = proc.test_directions_points_layer()
+
+ self.assertEqual(
+ "POINT(8.67251100000000008 49.39887900000000087)",
+ next(layer.getFeatures()).geometry().asPolyline()[0].asWkt(),
+ )
diff --git a/tests/test_proc.py b/tests/test_proc.py
index 21a2594b..6ec06e0d 100644
--- a/tests/test_proc.py
+++ b/tests/test_proc.py
@@ -16,7 +16,6 @@
from ORStools.proc.isochrones_layer_proc import ORSIsochronesLayerAlgo
from ORStools.proc.isochrones_point_proc import ORSIsochronesPointAlgo
from ORStools.proc.matrix_proc import ORSMatrixAlgo
-from ORStools.proc.export_proc import ORSExportAlgo
class TestProc(unittest.TestCase):
@@ -44,7 +43,7 @@ def setUpClass(cls) -> None:
feature = QgsFeature()
feature.setGeometry(line_geometry)
cls.line_layer.dataProvider().addFeature(feature)
-
+
lower_left = QgsPointXY(8.45, 48.85)
upper_right = QgsPointXY(8.46, 48.86)
cls.bbox = QgsRectangle(lower_left, upper_right)
@@ -101,6 +100,8 @@ def test_directions_points_layer(self):
feat_length = next(processed_layer.getFeatures()).geometry().length()
self.assertTrue(feat_length > 0)
+ return processed_layer
+
def test_directions_points_layers(self):
parameters = {
"INPUT_AVOID_BORDERS": None,
@@ -226,4 +227,3 @@ def test_matrix(self):
# self.assertTrue(feat_point.hasGeometry())
# feat_line = next(processed_nodes.getFeatures())
# self.assertTrue(feat_line.hasGeometry())
-
\ No newline at end of file