Skip to content

Commit

Permalink
Merge pull request #586 from kartoza/timlinux/issue577
Browse files Browse the repository at this point in the history
  • Loading branch information
timlinux authored Nov 10, 2024
2 parents cc493d2 + ebac931 commit 845fbf4
Show file tree
Hide file tree
Showing 21 changed files with 1,721 additions and 799 deletions.
97 changes: 65 additions & 32 deletions geest/core/tasks/ors_checker.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,63 +4,96 @@
QgsTask,
QgsMessageLog,
Qgis,
QgsNetworkAccessManager,
QgsNetworkReplyContent,
)
from qgis.PyQt.QtCore import QUrl
from qgis.PyQt.QtNetwork import QNetworkRequest
from qgis.PyQt.QtCore import pyqtSignal
from geest.core import setting
from geest.core.ors_client import ORSClient


class OrsCheckerTask(QgsTask):
# Crashes QGIS
# job_finished = pyqtSignal(bool)
# job_failed = pyqtSignal(str)
# Custom signal to emit when the job is finished
job_finished = pyqtSignal(bool)

def __init__(self, url: str):
super().__init__("ORS download task", QgsTask.CanCancel)
self.output_dir = "/tmp/"
self.content = None
super().__init__("ORS API Key Validation Task", QgsTask.CanCancel)
self.url = url
self.exception: Optional[Exception] = None
self.is_key_valid = False # Store whether the key is valid or not
self.ors_client = ORSClient("https://api.openrouteservice.org/v2/isochrones")

def run(self):
"""Do the work."""
"""Do the work to validate the ORS API key."""
try:
nam = QgsNetworkAccessManager()
# Retrieve the ORS API key from settings
ors_key = setting("ors_key", "")
if not ors_key:
raise ValueError("ORS API key is missing from settings.")
params = {
"locations": [[8.681495, 49.41461]],
"range": [100, 500], # Distances or times in the list
"range_type": "distance",
}
mode = "foot-walking"
# Make the request to ORS API using ORSClient
response = self.ors_client.make_request(mode, params)
QgsMessageLog.logMessage(
f"ORS API Key Validation Task response: {response}",
tag="Geest",
level=Qgis.Info,
)
# Assuming the response JSON contains a 'status' field
if response.get("type") == "FeatureCollection":
self.is_key_valid = True
QgsMessageLog.logMessage(
"ORS API Key is valid.", tag="Geest", level=Qgis.Info
)
else:
self.is_key_valid = False
QgsMessageLog.logMessage(
"ORS API Key is invalid.", tag="Geest", level=Qgis.Warning
)

# get the new tile if it didn't exist
url = QUrl(f"{self.url}")
request = QNetworkRequest(url)
reply: QgsNetworkReplyContent = nam.blockingGet(request)
self.content = reply.content()
# write the content to "/tmp/ors_response.json"
with open("/tmp/ors_response.json", "wb") as f:
f.write(self.content)
self.setProgress(100)

return True
except Exception as e:
# Dont raise the exception in a thread, you will crash QGIS
self.exception = e
QgsMessageLog.logMessage(
f"Exception in ORS API Key Validation Task: {str(e)}",
tag="Geest",
level=Qgis.Critical,
)
return False

def finished(self, result):
"""Postprocessing after the run() method."""
if self.isCanceled():
# if it was canceled by the user
QgsMessageLog.logMessage(
message=f"Canceled download task.",
"ORS API Key Validation Task was canceled by the user.",
tag="Geest",
level=Qgis.Warning,
)
self.job_finished.emit(False)
return
elif not result:
# if there was an error

if not result:
QgsMessageLog.logMessage(
message=f"Canceled download task.",
level=Qgis.Warning,
"ORS API Key Validation Task failed.", tag="Geest", level=Qgis.Critical
)
if self.exception:
QgsMessageLog.logMessage(
f"Error: {self.exception}", tag="Geest", level=Qgis.Critical
)
self.job_finished.emit(False)
return
QgsMessageLog.logMessage(
message=f"ORS Check Succeeded.",
level=Qgis.Warning,
)

