Skip to content

Commit

Permalink
Merge pull request #559 from kartoza/timlinux/issue434
Browse files Browse the repository at this point in the history
  • Loading branch information
timlinux authored Nov 4, 2024
2 parents 0583968 + be4748a commit 5e7ef92
Show file tree
Hide file tree
Showing 5 changed files with 130 additions and 116 deletions.
78 changes: 25 additions & 53 deletions geest/core/json_tree_item.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,6 @@ def __init__(self, data, role, guid=None, parent=None):

self._visible = True

self.updateStatus()

def set_visibility(self, visible: bool):
"""Sets the visibility of this item."""
self._visible = visible
Expand Down Expand Up @@ -109,6 +107,14 @@ def isDimension(self):
def isAnalysis(self):
return self.role == "analysis"

def clear(self):
"""
Mark the item as not run, keeping any configurations made
"""
data = self.itemData[3]
data["result"] = "Not run"
data["result_file"] = ""

def getIcon(self):
"""Retrieve the appropriate icon for the item based on its role."""
if self.isDimension():
Expand Down Expand Up @@ -145,37 +151,23 @@ def getItemTooltip(self):
def getStatusIcon(self):
"""Retrieve the appropriate icon for the item based on its role."""
status = self.getStatus()
if status == "✔️":
if status == "Completed successfully":
return QIcon(resources_path("resources", "icons", "completed-success.svg"))
elif status == "-":
elif status == "Required and not configured":
return QIcon(
resources_path("resources", "icons", "required-not-configured.svg")
)
elif status == "!":
elif status == "Not configured (optional)":
return QIcon(resources_path("resources", "icons", "not-configured.svg"))
elif status == "x":
elif status == "Configured, not run":
return QIcon(resources_path("resources", "icons", "not-run.svg"))
elif status == "Workflow failed":
return QIcon(resources_path("resources", "icons", "failed.svg"))
elif status == "e":
elif status == "WRITE TOOL TIP":
return QIcon(resources_path("resources", "icons", ".svg"))
else:
return QIcon(resources_path("resources", "icons", ".svg"))

def getStatusTooltip(self):
"""Retrieve the appropriate tooltip for the item based on its role."""
status = self.getStatus()
if status == "✔️":
return "Completed successfully"
elif status == "-":
return "Required and not configured"
elif status == "!":
return "Not configured (optional)"
elif status == "x":
return "Workflow failed"
elif status == "e":
return "WRITE TOOL TIP"
else:
return ""

def getStatus(self):
"""Return the status of the item as single character."""
try:
Expand All @@ -188,23 +180,26 @@ def getStatus(self):
# QgsMessageLog.logMessage(f"Data: {data}", tag="Geest", level=Qgis.Info)
status = ""
if "Error" in data.get("result", ""):
return "x"
return "Workflow failed"
if "Failed" in data.get("result", ""):
return "x"
return "Workflow failed"
# Item required and not configured
if "Do Not Use" in data.get("analysis_mode", "") and data.get(
"indicator_required", False
):
return "-"
return "Required and not configured"
# Item not required but not configured
if "Do Not Use" in data.get("analysis_mode", "") and not data.get(
"indicator_required", False
):
return "!"
return "Not configured (optional)"
if "Not run" in data.get("result", "") and not data.get("result_file", ""):
return "Configured, not run"
if "Workflow Completed" not in data.get("result", ""):
return "x"
return "Workflow failed"
if "Workflow Completed" in data.get("result", ""):
return "✔️"
return "Completed successfully"
return "WRITE TOOL TIP"

except Exception as e:
verbose_mode = setting("verbose_mode", False)
Expand All @@ -215,30 +210,7 @@ def getStatus(self):
QgsMessageLog.logMessage(
traceback.format_exc(), tag="Geest", level=Qgis.Warning
)
return "e" # e for error

def updateStatus(self, status=None):
"""Update the status of the item.
If no status is provided we will compute the best status based on the item's attributes.
:param status: The status to set the item to.
:return: None
Note: The status is stored in the second column of the itemData
"""
try:
if status is None:
status = self.getStatus()
# self.itemData[1] = status - taken care of by decoration role rather
except Exception as e:
QgsMessageLog.logMessage(
f"Error updating status: {e}", tag="Geest", level=Qgis.Warning
)
QgsMessageLog.logMessage(
traceback.format_exc(), tag="Geest", level=Qgis.Warning
)
return "WRITE TOOL TIP"

def getFont(self):
"""Retrieve the appropriate font for the item based on its role."""
Expand Down
59 changes: 57 additions & 2 deletions geest/gui/panels/tree_panel.py
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,10 @@ def __init__(self, parent=None, json_file=None):
)
button_bar.addWidget(self.toggle_visibility_button)

self.clear_button = QPushButton("Clear", self)
self.clear_button.clicked.connect(self.clear_button_clicked)
button_bar.addWidget(self.clear_button)

