Skip to content

Commit

Permalink
Merge pull request #514 from kartoza/timlinux/issue490
Browse files Browse the repository at this point in the history
Fix for issue Safety widget - extra unrelated widgets are being added #490
  • Loading branch information
timlinux authored Oct 30, 2024
2 parents e35f49f + 99d0ce6 commit 9a38a38
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 52 deletions.
3 changes: 3 additions & 0 deletions geest/core/json_tree_item.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,9 @@ def row(self):
return self.parentItem.childItems.index(self)
return 0

def name(self):
return self.data(0)

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

Expand Down
59 changes: 33 additions & 26 deletions geest/gui/dialogs/indicator_detail_dialog.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,26 @@ class IndicatorDetailDialog(QDialog):
"""Dialog to show layer properties, with a Markdown editor and preview for the 'indicator' field."""

# Signal to emit the updated data as a dictionary
dataUpdated = pyqtSignal(dict)
dataUpdated = pyqtSignal()

def __init__(self, layer_name, layer_data, tree_item, editing=False, parent=None):
def __init__(self, item, editing=False, parent=None):
"""
Initializes the dialog with the given item and optional editing mode.
:param item: The QTreeView item to show the properties for.
:param editing: Whether the dialog is in editing mode (default: False).
:param parent: The parent widget (default: None).
Note: The item is a reference to the QTreeView item, so any changes will update the tree.
"""
super().__init__(parent)