# Check the result of the API key validation
if self.is_key_valid:
QgsMessageLog.logMessage(
"ORS API Key is valid.", tag="Geest", level=Qgis.Info
)
self.job_finished.emit(True)
else:
QgsMessageLog.logMessage(
"ORS API Key is invalid.", tag="Geest", level=Qgis.Warning
)
self.job_finished.emit(False)
2 changes: 1 addition & 1 deletion geest/core/workflow_queue_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ def add_task(self, task: QgsTask) -> None:
.
:param task: A QgsTask object representing the task
"""
# ⭐️ Now we are passing the item reference to the WorkflowJob
# ⭐️ Now we are passing the item ritemeference to the WorkflowJob
# any changes made to the item will be reflected in the tree directly

self.workflow_queue.add_job(task)
Expand Down
124 changes: 107 additions & 17 deletions geest/gui/geest_dock.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,21 @@
QWidget,
)
from qgis.PyQt.QtCore import Qt
from qgis.PyQt.QtGui import QPixmap, QPainter

from qgis.core import QgsMessageLog, Qgis, QgsProject
from typing import Optional
from geest.gui.panels import IntroPanel, SetupPanel, TreePanel, HelpPanel
from geest.gui.panels import (
IntroPanel,
SetupPanel,
TreePanel,
HelpPanel,
OrsPanel,
OpenProjectPanel,
CreateProjectPanel,
)
from geest.core import set_setting, setting
from geest.utilities import resources_path


class GeestDock(QDockWidget):
Expand All @@ -34,6 +45,11 @@ def __init__(
layout.setContentsMargins(0, 0, 0, 0) # Remove margins for a cleaner look
layout.setSpacing(0) # Remove spacing between elements

# Load the background image
self.background_image = QPixmap(
resources_path("resources", "images", "background.png")
)

# Create a stacked widget
self.stacked_widget: QStackedWidget = QStackedWidget()

Expand All @@ -42,25 +58,80 @@ def __init__(
self.intro_widget: IntroPanel = IntroPanel()
intro_panel: QWidget = QWidget()
intro_layout: QVBoxLayout = QVBoxLayout(intro_panel)
intro_layout.setContentsMargins(0, 0, 0, 0) # Minimize padding
intro_layout.setContentsMargins(10, 10, 10, 10) # Minimize padding
intro_layout.addWidget(self.intro_widget)
self.stacked_widget.addWidget(intro_panel)
self.intro_widget.switch_to_next_tab.connect(
# Switch to the next tab when the button is clicked
lambda: self.stacked_widget.setCurrentIndex(1)
)
# Create and add the "ORS" panel (ORSPanel)
self.ors_widget: OrsPanel = OrsPanel()
ors_panel: QWidget = QWidget()
ors_layout: QVBoxLayout = QVBoxLayout(ors_panel)
ors_layout.setContentsMargins(10, 10, 10, 10) # Minimize padding
ors_layout.addWidget(self.ors_widget)
self.stacked_widget.addWidget(ors_panel)
self.ors_widget.switch_to_next_tab.connect(
# Switch to the next tab when the button is clicked
lambda: self.stacked_widget.setCurrentIndex(2)
)
self.ors_widget.switch_to_previous_tab.connect(
# Switch to the next tab when the button is clicked
lambda: self.stacked_widget.setCurrentIndex(0)
)

# Create and add the "Project" panel (SetupPanel)
self.setup_widget: SetupPanel = SetupPanel()
project_panel: QWidget = QWidget()
project_layout: QVBoxLayout = QVBoxLayout(project_panel)
project_layout.setContentsMargins(0, 0, 0, 0) # Minimize padding
project_layout.addWidget(self.setup_widget)
self.stacked_widget.addWidget(project_panel)
setup_panel: QWidget = QWidget()
setup_layout: QVBoxLayout = QVBoxLayout(setup_panel)
setup_layout.setContentsMargins(10, 10, 10, 10) # Minimize padding
setup_layout.addWidget(self.setup_widget)
self.stacked_widget.addWidget(setup_panel)

self.setup_widget.switch_to_next_tab.connect(
self.setup_widget.switch_to_load_project_tab.connect(
# Switch to the next tab when the button is clicked
lambda: self.stacked_widget.setCurrentIndex(2)
lambda: self.stacked_widget.setCurrentIndex(3)
)

self.setup_widget.switch_to_create_project_tab.connect(
# Switch to the next tab when the button is clicked
lambda: self.stacked_widget.setCurrentIndex(4)
)

self.setup_widget.switch_to_previous_tab.connect(
# Switch to the next tab when the button is clicked
lambda: self.stacked_widget.setCurrentIndex(1)
)

# Create and add the "Open Project" panel
self.open_project_widget: OpenProjectPanel = OpenProjectPanel()
open_project_panel: QWidget = QWidget()
open_project_layout: QVBoxLayout = QVBoxLayout(open_project_panel)
open_project_layout.setContentsMargins(10, 10, 10, 10) # Minimize padding
open_project_layout.addWidget(self.open_project_widget)
self.stacked_widget.addWidget(open_project_panel)

self.open_project_widget.switch_to_next_tab.connect(
# Switch to the next tab when the button is clicked
lambda: self.stacked_widget.setCurrentIndex(5)
)
self.open_project_widget.switch_to_previous_tab.connect(
# Switch to the next tab when the button is clicked
lambda: self.stacked_widget.setCurrentIndex(3)
)

# Create and add the "Create Project" panel
self.create_project_widget: CreateProjectPanel = CreateProjectPanel()
create_project_panel: QWidget = QWidget()
create_project_layout: QVBoxLayout = QVBoxLayout(create_project_panel)
create_project_layout.setContentsMargins(10, 10, 10, 10) # Minimize padding
create_project_layout.addWidget(self.create_project_widget)
self.stacked_widget.addWidget(create_project_panel)

self.create_project_widget.switch_to_next_tab.connect(
# Switch to the next tab when the button is clicked
lambda: self.stacked_widget.setCurrentIndex(5)
)

# Create and add the "Tree" panel (TreePanel)
Expand All @@ -72,11 +143,11 @@ def __init__(
self.stacked_widget.addWidget(tree_panel)
self.tree_widget.switch_to_next_tab.connect(
# Switch to the next tab when the button is clicked
lambda: self.stacked_widget.setCurrentIndex(3)
lambda: self.stacked_widget.setCurrentIndex(4)
)
self.tree_widget.switch_to_previous_tab.connect(
# Switch to the previous tab when the button is clicked
lambda: self.stacked_widget.setCurrentIndex(1)
lambda: self.stacked_widget.setCurrentIndex(2)
)
# Create and add the "Help" panel (HelpPanel)
help_widget: HelpPanel = HelpPanel()
Expand All @@ -87,7 +158,7 @@ def __init__(
self.stacked_widget.addWidget(help_panel)
help_widget.switch_to_previous_tab.connect(
# Switch to the previous tab when the button is clicked
lambda: self.stacked_widget.setCurrentIndex(2)
lambda: self.stacked_widget.setCurrentIndex(5)
)
# Add the stacked widget to the main layout
layout.addWidget(self.stacked_widget)
Expand All @@ -106,6 +177,7 @@ def __init__(

# Connect panel change event if custom logic is needed when switching panels
self.stacked_widget.currentChanged.connect(self.on_panel_changed)

QgsMessageLog.logMessage("GeestDock initialized successfully.", "Geest")

except Exception as e:
Expand All @@ -115,6 +187,22 @@ def __init__(
level=Qgis.Critical,
)

def paintEvent(self, event):
with QPainter(self) as painter:
# Calculate the scaling and cropping offsets
scaled_background = self.background_image.scaled(
self.size(), Qt.KeepAspectRatioByExpanding
)

# Calculate the offset to crop from top and right to keep bottom left anchored
x_offset = max(0, scaled_background.width() - self.width())
y_offset = max(0, scaled_background.height() - self.height())

# Draw the image at the negative offsets
painter.drawPixmap(-x_offset, -y_offset, scaled_background)

super().paintEvent(event)

def qgis_project_changed(self) -> None:
"""
Handle QGIS project change events.
Expand All @@ -134,7 +222,7 @@ def qgis_project_changed(self) -> None:
)
if geest_project and os.path.exists(geest_project):
self.tree_widget.set_working_directory(geest_project)
self.stacked_widget.setCurrentIndex(2) # Tree tab
self.stacked_widget.setCurrentIndex(5) # Tree tab

