Skip to content

Commit

Permalink
Merge pull request #398 from kartoza/timlinux/issue377
Browse files Browse the repository at this point in the history
This provides an interim workflow for the setup page
  • Loading branch information
timlinux authored Oct 10, 2024
2 parents fa5800a + 0c6b3f1 commit d4fb55f
Show file tree
Hide file tree
Showing 27 changed files with 628 additions and 509 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -75,3 +75,4 @@ app.py

.shell.nix.swp
geest.tar.gz
gitlog.txt
2 changes: 2 additions & 0 deletions geest/core/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,7 @@
from .settings import setting, set_setting

from .default_settings import default_settings
from .json_tree_item import JsonTreeItem
from .workflow_queue_manager import WorkflowQueueManager

# from .json_validator import JSONValidator
235 changes: 235 additions & 0 deletions geest/core/json_tree_item.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,235 @@
from qgis.PyQt.QtCore import (
Qt,
)

# Change to this when implementing in QGIS
# from qgis.PyQt.QtGui import (
from PyQt5.QtGui import QColor, QFont, QIcon
from qgis.core import QgsMessageLog, Qgis
from geest.utilities import resources_path


class JsonTreeItem:
"""A class representing a node in the tree.
🚩 TAKE NOTE: 🚩
This class may NOT inherit from QObject, as it has to remain
thread safe and not be tied to the main thread. Items are passed to
workflow threads and must be able to be manipulated in the background.
"""

def __init__(self, data, role, parent=None):
self.parentItem = parent
self.itemData = data
self.childItems = []
self.role = role # Stores whether an item is a dimension, factor, or layer
self.font_color = QColor(Qt.black) # Default font color

# Define icons for each role
self.dimension_icon = QIcon(
resources_path("resources", "icons", "dimension.svg")
)
self.factor_icon = QIcon(resources_path("resources", "icons", "factor.svg"))
self.indicator_icon = QIcon(
resources_path("resources", "icons", "indicator.svg")
)

# Define fonts for each role
self.dimension_font = QFont()
self.dimension_font.setBold(True)

self.factor_font = QFont()
self.factor_font.setItalic(True)

def appendChild(self, item):
self.childItems.append(item)

def child(self, row):
return self.childItems[row]

def childCount(self):
return len(self.childItems)

def columnCount(self):
return len(self.itemData)

def data(self, column):
if column < len(self.itemData):
return self.itemData[column]
return None

def setData(self, column, value):
if column == 3:
QgsMessageLog.logMessage(
f"JsonTreeItem setData: {value} for column {column} ",
tag="Geest JsonTreeItem",
level=Qgis.Info,
)
if column < len(self.itemData):
self.itemData[column] = value
return True
return False

def parent(self):
return self.parentItem

def row(self):
if self.parentItem:
return self.parentItem.childItems.index(self)
return 0

def isIndicator(self):
return self.role == "layer"

def isFactor(self):
return self.role == "factor"

def isDimension(self):
return self.role == "dimension"

def get_icon(self):
"""Retrieve the appropriate icon for the item based on its role."""
if self.isDimension():
return self.dimension_icon
elif self.isFactor():
return self.factor_icon
elif self.isIndicator():
return self.indicator_icon
return None

def get_font(self):
"""Retrieve the appropriate font for the item based on its role."""
if self.isDimension():
return self.dimension_font
elif self.isFactor():
return self.factor_font
return QFont()

def getPaths(self) -> []:
"""Return the path of the item in the tree in the form dimension/factor/indicator.
:return: A list of strings representing the path of the item in the tree.
"""
path = []
if self.isIndicator():
path.append(
self.parentItem.parentItem.itemData[3]
.get("id", "")
.lower()
.replace(" ", "_")
)
path.append(
self.parentItem.itemData[3].get("id", "").lower().replace(" ", "_")
)
path.append(self.itemData[3].get("id", "").lower().replace(" ", "_"))
elif self.isFactor():
path.append(
self.parentItem.itemData[3].get("id", "").lower().replace(" ", "_")
)
path.append(self.itemData[3].get("id", "").lower().replace(" ", "_"))
if self.isDimension():
path.append(self.itemData[3].get("id", "").lower().replace(" ", "_"))
return path