self.setWindowTitle(layer_name)
self.layer_data = layer_data
self.tree_item = tree_item # Reference to the QTreeView item to update
self.setWindowTitle(item.name())
# Note this is a reference to the tree item
# any changes you make will update the tree
self.item = item # Reference to the QTreeView item to update
self.attributes = self.item.data(3) # Reference to the attributes dictionary
self.editing = editing
self.config_widget = None # To hold the configuration from widget factory
self.radio_buttons = [] # To keep track of the radio buttons for later
Expand All @@ -57,7 +69,7 @@ def __init__(self, layer_name, layer_data, tree_item, editing=False, parent=None

# Left-hand tab for Markdown editor and preview
self.markdown_tab = QWidget()
self.setup_markdown_tab(layer_name)
self.setup_markdown_tab()

# Right-hand tab for editing properties (table)
self.edit_tab = QWidget()
Expand All @@ -84,7 +96,7 @@ def __init__(self, layer_name, layer_data, tree_item, editing=False, parent=None
# Initial call to update the preview with existing content
self.update_preview()

def setup_markdown_tab(self, layer_name):
def setup_markdown_tab(self):
"""Sets up the left-hand tab for the Markdown editor and preview."""
markdown_layout = QVBoxLayout(self.markdown_tab)

Expand All @@ -96,10 +108,8 @@ def setup_markdown_tab(self, layer_name):
markdown_layout.addWidget(self.title_label)

# Get the grandparent and parent items
grandparent_item = (
self.tree_item.parent().parent() if self.tree_item.parent() else None
)
parent_item = self.tree_item.parent()
grandparent_item = self.item.parent().parent() if self.item.parent() else None
parent_item = self.item.parent()

# If both grandparent and parent exist, create the label
if grandparent_item and parent_item:
Expand All @@ -114,7 +124,7 @@ def setup_markdown_tab(self, layer_name):
) # Add the label above the heading

# Heading for the dialog
heading_label = QLabel(layer_name)
heading_label = QLabel(self.item.name())
heading_label.setStyleSheet(
"font-size: 18px; font-weight: bold;"
) # Bold heading
Expand All @@ -138,7 +148,7 @@ def setup_markdown_tab(self, layer_name):

# Create the QTextEdit for Markdown editing (left side)
self.text_edit_left = QTextEdit()
self.text_edit_left.setPlainText(self.layer_data.get("description", ""))
self.text_edit_left.setPlainText(self.attributes.get("description", ""))
self.text_edit_left.setMinimumHeight(100) # Set at least 5 lines high
if self.editing:
splitter.addWidget(self.text_edit_left)
Expand Down Expand Up @@ -190,7 +200,7 @@ def setup_edit_tab(self):

def populate_table(self):
"""Populate the table with all key-value pairs except 'indicator'."""
filtered_data = {k: v for k, v in self.layer_data.items() if k != "indicator"}
filtered_data = {k: v for k, v in self.attributes.items() if k != "indicator"}
self.table.setRowCount(len(filtered_data))

for row, (key, value) in enumerate(filtered_data.items()):
Expand All @@ -215,7 +225,7 @@ def get_widget_for_value(self, key, value):
"""
Returns an appropriate widget for the table based on the data type or key.
"""
if "Use" in key or "Rasterise" in key:
if "use" in key or "rasterise" in key:
toggle_widget = ToggleSwitch(initial_value=bool(value))
return toggle_widget
elif isinstance(value, bool):
Expand Down Expand Up @@ -244,7 +254,7 @@ def get_widget_for_value(self, key, value):
def add_config_widgets(self, layout):
if not self.editing:

self.config_widget = IndicatorConfigWidget(self.layer_data)
self.config_widget = IndicatorConfigWidget(self.attributes)
if self.config_widget:
layout.addWidget(self.config_widget)
# connect to the stateChanged signal
Expand All @@ -258,7 +268,7 @@ def add_config_widgets(self, layout):

def handle_config_change(self, new_config):
"""Optionally handle configuration changes."""
self.layer_data = new_config
self.attributes = new_config
QgsMessageLog.logMessage(
f"LayerDetailDialog config set to: {new_config}",
tag="Geest",
Expand All @@ -270,22 +280,19 @@ def accept_changes(self):
if self.editing:
# In editing mode, the edit table is canonical
updated_data = self.get_updated_data_from_table()
# Update the layer data with the new data
# This directly updates the tree item
self.attributes = updated_data
else:
# Otherwise, the custom widget is canonical
updated_data = self.config_widget.attributes_dict

# Set 'Analysis Mode' based on the selected radio button
# Taken from IndicatorConfigWidget now
# selected_button = self.button_group.checkedButton()
# if selected_button:
# updated_data["analysis_mode"] = selected_button.text()
pass

self.dataUpdated.emit(updated_data) # Emit the updated data as a dictionary
self.dataUpdated.emit() # Emit the updated data as a dictionary
self.accept() # Close the dialog

def get_updated_data_from_table(self):
"""Convert the table back into a dictionary with any changes made, including the Markdown text."""
updated_data = self.layer_data
updated_data = self.attributes

# Loop through the table and collect other data
for row in range(self.table.rowCount()):
Expand Down
28 changes: 17 additions & 11 deletions geest/gui/indicator_config_widget.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,31 +9,37 @@ class IndicatorConfigWidget(QWidget):
Widget for configuring indicators based on a dictionary.
"""

data_changed = pyqtSignal(dict)
data_changed = pyqtSignal()

def __init__(self, attributes_dict: dict) -> None:
def __init__(self, attributes: dict) -> None:
super().__init__()
self.attributes_dict = attributes_dict
# This is a reference to the attributes dictionary
# So any changes made will propogate to the JSONTreeItem
self.attributes = attributes
self.layout: QVBoxLayout = QVBoxLayout()
self.button_group: QButtonGroup = QButtonGroup(self)

try:
self.create_radio_buttons(attributes_dict)
self.create_radio_buttons(attributes)
except Exception as e:
QgsMessageLog.logMessage(
f"Error in create_radio_buttons: {e}", tag="Geest", level=Qgis.Critical
)

self.setLayout(self.layout)

def create_radio_buttons(self, attributes_dict: dict) -> None:
def create_radio_buttons(self, attributes: dict) -> None:
"""
Uses the factory to create radio buttons from attributes dictionary.
"""
analysis_mode = attributes_dict.get("analysis_mode", "")
for key, value in attributes_dict.items():
# make a deep copy of the dictionary in case it changes while we
# are using it
attributes = attributes.copy()
analysis_mode = attributes.get("analysis_mode", "")

for key, value in attributes.items():
radio_button_widget = RadioButtonFactory.create_radio_button(
key, value, attributes_dict
key, value, attributes
)
if radio_button_widget:
if key == analysis_mode:
Expand All @@ -60,10 +66,10 @@ def update_attributes(self, new_data: dict) -> None:
self.button_group.checkedButton().label_text.lower().replace(" ", "_")
)
new_data["analysis_mode"] = snake_case_mode
self.attributes_dict.update(new_data)
self.data_changed.emit(self.attributes_dict)
self.attributes.update(new_data)
self.data_changed.emit()
QgsMessageLog.logMessage(
f"Updated attributes dictionary: {self.attributes_dict}",
f"Updated attributes dictionary: {self.attributes}",
"Geest",
level=Qgis.Info,
)
17 changes: 2 additions & 15 deletions geest/gui/panels/tree_panel.py
Original file line number Diff line number Diff line change
Expand Up @@ -680,24 +680,11 @@ def edit_factor_aggregation(self, factor_item):
def show_layer_properties(self, item):
"""Open a dialog showing layer properties and update the tree upon changes."""
editing = self.edit_mode and self.edit_toggle.isChecked()
# Get the current layer name and layer data from the item
layer_name = item.data(0) # Column 0: layer name
layer_data = item.data(3) # Column 3: layer data (stored as a dict)

# Create and show the LayerDetailDialog
dialog = IndicatorDetailDialog(
layer_name, layer_data, item, editing=editing, parent=self
)
dialog = IndicatorDetailDialog(item, editing=editing, parent=self)

# Connect the dialog's dataUpdated signal to handle data updates
def update_layer_data(updated_data):
# Update the layer data in the item (column 4)
item.setData(3, updated_data)

# Check if the layer name has changed, and if so, update it in column 0
if updated_data.get("name", layer_name) != layer_name:
item.setData(0, updated_data.get("name", layer_name))

def update_layer_data():
# Save the JSON data to the working directory
self.save_json_to_working_directory()

Expand Down

0 comments on commit 9a38a38

Please sign in to comment.