def on_panel_changed(self, index: int) -> None:
"""
Expand All @@ -144,10 +232,12 @@ def on_panel_changed(self, index: int) -> None:
"""
if index == 0:
QgsMessageLog.logMessage("Switched to Intro panel", "Geest", Qgis.Info)
elif index == 1:
QgsMessageLog.logMessage("Switched to Project panel", "Geest", Qgis.Info)
if index == 1:
QgsMessageLog.logMessage("Switched to ORS panel", "Geest", Qgis.Info)
elif index == 2:
QgsMessageLog.logMessage("Switched to Tree panel", "Geest", Qgis.Info)
self.tree_widget.set_working_directory(self.setup_widget.working_dir)
QgsMessageLog.logMessage("Switched to Project panel", "Geest", Qgis.Info)
elif index == 3:
QgsMessageLog.logMessage("Switched to Tree panel", "Geest", Qgis.Info)
# self.tree_widget.set_working_directory(self.setup_widget.working_dir)
elif index == 4:
QgsMessageLog.logMessage("Switched to Help panel", "Geest", Qgis.Info)
3 changes: 3 additions & 0 deletions geest/gui/panels/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,6 @@
from .setup_panel import SetupPanel
from .tree_panel import TreePanel
from .help_panel import HelpPanel
from .ors_panel import OrsPanel
from .create_project_panel import CreateProjectPanel
from .open_project_panel import OpenProjectPanel
Loading

0 comments on commit 845fbf4

Please sign in to comment.