Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 17 additions & 4 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -122,9 +122,16 @@ QTorres/

**Fase 3 — Sub-VIs y extensibilidad (en curso):**
- ~~#17 Sub-VI con connector pane~~ ✅ (pin-based connector, compile-subvi-call, runner carga contextos, btn-run sincronizado)
- #18 Librería .qlib
- ~~#18 Librería .qlib~~ ✅ (load-qlib, find-qlibs, paleta integrada, ejemplo math.qlib, 482 tests PASS)
- ~~#64 FP como ventana maestra~~ ✅ (FP=blocking master, BD=no-wait slave, Ctrl+E toggle, títulos sincronizados, current-file en app-model)
- ~~#65 Scroll en BD y FP~~ ✅ (ventanas fijas 900x600, scroll wheel + click scrollbar, límites por contenido real)

**Próximo paso:** #18 Librería .qlib
**Fase 5 — UX y gestión de proyectos (planificado):**
- Splash / Welcome screen (Create New VI, Open Existing, proyectos recientes)
- Project Explorer con formato .qproj (árbol de ficheros, gestión de dependencias)
- Depende de: .qlib (#18) ✅ y FP como ventana maestra (#64) ✅

**Próximo paso:** Fase 4 (hardware) o Fase 5 (UX)

## Decisiones técnicas clave

Expand Down Expand Up @@ -275,8 +282,10 @@ Estrategia QA: tests con cada feature nueva, no sesión QA dedicada.
Spec visual: cada tipo implementa su aspecto según `docs/visual-spec.md`.

**Fase 3 — Sub-VIs y extensibilidad:**
- #17 Sub-VI con connector pane
- #18 Librería .qlib
- #17 Sub-VI con connector pane ✅
- #18 Librería .qlib ✅
- #64 FP como ventana maestra — BD bajo demanda (Ctrl+E) ✅
- ~~#65 Scroll en BD y FP~~ ✅ (ventanas fijas 900x600, scrollbars draw-based, límites por contenido)

**Fase 4 — Hardware:**
- #19 SCPI sobre TCP/IP (Keysight por red)
Expand All @@ -285,6 +294,10 @@ Spec visual: cada tipo implementa su aspecto según `docs/visual-spec.md`.
- #22 TCP/IP genérico (Modbus TCP, protocolos propios)
- #23 DAQ analógico (comedi/libcomedi)

**Fase 5 — UX y gestión de proyectos:**
- Splash / Welcome screen (Create New VI, Open Existing, proyectos recientes)
- Project Explorer con formato .qproj (árbol de proyecto, gestión de dependencias)

## Ollama MCP — Delegación de tareas a modelo local

QTorres tiene un MCP server que conecta con Ollama (modelo local). Ollama tiene cargado automáticamente CLAUDE.md y el skill de Red-Lang como contexto del proyecto.
Expand Down
94 changes: 94 additions & 0 deletions docs/GTK_ISSUES.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,9 @@ Cuando Red migre a 64-bit, este problema desaparece. QTorres debe seguir ese roa
| GTK-008 `request-file/save` abre diálogo de carpetas | — | Workaround: diálogo VID propio |
| GTK-009 `request-file` no permite controlar tamaño | — | Posible: file browser VID propio |
| GTK-010 `on-change` de field queda enganchado tras Run | — | Issue anlaco/QTorres#49 |
| GTK-014 `face/size` flip-flop CSD↔cliente tras alt+tab | — | Workaround: ventanas fijas 900x600 sin resize (Issue #65) |
| GTK-015 Tab crashea navegación foco en window con solo `base` | — | Pendiente de crear — no fatal |
| GTK-016 Access violation en show/draw bajo maximize/resize | — | Crítico — sin workaround user-land |

---

Expand All @@ -115,6 +118,97 @@ La causa probable es que Red/View no llama a `gtk_window_set_transient_for()` o

---

### GTK-014: `face/size` reporta dos interpretaciones distintas según el estado de foco — flip-flop tras alt+tab / maximize / restore

**Severidad:** Alta
**Impacto en QTorres:** El canvas del BD y del FP se dimensionaban mal tras alt+tab o restore de maximize, saliéndose por la derecha y/o abajo de la ventana, o quedándose demasiado pequeño con huecos visibles.

**Descripción:**
En GTK3 con CSD (Client-Side Decorations), `face/size` de una ventana reporta **dos valores distintos para el mismo estado visual**, y cambia entre ellos tras eventos de foco sin intervención del usuario:

- **Modo CSD** (inicial y tras restore): `face/size = área cliente + header bar + sombras`
- **Modo cliente** (tras primer alt+tab o focus cycle): `face/size = área cliente + header bar` (sin sombras)

El valor en modo cliente es `~98x98 px menor` que en modo CSD para la misma ventana visual. No hay API en Red/View para saber en qué modo está GTK.

**Ejemplo capturado** (pantalla 1366x768, ventana maximizada):

```
#21 on-resize 1464x836 ← maximizar, modo CSD (shadows incluidas)
#22 on-time 1464x836
#23 on-unfocus 1366x738 ← alt+tab, GTK cambia a modo cliente (-98x-98)
#28 on-resize 663x486 ← restore, modo cliente (747-98, 584-98)
#30 on-resize 747x584 ← mismo estado, GTK vuelve a modo CSD (+98x+98)
```

**Workaround implementado (Issue #65):** Ventanas de tamaño fijo (900x600) sin `flags: [resize]`. Al no haber redimensionado, el flip CSD↔cliente no afecta al layout — los canvas tienen tamaño fijo calculado contra el spec de la ventana, no contra `face/size`.

La detección bidireccional del flip fue explorada y descartada: los deltas -98x-98 durante maximize son indistinguibles de un flip legítimo por alt+tab, y la lógica de corrección se volvía inestable. Ver `tests/test-overhead.red` para el diagnóstico completo.

**Test reproducible:** `tests/test-overhead.red` — con logging a `/tmp/test-overhead.log` para capturar la secuencia de eventos.

---

### GTK-015: Pulsar `Tab` en ventana con solo `base` face crashea en navegación de foco

**Severidad:** Media (no fatal)
**Impacto en QTorres:** Si el usuario pulsa Tab con foco en el canvas del BD o FP, aparece un error en stderr. La aplicación **no muere** — el event loop continúa funcionando normalmente.

**Descripción:**
Al pulsar Tab en una ventana cuyo `pane` solo contiene faces de tipo `base` (no focusables), el handler interno de navegación de foco de Red/View intenta recorrer `p/parent/pane` y falla porque `parent` es `none`:

```
*** Script Error: path p/parent/pane is not valid for none! type
*** Where: eval-path
*** Near : handler face event
*** Stack: view do-events do-safe
```

**Hallazgos del diagnóstico:**

1. **`on-key` recibe el Tab** (`event/key = #"^-"`) — el evento llega al user-land antes del crash.
2. **`return 'done` desde `on-key` NO previene** el handler interno — Red/View lo ejecuta igualmente.
3. **Añadir un `field` al pane como "tab-sink"** no evita el crash. Si es `visible?: false` GTK emite `gtk_widget_event: WIDGET_REALIZED_FOR_EVENT failed` porque el widget no está realizado. Si es visible pero off-screen, el crash sigue produciéndose en un handler distinto.
4. **`set-focus tab-sink` en `on-create`** falla porque los widgets hijos aún no están realizados en ese momento.
5. **El crash es no-fatal** — el event loop sigue vivo y los siguientes eventos de teclado se procesan normalmente.

**Workaround temporal:** Ninguno limpio desde user-land. Se acepta como limitación conocida de Red/View GTK. El BD/FP de QTorres no usa Tab como interacción normal.

**Test reproducible:** `tests/test-overhead.red` — pulsar Tab muestra el error repetidamente en stderr pero la aplicación sigue funcionando.

---

### GTK-016: Access violation en `show`/`draw` bajo maximize/resize repetidos

**Severidad:** Crítica
**Impacto en QTorres:** Bajo presión de eventos de resize (maximize/restore rápido, o drag agresivo del borde) el runtime de Red/View genera un `*** Runtime Error 1: access violation` nativo en una dirección dentro del runtime (ej. `at: 0809DC91h`). En un caso observado el crash arrastró al sistema entero hasta colgarlo.

**Descripción:**
El crash ocurre esporádicamente al combinar:
- Modificaciones de `face/size` desde un handler (`on-time`)
- Llamadas a `show` sobre el face hijo (base con Draw)
- Eventos GTK concurrentes de maximize/restore/focus

La pila de ejecución nunca llega al user-land — es un `access violation` en memoria nativa, probablemente en el path de actualización del widget GTK desde el binding de Red. No hay forma de capturarlo con `try`/`catch`: es segfault puro.

**Hallazgos del diagnóstico:**

1. **Intermitente** — no se reproduce de forma determinista. Requiere varios ciclos de maximize/restore seguidos.
2. **No depende de la lógica user-land** — se reproduce con el test simplificado `test-overhead.red` que no hace flip detection ni manipula estado.
3. **Peligroso** — en un caso concreto arrastró al sistema entero (no solo a la app) y obligó a reiniciar el equipo.
4. **No hay workaround** — cualquier estrategia que implique `show` tras cambiar `face/size` es vulnerable.

**Workaround temporal:** Ninguno conocido desde user-land. Posibles mitigaciones a investigar:
- Diferir `show` con un timer adicional tras el resize
- Usar `show/with` o `show face/pane` en lugar de `show child`
- Evitar modificar `face/size` dentro del handler y hacerlo en un tick posterior

**Siguiente paso:** Caso mínimo reproducible para bug report upstream a Red-Lang. Mientras tanto, QTorres debe asumir que el resize agresivo puede matar la app.

**Test reproducible:** `tests/test-overhead.red` — maximize/restore repetido acaba disparando el crash en una fracción de los intentos.

---

### GTK-010: `on-change` de field nativo queda enganchado tras ejecutar Run

**Severidad:** Media
Expand Down
45 changes: 45 additions & 0 deletions docs/decisiones.md
Original file line number Diff line number Diff line change
Expand Up @@ -1072,3 +1072,48 @@ _err: scpi-read instrument _err
| Error cluster desde Fase 2 | Complejidad prematura. Sin hardware, no hay errores reales que propagar |
| Solo `try/catch` global | No permite al usuario ver qué nodo falló ni tomar decisiones en el diagrama |
| Ignorar errores (solo `print`) | Inaceptable para producción industrial |

---

## DT-030: UI Framework — Red/View + Draw con capa QT-Widgets propia

**Fecha:** 2026-04-10
**Estado:** Adoptada

**Contexto:** QTorres necesita un editor visual con nodos arrastrables, wires, scrollbars, controles custom, inline text editing, tree views (project explorer) y más. Red/View proporciona ventanas y eventos, Draw proporciona renderizado 2D, pero no hay widget toolkit intermedio. Se evaluó si construir sobre Red/View+Draw, GTK directo, o Qt.

**Alternativas evaluadas:**

| Opción | Ventajas | Inconvenientes |
|--------|----------|----------------|
| **Red/View + Draw** (actual) | Todo en Red (DT-001), binario < 1 MB, multiplataforma, control total | Cada widget hay que construirlo desde cero, bugs GTK, no hay accessibility |
| **GTK (via FFI/C)** | Widgets nativos maduros, TreeView, ScrolledWindow, accessibility | Rompe DT-001, solo nativo en Linux, runtime pesado en Win/macOS, el canvas custom sigue siendo necesario |
| **Qt (C++/Python)** | QGraphicsScene resuelve el canvas, toolkit más completo que existe, multiplataforma real | Rompe DT-001 completamente, 50-100 MB de runtime, Red relegado a lenguaje del .qvi, no del editor |

**Decisión:** Construir sobre Red/View + Draw, formalizando progresivamente una capa intermedia (QT-Widgets).

**Arquitectura objetivo:**

```
Red/View (ventanas + event loop)
└── Draw (renderizado 2D)
└── QT-Widgets (capa propia: hit-test, scroll, controles Draw-based)
└── QTorres UI (canvas, panel, diálogos, project explorer)
```

**Razones:**

1. **El canvas del diagrama es custom sí o sí.** Incluso con Qt/QGraphicsScene, los nodos QTorres, los wires con tipado por color, las estructuras de control y el connector pane necesitan renderizado propio. El 80% de la complejidad no se ahorra con un toolkit externo.

2. **Identidad del proyecto.** "Todo en Red, un binario < 1 MB, sin dependencias" es la propuesta de valor que diferencia a QTorres de LabVIEW. Meter Qt o GTK la destruye.

3. **Ya estamos construyendo el framework.** canvas-render.red (932 líneas), panel-render.red (411 líneas), el hit-testing en canvas.red — eso ya ES un framework UI custom, solo falta formalizarlo.

4. **Los widgets necesarios son pocos.** Scrollbar, text input inline, tree view, tabs. No necesitamos un toolkit genérico de 200 widgets.

**Plan de formalización:**

- **Fases 3-4:** Seguir construyendo widgets ad-hoc (scroll, resize) dentro de los módulos existentes. No extraer todavía.
- **Fase 5+:** Cuando lleguen inline text editing, property panels y project explorer, extraer QT-Widgets como módulo en `src/ui/widgets/`. Widgets candidatos: scrollbar, text-input, tree-view, tab-bar.

**Plan B:** Si Red se estanca (bugs GTK sin arreglar en 1-2 años, 64-bit no llega), migrar el editor a PyQt/PySide manteniendo Red como lenguaje del código generado (.qvi). El formato .qvi y el compilador no cambian.
43 changes: 38 additions & 5 deletions docs/plan.md
Original file line number Diff line number Diff line change
Expand Up @@ -157,11 +157,20 @@ Los controles de entrada se convierten en `field` editables. Los indicadores de

## Fase 3 — Sub-VIs y extensibilidad

- [ ] Connector pane: definir entradas/salidas de un VI para usarlo como bloque (#18)
- [ ] Compilador genera `func` Red para sub-VIs (DT-006, DT-009)
- [ ] Un .qvi con connector pane se puede usar como bloque en otro .qvi
- [ ] `.qlib`: librería de bloques con `context` Red para namespacing
### Sub-VIs
- [x] Connector pane: definir entradas/salidas de un VI para usarlo como bloque (#17) ✅
- [x] Compilador genera `func` Red para sub-VIs (DT-006, DT-009) ✅
- [x] Un .qvi con connector pane se puede usar como bloque en otro .qvi ✅

### Librería
- [ ] `.qlib`: librería de bloques con `context` Red para namespacing (#18)
- [ ] Paleta de bloques extensible por el usuario

### UX — Modelo de ventanas LabVIEW
- [ ] FP como ventana maestra — BD se abre bajo demanda con Ctrl+E (#64)
- [ ] Ventanas redimensionables con scroll horizontal y vertical (#65)

### Herramientas
- [ ] Depurador con sondas en wires (ver valor en ejecución)
- [ ] Exportar a ejecutable (compilación Red nativa a binario)

Expand Down Expand Up @@ -195,6 +204,26 @@ Esta fase es esencial para el público objetivo (mismo que LabVIEW: ingeniería

---

## Fase 5 — Experiencia de usuario y gestión de proyectos

### Splash / Welcome screen
- [ ] Pantalla de bienvenida al lanzar QTorres (Create New VI, Open Existing, proyectos recientes)
- [ ] Depende de que exista el concepto de proyecto (.qproj) o al menos .qlib (#18)

### Project Explorer (.qproj)
- [ ] Formato `.qproj`: fichero de proyecto que agrupa VIs, sub-VIs, librerías y targets
- [ ] Ventana Project Explorer con árbol de ficheros del proyecto (equivalente al .lvproj de LabVIEW)
- [ ] Abrir un .qproj carga el árbol y muestra el explorer (doble clic en un VI abre su FP)
- [ ] Gestión de dependencias entre VIs y librerías dentro del proyecto
- [ ] Depende de: .qlib (#18), FP como ventana maestra (#64)

### Notas
- El splash screen tiene sentido cuando haya algo que "abrir" — un .qproj o al menos historial de .qvi recientes
- El Project Explorer es una feature grande que requiere .qlib resuelto primero
- El modelo LabVIEW es: splash → project explorer → doble clic VI → FP → Ctrl+E → BD

---

## Hitos clave

| Hito | Descripción | Fase |
Expand All @@ -205,9 +234,13 @@ Esta fase es esencial para el público objetivo (mismo que LabVIEW: ingeniería
| Tipo booleano | Wire verde, LED control/indicator | 2 ✅ |
| Tipos completos | Boolean, string, array, cluster en wires | 2 |
| Estructuras de control | Bucles y condicionales en el diagrama | 2 |
| Sub-VIs | VIs reutilizables como bloques con connector | 3 |
| Sub-VIs | VIs reutilizables como bloques con connector | 3 ✅ |
| FP como master | FP ventana principal, BD bajo demanda | 3 |
| Resize + scroll | Ventanas redimensionables con scrollbars | 3 |
| Primera medida real | Controlar un Keysight desde QTorres | 4 |
| DAQ completo | Adquisición continua con tarjeta o Arduino | 4 |
| Welcome screen | Splash con Create/Open al lanzar QTorres | 5 |
| Project Explorer | Árbol de proyecto .qproj con gestión de VIs | 5 |

---

Expand Down
56 changes: 37 additions & 19 deletions docs/tipos-de-fichero.md
Original file line number Diff line number Diff line change
Expand Up @@ -324,37 +324,55 @@ qproj [

### `.qlib` — Librería

Una librería agrupa VIs y primitivas bajo un namespace. Puede contener tanto `.qvi` como `.qprim`.
Una librería agrupa VIs bajo un namespace. Es un **directorio** con un manifiesto `qlib.red` y los `.qvi` miembros. Cada miembro debe tener un `connector:` para poder usarse como sub-VI.

**Estructura:**
```
proyecto/
math.qlib ; manifiesto (fichero de texto)
math/
add.qvi ; sub-VI con connector
subtract.qvi ; sub-VI con connector
```

**Formato del fichero `math.qlib`:**
```red
qlib [
version: 1
name: "math"

name: "math"
version: 1
description: "Operaciones matematicas basicas"
members: [
%add.qprim
%subtract.qprim
%interpolate.qvi
%fft.qvi
%math/add.qvi
%math/subtract.qvi
]
]
```

Código generado al cargar la librería:
**Comportamiento en QTorres:**
- La paleta del editor detecta automáticamente `.qlib` en el directorio de trabajo
- Los VIs de la librería aparecen en sección "Librerías" de la paleta con etiqueta `nombre-lib/vi`
- Al insertar un VI de librería se crea un nodo subvi igual que con cualquier sub-VI
- Al compilar, el compilador emite `#include` selectivo (solo los miembros usados)

**Código generado en el caller (usa `#include` selectivo):**
```red
math: context [
do %math/add.qprim ; incrusta código de la primitiva
do %math/subtract.qprim
do %math/interpolate.qvi ; define math/interpolate
do %math/fft.qvi ; define math/fft
]

; Uso desde otro VI:
math/interpolate datos frecuencia
math/fft señal
_saved-qtorres-runtime: value? 'qtorres-runtime
qtorres-runtime: true
#include %math.qlib/add.qvi ; solo los miembros usados
#include %math.qlib/subtract.qvi
if not _saved-qtorres-runtime [unset 'qtorres-runtime]

; Llamadas con la convención nombre-context/exec:
resultado-suma: add/exec A B
resultado-resta: subtract/exec A B
```

**Instalación:**
- Local al proyecto: copiar el directorio `.qlib` junto al `.qvi` principal
- Global del usuario: copiar a `~/.qtorres/libs/` (pendiente de implementar)

**Ver ejemplo:** `examples/math.qlib` + `examples/math/` + `examples/usa-libreria.qvi`

### `.qctl` — Type definition

```red
Expand Down
9 changes: 9 additions & 0 deletions examples/math.qlib
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
qlib [
name: "math"
version: 1
description: "Operaciones matematicas basicas"
members: [
%math/add.qvi
%math/subtract.qvi
]
]
Loading
Loading