self.project_button = QPushButton("Project")
self.project_button.clicked.connect(self.switch_to_previous_tab)
button_bar.addWidget(self.project_button)
Expand Down Expand Up @@ -263,6 +267,15 @@ def on_previous_button_clicked(self):
def on_next_button_clicked(self):
self.switch_to_next_tab.emit()

def clear_button_clicked(self):
"""
Slot for handling the clear button click.
This method is needed to avoid passing bool via the slot.
"""
self._clear_workflows()
self.save_json_to_working_directory()

@pyqtSlot(str)
def working_directory_changed(self, new_directory):
"""Change the working directory and load the model.json if available."""
Expand Down Expand Up @@ -812,6 +825,49 @@ def _start_workflows(self, parent_item, role=None):
# Recursively process children (dimensions, factors)
self._start_workflows(child_item, role)

def _clear_workflows(self, parent_item=None):
"""
Recursively mark workflows as not done, delete their working directories and their file_paths.
It will reflect the self.run_only_incomplete flag to only clear incomplete workflows if requested.
:param parent_item: The parent item to process. If none, start from the root.
"""
# if the parent item is a boolean, it means we are running this from the clear button
if parent_item is None:
parent_item = self.model.rootItem
for i in range(parent_item.childCount()):
child_item = parent_item.child(i)
self._clear_workflows(child_item)
if child_item.data(3).get("result_file", None) and self.run_only_incomplete:
# if the item role is indicator, remove its entire folder
if child_item.role == "indicator":
result_file = child_item.data(3).get("result_file")
if result_file:
folder = os.path.dirname(result_file)
# check the folder exists
if os.path.exists(folder):
QgsMessageLog.logMessage(
f"Removing {folder}", tag="Geest", level=Qgis.Info
)
shutil.rmtree(folder)
# if the item rols if factor or dimension, remove the files in it
# but not subdirs in case the user elected to keep them
else:
result_file = child_item.data(3).get("result_file")
if result_file:
folder = os.path.dirname(result_file)
# check if the folder exists
if os.path.exists(folder):
for file in os.listdir(folder):
file_path = os.path.join(folder, file)
if os.path.isfile(file_path):
os.remove(file_path)
child_item.clear() # sets status to not run and blanks file path

elif not self.run_only_incomplete:
child_item.clear()

def _count_workflows_to_run(self, parent_item=None):
"""
Recursively count workflows that need to be run visiting each node in the tree.
Expand Down Expand Up @@ -942,8 +998,6 @@ def on_workflow_completed(self, item, success):
"""
self.overall_progress_bar.setValue(self.overall_progress_bar.value() + 1)
self.workflow_progress_bar.setValue(100)

item.updateStatus()
self.save_json_to_working_directory()

self.add_to_map(item)
Expand Down Expand Up @@ -978,6 +1032,7 @@ def run_all(self):
self.run_only_incomplete = False
self.items_to_run = 0
self._count_workflows_to_run()
self._clear_workflows()
self._queue_workflows()

def run_incomplete(self):
Expand Down
22 changes: 11 additions & 11 deletions geest/gui/views/treeview.py
Original file line number Diff line number Diff line change
Expand Up @@ -233,11 +233,11 @@ def toggle_indicator_visibility(self, visible: bool, parent_item=None):
visible (bool): Whether to show or hide the indicator nodes.
parent_item (JsonTreeItem): Optional parent item to start from. If None, start from root.
"""
QgsMessageLog.logMessage(
f"Toggling item visibility for item (was {visible})",
tag="Geest",
level=Qgis.Info,
)
# QgsMessageLog.logMessage(
# f"Toggling item visibility for item (was {visible})",
# tag="Geest",
# level=Qgis.Info,
# )

parent_item = parent_item if parent_item else self.rootItem
for i in range(parent_item.childCount()):
Expand Down Expand Up @@ -289,7 +289,7 @@ def data(self, index, role):
): # Icon for the status column
return item.getStatusIcon()
elif role == Qt.ToolTipRole and index.column() == 1:
return item.getStatusTooltip()
return item.getStatus()
elif role == Qt.ToolTipRole and index.column() == 0:
return item.getItemTooltip()
elif role == Qt.FontRole:
Expand Down Expand Up @@ -708,11 +708,11 @@ def toggle_indicator_nodes(self):
"""Toggles visibility of all indicator nodes."""
indicators_visible = self._indicators_visible()
self.model().toggle_indicator_visibility(not indicators_visible)
QgsMessageLog.logMessage(
f"Toggled indicator nodes (was {indicators_visible})",
tag="Geest",
level=Qgis.Info,
)
# QgsMessageLog.logMessage(
# f"Toggled indicator nodes (was {indicators_visible})",
# tag="Geest",
# level=Qgis.Info,
# )

def _indicators_visible(self):
"""Checks if indicators are currently visible."""
Expand Down
56 changes: 6 additions & 50 deletions geest/resources/icons/completed-success.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
31 changes: 31 additions & 0 deletions geest/resources/icons/not-run.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 5e7ef92

Please sign in to comment.