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

keep provider selection on re-open #169

Draft
wants to merge 3 commits into
base: main
Choose a base branch
from
Draft
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
8 changes: 7 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,15 @@ RELEASING:
12. Upload the package to https://plugins.qgis.org/plugins/ORStools/ (Manage > Add Version)
13. Create new release in GitHub with tag version and release title of `vX.X.X`
-->
## [Unreleased]

### Added
- active provider storage, persisted between QGIS sessions ([#168](https://github.com/GIScience/orstools-qgis-plugin/pull/166))
- provider storage to processing scripts

## [1.5.2] - 2022-01-20

## Fixed
### Fixed
- error for layers with z/m values ([#166](https://github.com/GIScience/orstools-qgis-plugin/pull/166))

## [1.5.1] - 2022-01-11
Expand Down
12 changes: 11 additions & 1 deletion ORStools/gui/ORStoolsDialog.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
from . import resources_rc



def on_config_click(parent):
"""Pop up provider config window. Outside of classes because it's accessed by multiple dialogs.

Expand Down Expand Up @@ -97,6 +98,12 @@ def on_about_click(parent):
)


def on_change_save_provider(index):
"""Set the provider with the passed index as active provider if it isn't already"""
if index != configmanager.get_active_provider_index():
configmanager.set_active_provider(index)


class ORStoolsDialogMain:
"""Defines all mandatory QGIS things about dialog."""

Expand Down Expand Up @@ -219,6 +226,9 @@ def _init_gui_control(self):
for provider in providers:
self.dlg.provider_combo.addItem(provider['name'], provider)

self.dlg.provider_combo.setCurrentIndex(configmanager.get_active_provider_index())
self.dlg.provider_combo.activated.connect(on_change_save_provider)

self.dlg.show()

def run_gui_control(self):
Expand Down Expand Up @@ -292,7 +302,7 @@ def run_gui_control(self):
params['coordinates'] = directions.get_request_line_feature()
profile = self.dlg.routing_travel_combo.currentText()
# abort on empty avoid polygons layer
if 'options' in params and 'avoid_polygons' in params['options']\
if 'options' in params and 'avoid_polygons' in params['options'] \
and params['options']['avoid_polygons'] == {}:
QMessageBox.warning(
self.dlg,
Expand Down
50 changes: 39 additions & 11 deletions ORStools/proc/base_processing_algorithm.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@

from ORStools import RESOURCE_PREFIX, __help__
from ORStools.utils import configmanager
from ORStools.gui.ORStoolsDialog import on_change_save_provider
from ..common import client, PROFILES, AVOID_BORDERS, AVOID_FEATURES, ADVANCED_PARAMETERS
from ..utils.processing import read_help_file
from ..gui.directions_gui import _get_avoid_polygons
Expand All @@ -66,6 +67,7 @@ def __init__(self):
self.IN_AVOID_POLYGONS = "INPUT_AVOID_POLYGONS"
self.OUT = 'OUTPUT'
self.PARAMETERS = None
self.ORS_CLIENT = None

def createInstance(self) -> Any:
"""
Expand Down Expand Up @@ -119,23 +121,27 @@ def provider_parameter(self) -> QgsProcessingParameterEnum:
Parameter definition for provider, used in all child classes
"""
providers = [provider['name'] for provider in configmanager.read_config()['providers']]
active_provider = providers[configmanager.get_active_provider_index()]
# reorders enum options so the active provider is shown at the top which
# setting the defaultValue of the QgsProcessingParameterEnum here does not work
providers.sort(key=lambda x: x != active_provider)
return QgsProcessingParameterEnum(
self.IN_PROVIDER,
"Provider",
providers,
defaultValue=providers[0]
defaultValue=active_provider
)

def profile_parameter(self) -> QgsProcessingParameterEnum:
"""
Parameter definition for profile, used in all child classes
"""
return QgsProcessingParameterEnum(
self.IN_PROFILE,
"Travel mode",
PROFILES,
defaultValue=PROFILES[0]
)
self.IN_PROFILE,
"Travel mode",
PROFILES,
defaultValue=PROFILES[0]
)

def output_parameter(self) -> QgsProcessingParameterFeatureSink:
"""
Expand Down Expand Up @@ -177,14 +183,32 @@ def option_parameters(self) -> [QgsProcessingParameterDefinition]:
)
]

def _get_provider_from_id(self, provider_id: int) -> dict:
"""
Resolve the index from the reordered QgsProcessingParameterEnum options to the actual provider
dict from the config storage.

Also sets the selected provider to active.

:param provider_id: the provider ID in the dropdown of the processing script
:return:
"""
provider_name = self.provider_parameter().options()[provider_id]
providers = configmanager.read_config()['providers']

ors_provider = next((p for p in providers if p['name'] == provider_name), None)
on_change_save_provider(providers.index(ors_provider))

return ors_provider

@staticmethod
def _get_ors_client_from_provider(provider: str, feedback: QgsProcessingFeedback) -> client.Client:
def _get_ors_client_from_provider(provider: dict, feedback: QgsProcessingFeedback) -> client.Client:
"""
Connects client to provider and returns a client instance for requests to the ors API
"""
providers = configmanager.read_config()['providers']
ors_provider = providers[provider]
ors_client = client.Client(ors_provider)
ors_client = client.Client(provider)
if not ors_client:
feedback.reportError("Provider not found in provider configuration.", fatalError=True)
ors_client.overQueryLimit.connect(lambda: feedback.reportError("OverQueryLimit: Retrying..."))
return ors_client

Expand Down Expand Up @@ -219,7 +243,7 @@ def initAlgorithm(self, configuration):
for param in parameters:
if param.name() in ADVANCED_PARAMETERS:
if self.GROUP == "Matrix":
param.setFlags(param.flags()| QgsProcessingParameterDefinition.FlagHidden)
param.setFlags(param.flags() | QgsProcessingParameterDefinition.FlagHidden)
else:
# flags() is a wrapper around an enum of ints for type-safety.
# Flags are added by or-ing values, much like the union operator would work
Expand All @@ -228,3 +252,7 @@ def initAlgorithm(self, configuration):
self.addParameter(
param
)

def processAlgorithm(self, parameters, context, feedback, **kwargs):
ors_provider = self._get_provider_from_id(parameters[self.IN_PROVIDER])
self.ORS_CLIENT = self._get_ors_client_from_provider(ors_provider, feedback)
8 changes: 4 additions & 4 deletions ORStools/proc/directions_lines_proc.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,8 +82,8 @@ def __init__(self):
)
]

def processAlgorithm(self, parameters, context, feedback):
ors_client = self._get_ors_client_from_provider(parameters[self.IN_PROVIDER], feedback)
def processAlgorithm(self, parameters, context, feedback, **kwargs):
super().processAlgorithm(parameters, context, feedback, **kwargs)

profile = dict(enumerate(PROFILES))[parameters[self.IN_PROFILE]]

Expand Down Expand Up @@ -130,7 +130,7 @@ def processAlgorithm(self, parameters, context, feedback):
try:
if optimization_mode is not None:
params = get_params_optimize(line, profile, optimization_mode)
response = ors_client.request('/optimization', {}, post_json=params)
response = self.ORS_CLIENT.request('/optimization', {}, post_json=params)

sink.addFeature(directions_core.get_output_features_optimization(
response,
Expand All @@ -139,7 +139,7 @@ def processAlgorithm(self, parameters, context, feedback):
))
else:
params = directions_core.build_default_parameters(preference, point_list=line, options=options)
response = ors_client.request('/v2/directions/' + profile + '/geojson', {}, post_json=params)
response = self.ORS_CLIENT.request('/v2/directions/' + profile + '/geojson', {}, post_json=params)

sink.addFeature(directions_core.get_output_feature_directions(
response,
Expand Down
8 changes: 4 additions & 4 deletions ORStools/proc/directions_points_layer_proc.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,8 @@ def __init__(self):
)
]

def processAlgorithm(self, parameters, context, feedback):
ors_client = self._get_ors_client_from_provider(parameters[self.IN_PROVIDER], feedback)
def processAlgorithm(self, parameters, context, feedback, **kwargs):
super().processAlgorithm(parameters, context, feedback, **kwargs)

profile = dict(enumerate(PROFILES))[parameters[self.IN_PROFILE]]

Expand Down Expand Up @@ -160,7 +160,7 @@ def sort(f): return f.id()
try:
if optimization_mode is not None:
params = get_params_optimize(points, profile, optimization_mode)
response = ors_client.request('/optimization', {}, post_json=params)
response = self.ORS_CLIENT.request('/optimization', {}, post_json=params)

sink.addFeature(directions_core.get_output_features_optimization(
response,
Expand All @@ -169,7 +169,7 @@ def sort(f): return f.id()
))
else:
params = directions_core.build_default_parameters(preference, point_list=points, options=options)
response = ors_client.request('/v2/directions/' + profile + '/geojson', {}, post_json=params)
response = self.ORS_CLIENT.request('/v2/directions/' + profile + '/geojson', {}, post_json=params)

sink.addFeature(directions_core.get_output_feature_directions(
response,
Expand Down
6 changes: 3 additions & 3 deletions ORStools/proc/directions_points_layers_proc.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,8 +111,8 @@ def __init__(self):

# TODO: preprocess parameters to options the range cleanup below:
# https://www.qgis.org/pyqgis/master/core/Processing/QgsProcessingAlgorithm.html#qgis.core.QgsProcessingAlgorithm.preprocessParameters
def processAlgorithm(self, parameters, context, feedback):
ors_client = self._get_ors_client_from_provider(parameters[self.IN_PROVIDER], feedback)
def processAlgorithm(self, parameters, context, feedback, **kwargs):
super().processAlgorithm(parameters, context, feedback, **kwargs)

profile = dict(enumerate(PROFILES))[parameters[self.IN_PROFILE]]

Expand Down Expand Up @@ -186,7 +186,7 @@ def sort_end(f): return f.id()
params = directions_core.build_default_parameters(preference, coordinates=coordinates, options=options)

try:
response = ors_client.request('/v2/directions/' + profile + '/geojson', {}, post_json=params)
response = self.ORS_CLIENT.request('/v2/directions/' + profile + '/geojson', {}, post_json=params)
except (exceptions.ApiError,
exceptions.InvalidKey,
exceptions.GenericServerError) as e:
Expand Down
6 changes: 3 additions & 3 deletions ORStools/proc/isochrones_layer_proc.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,8 +94,8 @@ def __init__(self):

# TODO: preprocess parameters to options the range cleanup below:
# https://www.qgis.org/pyqgis/master/core/Processing/QgsProcessingAlgorithm.html#qgis.core.QgsProcessingAlgorithm.prepareAlgorithm
def processAlgorithm(self, parameters, context, feedback):
ors_client = self._get_ors_client_from_provider(parameters[self.IN_PROVIDER], feedback)
def processAlgorithm(self, parameters, context, feedback, **kwargs):
super().processAlgorithm(parameters, context, feedback, **kwargs)

profile = dict(enumerate(PROFILES))[parameters[self.IN_PROFILE]]
dimension = dict(enumerate(DIMENSIONS))[parameters[self.IN_METRIC]]
Expand Down Expand Up @@ -152,7 +152,7 @@ def processAlgorithm(self, parameters, context, feedback):
# If feature causes error, report and continue with next
try:
# Populate features from response
response = ors_client.request('/v2/isochrones/' + profile, {}, post_json=params)
response = self.ORS_CLIENT.request('/v2/isochrones/' + profile, {}, post_json=params)

for isochrone in self.isochrones.get_features(response, params['id']):
sink.addFeature(isochrone)
Expand Down
6 changes: 3 additions & 3 deletions ORStools/proc/isochrones_point_proc.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,8 @@ def __init__(self):

# TODO: preprocess parameters to options the range cleanup below:
# https://www.qgis.org/pyqgis/master/core/Processing/QgsProcessingAlgorithm.html#qgis.core.QgsProcessingAlgorithm.preprocessParameters
def processAlgorithm(self, parameters, context, feedback):
ors_client = self._get_ors_client_from_provider(parameters[self.IN_PROVIDER], feedback)
def processAlgorithm(self, parameters, context, feedback, **kwargs):
super().processAlgorithm(parameters, context, feedback, **kwargs)

profile = dict(enumerate(PROFILES))[parameters[self.IN_PROFILE]]
dimension = dict(enumerate(DIMENSIONS))[parameters[self.IN_METRIC]]
Expand Down Expand Up @@ -113,7 +113,7 @@ def processAlgorithm(self, parameters, context, feedback):
self.crs_out)

try:
response = ors_client.request('/v2/isochrones/' + profile, {}, post_json=params)
response = self.ORS_CLIENT.request('/v2/isochrones/' + profile, {}, post_json=params)

# Populate features from response
for isochrone in self.isochrones.get_features(response, params['id']):
Expand Down
6 changes: 3 additions & 3 deletions ORStools/proc/matrix_proc.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,8 @@ def __init__(self):
),
]

def processAlgorithm(self, parameters, context, feedback):
ors_client = self._get_ors_client_from_provider(parameters[self.IN_PROVIDER], feedback)
def processAlgorithm(self, parameters, context, feedback, **kwargs):
super().processAlgorithm(parameters, context, feedback, **kwargs)

# Get profile value
profile = dict(enumerate(PROFILES))[parameters[self.IN_PROFILE]]
Expand Down Expand Up @@ -162,7 +162,7 @@ def processAlgorithm(self, parameters, context, feedback):

# Make request and catch ApiError
try:
response = ors_client.request('/v2/matrix/' + profile, {}, post_json=params)
response = self.ORS_CLIENT.request('/v2/matrix/' + profile, {}, post_json=params)

except (exceptions.ApiError,
exceptions.InvalidKey,
Expand Down
Loading