def getIndicatorAttributes(self):
"""Return the dict of indicators (or layers) under this factor."""
attributes = {}
if self.isIndicator():
attributes["Dimension ID"] = self.parentItem.itemData[3].get("id", "")
attributes["Factor ID"] = self.data(0)
attributes["Indicators"] = [
{
"Indicator ID": i,
"Indicator Name": child.data(0),
"Indicator Weighting": child.data(2),
"Indicator Result File": child.data(3).get(
"Indicator Result File", ""
),
}
for i, child in enumerate(self.childItems)
]
return attributes

def getFactorAttributes(self):
"""Return the dict of indicators (or layers) under this factor."""
attributes = {}
if self.isFactor():
attributes["Dimension ID"] = self.parentItem.itemData[3].get("id", "")
attributes["Analysis Mode"] = "Factor Aggregation"
attributes["Factor ID"] = self.data(0)
attributes["Indicators"] = [
{
"Indicator ID": i,
"Indicator Name": child.data(0),
"Indicator Weighting": child.data(2),
"Indicator Result File": child.data(3).get(
"Indicator Result File", ""
),
}
for i, child in enumerate(self.childItems)
]
return attributes

def getDimensionAttributes(self):
"""Return the dict of factors under this dimension."""
attributes = {}
if self.isDimension():
attributes["Analysis Mode"] = "Dimension Aggregation"
attributes["Dimension ID"] = self.data(0)
attributes["Factors"] = [
{
"Factor ID": i,
"Factor Name": child.data(0),
"Factor Weighting": child.data(2),
"Factor Result File": child.data(3).get(f"Factor Result File", ""),
}
for i, child in enumerate(self.childItems)
]
return attributes

def getAnalysisAttributes(self):
"""Return the dict of dimensions under this analysis."""
attributes = {}
if self.isFactor():
attributes["Analysis Mode"] = "Top Level Aggregation"
attributes["Analysis ID"] = self.data(0)
attributes["Dimensions"] = [
{
"Dimension ID": i,
"Dimension Name": child.data(0),
"Dimension Weighting": child.data(2),
"Dimension Result File": child.data(3).get(
f"Dimension Result File", ""
),
}
for i, child in enumerate(self.childItems)
]
return attributes

def updateIndicatorWeighting(self, indicator_name, new_weighting):
"""Update the weighting of a specific indicator by its name."""
try:
# Search for the indicator by name
indicator_item = next(
(child for child in self.childItems if child.data(0) == indicator_name),
None,
)

# If found, update the weighting
if indicator_item:
indicator_item.setData(2, f"{new_weighting:.2f}")
else:
# Log if the indicator name is not found
QgsMessageLog.logMessage(
f"Indicator '{indicator_name}' not found.",
tag="Geest",
level=Qgis.Warning,
)

except Exception as e:
# Handle any exceptions and log the error
QgsMessageLog.logMessage(
f"Error updating weighting: {e}", tag="Geest", level=Qgis.Warning
)
2 changes: 1 addition & 1 deletion geest/core/workflow_factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
AnalysisAggregationWorkflow,
MultiBufferDistancesWorkflow,
)
from geest.gui.treeview import JsonTreeItem
from .json_tree_item import JsonTreeItem


class WorkflowFactory:
Expand Down
4 changes: 2 additions & 2 deletions geest/core/workflow_job.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from qgis.core import QgsTask, QgsMessageLog, QgsFeedback, Qgis
from qgis.PyQt.QtCore import QObject, pyqtSignal
from geest.gui.treeview import JsonTreeItem
from qgis.PyQt.QtCore import pyqtSignal
from .json_tree_item import JsonTreeItem
from .workflow_factory import WorkflowFactory


Expand Down
2 changes: 1 addition & 1 deletion geest/core/workflow_queue_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from qgis.core import QgsMessageLog, Qgis, QgsTask
from .workflow_queue import WorkflowQueue
from .workflow_job import WorkflowJob
from geest.gui.treeview import JsonTreeItem
from .json_tree_item import JsonTreeItem


class WorkflowQueueManager(QObject):
Expand Down
2 changes: 1 addition & 1 deletion geest/core/workflows/aggregation_workflow_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
from .workflow_base import WorkflowBase
from geest.core.convert_to_8bit import RasterConverter
from geest.utilities import resources_path
from geest.gui.treeview import JsonTreeItem
from geest.core import JsonTreeItem


class AggregationWorkflowBase(WorkflowBase):
Expand Down
2 changes: 1 addition & 1 deletion geest/core/workflows/analysis_aggregation_workflow.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from qgis.analysis import QgsRasterCalculator, QgsRasterCalculatorEntry
from .aggregation_workflow_base import AggregationWorkflowBase
from geest.utilities import resources_path
from geest.gui.treeview import JsonTreeItem
from geest.core import JsonTreeItem


