Skip to content

Commit

Permalink
Editing workflow with custom widgets working
Browse files Browse the repository at this point in the history
  • Loading branch information
timlinux committed Sep 14, 2024
1 parent c5c22a8 commit 57786b6
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 49 deletions.
24 changes: 21 additions & 3 deletions geest/gui/geest_dock.py
Original file line number Diff line number Diff line change
Expand Up @@ -188,12 +188,30 @@ def open_context_menu(self, position: QPoint):
menu.exec_(self.treeView.viewport().mapToGlobal(position))

def show_layer_properties(self, item):
"""Open a dialog showing layer properties."""
layer_name = item.data(0)
layer_data = item.data(4) # The 4th column stores the whole layer data dict
"""Open a dialog showing layer properties and update the tree upon changes."""
# Get the current layer name and layer data from the item
layer_name = item.data(0) # Column 0: layer name
layer_data = item.data(4) # Column 4: layer data (stored as a dict)

# Create and show the LayerDetailDialog
dialog = LayerDetailDialog(layer_name, layer_data, 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(4, 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))

# Connect the signal emitted from the dialog to update the item
dialog.dataUpdated.connect(update_layer_data)

# Show the dialog (exec_ will block until the dialog is closed)
dialog.exec_()


def process_leaves(self):
"""
This function processes all the leaf nodes in the QTreeView.
Expand Down
81 changes: 38 additions & 43 deletions geest/gui/layer_details_dialog.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import re
from qgis.PyQt.QtWidgets import (
QDialog,
QVBoxLayout,
Expand All @@ -13,12 +14,15 @@
QComboBox,
QHBoxLayout,
QTextEdit,
QWidget,
QSplitter,
)
from qgis.PyQt.QtCore import Qt, pyqtSignal
from .toggle_switch import ToggleSwitch


class LayerDetailDialog(QDialog):
"""Dialog to show layer properties, with a Markdown editor for the 'indicator' field."""
"""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)
Expand All @@ -36,26 +40,24 @@ def __init__(self, layer_name, layer_data, tree_item, parent=None):
heading_label = QLabel(layer_name)
layout.addWidget(heading_label)

# Create the QTextEdit for Markdown editing
self.text_edit = QTextEdit()
self.text_edit.setPlainText(layer_data.get("indicator", ""))
self.text_edit.setMinimumHeight(100) # Set at least 5 lines high
layout.addWidget(self.text_edit)
# Create a horizontal splitter to hold both the Markdown editor and the preview
splitter = QSplitter(Qt.Horizontal)

# Create a layout for the toggle and label at the bottom-right of the text edit
toggle_layout = QHBoxLayout()
toggle_layout.addStretch() # Push to the right
# Create the QTextEdit for Markdown editing (left side)
self.text_edit_left = QTextEdit()
self.text_edit_left.setPlainText(layer_data.get("indicator", ""))
self.text_edit_left.setMinimumHeight(100) # Set at least 5 lines high
splitter.addWidget(self.text_edit_left)

# Add the toggle switch and "Edit" label
self.edit_mode_toggle = ToggleSwitch(initial_value=True)
self.edit_mode_toggle.toggled.connect(self.toggle_edit_mode)
toggle_layout.addWidget(QLabel("Edit"))
toggle_layout.addWidget(self.edit_mode_toggle)
# Create the QTextEdit for HTML preview (right side)
self.text_edit_right = QTextEdit()
self.text_edit_right.setReadOnly(True) # Set as read-only for preview
splitter.addWidget(self.text_edit_right)

layout.addLayout(toggle_layout)
layout.addWidget(splitter)

# Set the initial mode to edit mode
self.is_edit_mode = True
# Connect the Markdown editor (left) to update the preview (right) in real-time
self.text_edit_left.textChanged.connect(self.update_preview)

# Create the QTableWidget for other properties
self.table = QTableWidget()
Expand All @@ -80,6 +82,9 @@ def __init__(self, layer_name, layer_data, tree_item, parent=None):

