Files
BEdit/AGENTS.md

205 lines
9.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# BEdit Agent Guide
This file is the handoff context for coding agents working in this repository. Read it before making changes.
## Working agreement
- Make only the changes the user requested.
- Keep completely out of unrelated code. Do not reformat, reorder, rename, clean up, or “improve” code that is outside the task.
- Preserve existing user changes and assume a dirty worktree belongs to the user.
- Inspect the relevant files before deciding on an implementation.
- Prefer small, modular changes over growing `MainWindow`, a controller, or another file into a monolith.
- When the user asks why something happens, diagnose and explain it without editing files unless they also ask for a fix.
- Do not create commits unless explicitly requested.
## Code style
Follow the local style in the file being edited, with these user preferences taking priority:
- Prefer compact, readable one-line imports. Do not introduce parenthesized multiline imports.
- Avoid spreading short function calls, conditions, and expressions across multiple lines.
- Do not run broad formatters or import sorters.
- Do not use a lint autofix over the project.
- Keep classes and functions focused. Extract a controller, service, command, model, or reusable widget when a feature would otherwise make an existing file large.
- Generated modules contain no handwritten application behavior.
The project uses Ruff, but import sorting is intentionally not enforced during scoped checks:
```sh
.venv/bin/ruff check --ignore I001 path/to/changed_file.py
```
## Project structure and dependency direction
Relevant GUI structure:
```text
src/bedit_gui/
├── application.py
├── commands/
├── controllers/
├── documents/
├── models.py
├── services/
├── ui/
│ ├── forms/
│ └── generated/
├── resources/
│ └── generated/
├── utils/
└── views/
└── models/
```
Responsibilities:
- `application.py`: composition root. Create and connect the application, document, window, services, and controllers here.
- `documents/document.py`: editable document facade. Owns the core model, path, main `QUndoStack`, modified state, and high-level operations.
- `commands/`: `QUndoCommand` implementations. Persistent changes to the document model go through commands.
- `controllers/`: connect actions and widgets to document/service operations. Keep workflow logic out of `MainWindow`.
- `views/`: handwritten widget/window/graphics behavior.
- `views/models/`: Qt item models used by views.
- `services/`: non-visual functionality such as files, clipboard, logging, and settings.
- `models.py`: GUI metadata persisted inside the core document, currently including icons and shapes.
- `bedit_core`: domain model and serialization. It must never import from `bedit_gui`.
Preferred direction:
```text
views/controllers
documents/services
commands
bedit_core
```
Avoid introducing imports from `bedit_gui` into `bedit_core` or circular dependencies between services and documents.
## Qt Designer and generated files
Raw forms are in:
```text
src/bedit_gui/ui/forms/
```
Generated Python is in:
```text
src/bedit_gui/ui/generated/
```
Never add handwritten behavior to generated UI modules. Change the `.ui` form and regenerate with:
```sh
.venv/bin/python scripts/generate_qt_files.py
```
The generation script also fixes the package-qualified resource import. Calling `pyside6-uic` directly without the script can produce a broken `resources_rc` import.
Raw resources and the QRC file live under `src/bedit_gui/resources/`. Generated resource Python lives under `src/bedit_gui/resources/generated/`.
## Undo and document changes
- The main application document owns the main undo stack.
- The icon editor owns a separate local undo stack.
- The `Document` facade should expose high-level methods that push commands. Controllers should normally call those methods rather than construct commands.
- Commands mutate the model in `redo()`/`undo()` and emit the appropriate document signals.
- Multi-object user operations should be one command or one undo macro.
- Allocate stable IDs and final names before pushing a command so redo reproduces the same result.
- Component names must be unique within their destination component dictionary. Conflicts use `_0`, `_1`, and so on.
- Copy/paste must generate new component, port, parameter, connection, and icon-shape IDs and rewrite references.
## Document tree
`DocumentTreeModel` has two columns:
- Column 0: editable document/component name.
- Column 1: rendered component icon.
Use `selectedRows(0)` for multi-selection; `selectedIndexes()` returns both columns. Filter selected descendants when an ancestor is also selected.
The tree uses extended row selection. Delete, cut, and copy may operate on multiple components. Paste targets either:
- the document root, or
- the component dictionary of a selected graph component.
The controller listens to document model/icon signals and refreshes the tree/icon cache.
## Clipboard architecture
Clipboard support is intentionally extensible:
- `services/clipboard.py`: system `QClipboard` and MIME/JSON handling.
- `services/component_clipboard.py`: component payload serialization and ID remapping.
- `controllers/clipboard_controller.py`: focus-based action router and handlers.
`ClipboardHandler` is the base implementation for future editors. Add a graph-editor handler later by subclassing it and registering that handler in `application.py`.
Text widgets use their native `copy()`, `cut()`, and `paste()` methods. Component clipboard data uses the custom BEdit MIME type and JSON; never use pickle or live object references.
## Icon editor conventions
- Icons are GUI metadata stored in `document.metadata["icon_database"]`.
- Shapes currently include rectangles, text, and lines.
- Shape changes use the icon editors local undo stack.
- Shapes are selectable, movable, resizable, pixel-snapped, and constrained to the icon scene.
- Ports are separate 16×16 items: black for inputs and white for outputs. They can be moved but are not ordinary deletable/copyable shapes.
- Colors are serialized as `#rrggbbaa`.
- The icon scene is currently `(-64, -64, 128, 128)`.
- The grid spacing is 8 scene pixels and is drawn only inside the scene rectangle.
- Keep reusable widgets such as the RGBA color button independent of the icon editor.
- Static icon previews belong in rendering utilities, not in the interactive editor scene.
## Actions and shortcut routing
- Put visible actions in Designer menus/toolbars.
- An action that only exists as a child object may not have an active shortcut; attach it to the relevant widget or place it in a menu/toolbar.
- Route application-wide Copy/Cut/Paste by focused widget through `ClipboardController`.
- Scope destructive shortcuts to the relevant widget where appropriate.
- Always guard the operation itself even when an action is disabled for presentation.
## Simulator application
- `bedit_gui/simulation_application.py` is the composition root for the separate `bedit-sim` Qt application.
- Keep compilation GUI-independent. Shared compile entry points belong in `bedit_simulation` and must not create or depend on a `QApplication` or window.
- The simulator opens BEdit `.beb`/`.json` documents or serialized simulation `.bes`/`.json` files.
- A component selector uses default simulation settings. A stored simulation-settings block already identifies its component; do not require both selectors.
- `SimulationDatabase.active_simulation` is the persisted active settings ID selected when the Simulation Settings dialog is accepted.
- Simulation files serialize `bedit_gui.simulation_models.SimulationRoot`. JSON uses the `root_type = "simulation_root"` discriminator; binary `.bes` files use their own BES header.
- `SimulationRoot` contains source-document identity, the selected component and copied settings, and eventually results. Compiled artifacts are transient application state and must not be serialized; reopen saved simulations by compiling them again. Never serialize live Python objects.
- BEdit launches the simulator as a separate process. Compile/Open Simulation integration may transfer a `.bes` file to that process.
- Keep simulator file workflows in their own services/controllers rather than adding them to `MainWindow` or the editor document controller.
- Keep compiled-executable launching, time-window progression, result loading, and cancellation inside `bedit_simulation`. GUI controllers may schedule backend calls and present state, but must not execute or manage simulation binaries themselves.
## Verification
The old test suite and its VS Code/packaging references were deliberately removed. Do not recreate a test suite unless asked.
Use checks proportional to the change:
```sh
.venv/bin/ruff check --ignore I001 path/to/changed_files.py
```
For Qt smoke checks in a headless environment:
```sh
QT_QPA_PLATFORM=minimal QT_QPA_PLATFORMTHEME= QT_STYLE_OVERRIDE=Fusion .venv/bin/python ...
```
Prefer focused model, serialization, signal, command undo/redo, and offscreen rendering checks. Do not launch a GUI during verification unless explicitly requested or approved.
## Handoff expectations
At the end of a task, report:
- the outcome,
- the files or subsystem changed,
- relevant behavior and limitations,
- checks that actually passed.
Do not claim tests passed when only a lint or smoke check was run.