summaryrefslogtreecommitdiff
path: root/ui/windows
diff options
context:
space:
mode:
authorChristian Kolset <christian.kolset@gmail.com>2026-06-09 22:27:44 -0600
committerChristian Kolset <christian.kolset@gmail.com>2026-06-09 22:27:44 -0600
commitf8b5e47ffe9a52bd28ad5d953a551ccb92cbbb09 (patch)
treef22a6743ea7b9ac2a4c476bd85abd462ea445f78 /ui/windows
parent4d62e4c03227500984a2770ef9615c603a5b71aa (diff)
Channels: inject variable names as comment in code editor, fix derivative wrt
- Variable names now appear as a live '# Variables: A0 = x[0] · ...' comment at the top of the code editor (function, custom_script, and built-in read-only templates); updates on every source add/remove/change - Derivative 'With Respect To' channel combo now included in variable list as x[1] when channel mode is selected - _apply() strips the auto-generated comment before saving the script so it doesn't pollute the stored expression Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Diffstat (limited to 'ui/windows')
-rw-r--r--ui/windows/channels_window.py64
1 files changed, 59 insertions, 5 deletions
diff --git a/ui/windows/channels_window.py b/ui/windows/channels_window.py
index 3730b12..266432b 100644
--- a/ui/windows/channels_window.py
+++ b/ui/windows/channels_window.py
@@ -723,6 +723,7 @@ class DerivedBlock(QFrame):
_cur_wrt = self.dc.params.get("deriv_wrt", "time")
self._wrt_cb.setCurrentIndex(1 if _cur_wrt == "channel" else 0)
self._wrt_cb.currentIndexChanged.connect(self._on_wrt_changed)
+ self._wrt_cb.currentIndexChanged.connect(lambda _: self._update_vars_hint())
wrt_top.addWidget(self._wrt_cb); wrt_top.addStretch()
wrt_lay.addLayout(wrt_top)
self._wrt_x_row = QWidget()
@@ -736,6 +737,7 @@ class DerivedBlock(QFrame):
for i in range(self._wrt_x_cb.count()):
if self._wrt_x_cb.itemData(i) == x_src:
self._wrt_x_cb.setCurrentIndex(i); break
+ self._wrt_x_cb.currentIndexChanged.connect(lambda _: self._update_vars_hint())
wx_lay.addWidget(self._wrt_x_cb, 1)
wrt_lay.addWidget(self._wrt_x_row)
bl.addWidget(self._wrt_grp)
@@ -814,17 +816,63 @@ class DerivedBlock(QFrame):
self._update_vars_hint()
def _update_vars_hint(self):
- """Refresh the variable-name hint above the code editor."""
+ """Refresh the variable-name hint and code comment whenever sources change."""
if not hasattr(self, "_vars_lbl"):
return
from core.signal_processor import _make_src_names
+ from ui.code_templates import BUILTIN_TEMPLATES
+
+ # Build source list — for derivatives in channel mode, include wrt channel
sources = [cb.currentData() for cb in self._src_combos if cb.currentData()]
+ is_deriv = self.dc.kind in ("derivative", "second_derivative")
+ if (is_deriv and hasattr(self, "_wrt_cb")
+ and self._wrt_cb.currentIndex() == 1
+ and hasattr(self, "_wrt_x_cb")):
+ wrt_src = self._wrt_x_cb.currentData()
+ if wrt_src and wrt_src not in sources:
+ sources.append(wrt_src)
+
if not sources:
self._vars_lbl.setText("No sources — add sources above to use named variables")
+ self._inject_code_comment("")
return
+
names = _make_src_names(sources)
parts = [f"{name} = x[{i}]" for i, name in enumerate(names)]
- self._vars_lbl.setText("Variables: " + " · ".join(parts))
+ comment = "# Variables: " + " · ".join(parts)
+ self._vars_lbl.setText(comment)
+ self._inject_code_comment(comment)
+
+ def _inject_code_comment(self, comment: str):
+ """Insert or update a '# Variables:' first line in the code editor."""
+ if not hasattr(self, "_code"):
+ return
+ from ui.code_templates import BUILTIN_TEMPLATES
+
+ if self.dc.kind in _BUILTIN:
+ # Read-only template — prepend comment to base template each time
+ template = BUILTIN_TEMPLATES.get(self.dc.kind, "")
+ new_text = (comment + "\n" + template) if comment else template
+ if self._code.toPlainText() != new_text:
+ self._code.setPlainText(new_text)
+
+ elif self.dc.kind in ("function", "custom_script"):
+ current = self._code.toPlainText()
+ lines = current.splitlines()
+ if lines and lines[0].startswith("# Variables:"):
+ # Replace existing auto-comment
+ rest = "\n".join(lines[1:]).lstrip("\n")
+ new_text = (comment + "\n" + rest) if comment else rest
+ else:
+ new_text = (comment + "\n" + current) if comment else current
+ if self._code.toPlainText() != new_text:
+ # Preserve cursor position
+ cursor = self._code.textCursor()
+ pos = cursor.position() + len(comment) + 1
+ self._code.setPlainText(new_text)
+ cursor.setPosition(min(pos, len(new_text)))
+ self._code.setTextCursor(cursor)
+ # expression kind: label-only, no code injection (single-line expr)
def _on_kind(self, idx: int):
from ui.code_templates import BUILTIN_TEMPLATES
@@ -834,9 +882,9 @@ class DerivedBlock(QFrame):
if k in ("derivative", "second_derivative") and not self._src_combos:
self._add_src()
if k in _BUILTIN:
- # Show the template as a read-only preview
+ # Reset to bare template first; _update_vars_hint will prepend comment
self._code.setPlainText(BUILTIN_TEMPLATES.get(k, ""))
- self._update_vars_hint()
+ self._update_vars_hint() # also injects variable comment into code
self._update_visibility()
def _on_wrt_changed(self, idx: int):
@@ -855,6 +903,7 @@ class DerivedBlock(QFrame):
self._help.setText(_KIND_HELP.get("custom_script", ""))
self.dc.script = template
self._code.setPlainText(template)
+ self._update_vars_hint() # prepend variable comment to template
self._update_visibility()
def _update_visibility(self):
@@ -884,7 +933,12 @@ class DerivedBlock(QFrame):
if self.dc.kind == "expression":
self.dc.expression = self._code.toPlainText().strip()
elif self.dc.kind in ("function", "custom_script"):
- self.dc.script = self._code.toPlainText()
+ # Strip auto-generated Variables comment before saving
+ raw = self._code.toPlainText()
+ lines = raw.splitlines()
+ if lines and lines[0].startswith("# Variables:"):
+ raw = "\n".join(lines[1:]).lstrip("\n")
+ self.dc.script = raw
err = self.processor.add_derived(self.dc)
if err:
self._st.setText(f"⚠ {err[:100]}")