self.setLayout(layout)

# Initial call to update the preview with existing content
self.update_preview()

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"}
Expand All @@ -95,23 +100,14 @@ def populate_table(self):
value_widget = self.get_widget_for_value(key, value)
self.table.setCellWidget(row, 1, value_widget)

def toggle_edit_mode(self, checked):
"""Switch between edit mode (plain text) and display mode (render as HTML)."""
if checked:
# In Edit Mode: Show plain text to allow Markdown writing
self.is_edit_mode = True
self.text_edit.setReadOnly(False)
self.text_edit.setPlainText(self.text_edit.toPlainText()) # Reset to plain text
else:
# In Display Mode: Render Markdown as HTML
self.is_edit_mode = False
self.text_edit.setReadOnly(True)
markdown_text = self.text_edit.toPlainText()

# Render basic Markdown elements as HTML
rendered_html = markdown_text.replace("# ", "<h1>").replace("\n", "<br>")
rendered_html = rendered_html.replace("**", "<b>").replace("_", "<i>")
self.text_edit.setHtml(rendered_html) # Render as HTML

def update_preview(self):
"""Update the right text edit to show a live HTML preview of the Markdown, ensuring headings are terminated at the first line feed."""
markdown_text = self.text_edit_left.toPlainText()
# Set the rendered HTML into the right text edit
self.text_edit_right.setMarkdown(markdown_text)


def get_widget_for_value(self, key, value):
"""
Expand Down Expand Up @@ -147,19 +143,16 @@ def on_close(self):
"""Handle the dialog close event by writing the edited data back to the TreeView item."""
updated_data = self.get_updated_data_from_table()
self.dataUpdated.emit(updated_data) # Emit the updated data as a dictionary

# Write the Markdown or plain text back to the TreeView column 4
if self.is_edit_mode:
updated_text = self.text_edit.toPlainText()
else:
updated_text = self.text_edit.toHtml()
self.tree_item.setText(4, updated_text) # Update the TreeView item's 4th column

self.close()

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

# Include the Markdown text from the left text edit
updated_data["indicator"] = self.text_edit_left.toPlainText()

# Loop through the table and collect other data
for row in range(self.table.rowCount()):
key = self.table.item(row, 0).text() # Get the key (read-only)
value_widget = self.table.cellWidget(row, 1) # Get the widget from the second column
Expand All @@ -175,5 +168,7 @@ def get_updated_data_from_table(self):
else:
updated_value = value_widget.text() # Default to text value

updated_data[key] = updated_value # Update the dictionary
updated_data[key] = updated_value # Update the dictionary with the key-value pair

return updated_data

6 changes: 3 additions & 3 deletions geest/gui/toggle_switch.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ class ToggleSwitch(QWidget):

def __init__(self, initial_value=False, parent=None):
super().__init__(parent)
self.setFixedSize(QSize(60, 30)) # Size of the toggle switch
self.setFixedSize(QSize(40, 20)) # Size of the toggle switch
self.checked = initial_value

def paintEvent(self, event):
Expand All @@ -20,7 +20,7 @@ def paintEvent(self, event):

# Background color based on state
if self.checked:
painter.setBrush(QColor("#0082C8")) # Active state color (blue)
painter.setBrush(QColor("#002244")) # Active state color (blue) from WB Style Guide
else:
painter.setBrush(QColor("#ADB5BD")) # Inactive state color (gray)

Expand All @@ -31,7 +31,7 @@ def paintEvent(self, event):
# Draw the circle (slider knob)
knob_radius = rect.height() - 6
knob_x = rect.x() + 3 if not self.checked else rect.right() - knob_radius - 3
painter.setBrush(QColor("#FFFFFF")) # White color for the knob
painter.setBrush(QColor("#009CA7")) # From WB Style Guide
painter.drawEllipse(knob_x, rect.y() + 3, knob_radius, knob_radius)

def mousePressEvent(self, event):
Expand Down

0 comments on commit 57786b6

Please sign in to comment.