class AnalysisAggregationWorkflow(AggregationWorkflowBase):
Expand Down
4 changes: 1 addition & 3 deletions geest/core/workflows/default_index_score_workflow.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,13 @@
QgsVectorLayer,
QgsField,
QgsGeometry,
QgsRectangle,
QgsRasterLayer,
QgsProject,
QgsCoordinateReferenceSystem,
)
from qgis.PyQt.QtCore import QVariant
import processing # QGIS processing toolbox
from .workflow_base import WorkflowBase
from geest.gui.treeview import JsonTreeItem
from geest.core import JsonTreeItem
from geest.core.utilities import GridAligner


Expand Down
2 changes: 1 addition & 1 deletion geest/core/workflows/dimension_aggregation_workflow.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from qgis.analysis import QgsRasterCalculator, QgsRasterCalculatorEntry
from .aggregation_workflow_base import AggregationWorkflowBase
from geest.utilities import resources_path
from geest.gui.treeview import JsonTreeItem
from geest.core import JsonTreeItem


class DimensionAggregationWorkflow(AggregationWorkflowBase):
Expand Down
2 changes: 1 addition & 1 deletion geest/core/workflows/dont_use_workflow.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import time
from qgis.core import QgsMessageLog, Qgis, QgsFeedback
from .workflow_base import WorkflowBase
from geest.gui.treeview import JsonTreeItem
from geest.core import JsonTreeItem


class DontUseWorkflow(WorkflowBase):
Expand Down
2 changes: 1 addition & 1 deletion geest/core/workflows/factor_aggregation_workflow.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
)
from .aggregation_workflow_base import AggregationWorkflowBase
from geest.utilities import resources_path
from geest.gui.treeview import JsonTreeItem
from geest.core import JsonTreeItem


class FactorAggregationWorkflow(AggregationWorkflowBase):
Expand Down
2 changes: 1 addition & 1 deletion geest/core/workflows/multi_buffer_distances_workflow.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
from qgis.PyQt.QtCore import QVariant
import processing # QGIS processing toolbox
from .workflow_base import WorkflowBase
from geest.gui.treeview import JsonTreeItem
from geest.core import JsonTreeItem
from geest.core.multibuffer_point import MultiBufferCreator


Expand Down
2 changes: 1 addition & 1 deletion geest/core/workflows/raster_layer_workflow.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from qgis.core import QgsMessageLog, Qgis, QgsFeedback
from .workflow_base import WorkflowBase
from geest.gui.treeview import JsonTreeItem
from geest.core import JsonTreeItem


class RasterLayerWorkflow(WorkflowBase):
Expand Down
2 changes: 1 addition & 1 deletion geest/core/workflows/workflow_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from abc import ABC, abstractmethod
from qgis.core import QgsFeedback, QgsVectorLayer, QgsMessageLog, Qgis
from qgis.PyQt.QtCore import QSettings
from geest.gui.treeview import JsonTreeItem
from geest.core import JsonTreeItem


class WorkflowBase(ABC):
Expand Down
7 changes: 3 additions & 4 deletions geest/gui/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

from .geest_settings import GeestOptionsFactory
from .geest_dock import GeestDock
from .treeview import JsonTreeItem, JsonTreeModel, CustomTreeView
from .setup_panel import SetupPanel
from .tree_panel import TreePanel
from .indicator_detail_dialog import IndicatorDetailDialog
from .indicator_config_widget import IndicatorConfigWidget
from .toggle_switch import ToggleSwitch
from .indicator_widget_factory import RadioButtonFactory
2 changes: 2 additions & 0 deletions geest/gui/dialogs/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
from .factor_aggregation_dialog import FactorAggregationDialog
from .indicator_detail_dialog import IndicatorDetailDialog
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@
from qgis.PyQt.QtGui import QPixmap
from qgis.PyQt.QtCore import Qt, pyqtSignal
from qgis.core import QgsMessageLog, Qgis
from .toggle_switch import ToggleSwitch
from ..toggle_switch import ToggleSwitch
from geest.utilities import resources_path
from .indicator_config_widget import IndicatorConfigWidget
from ..indicator_config_widget import IndicatorConfigWidget


class IndicatorDetailDialog(QDialog):
Expand Down
Loading

0 comments on commit d4fb55f

Please sign in to comment.