178 lines
7.1 KiB
Markdown
178 lines
7.1 KiB
Markdown
# BEdit Qt starter
|
|
|
|
A small desktop application scaffold using Python and PySide6 (the official Qt
|
|
bindings). Its interface is maintained in Qt Designer and it includes a main
|
|
window, menu bar, blank central workspace, common keyboard shortcuts, and
|
|
persisted window geometry. The application forces Qt's light Fusion palette, so
|
|
it remains light even when the operating-system theme is dark.
|
|
|
|
## Run it
|
|
|
|
Python 3.10 or newer is required. From this directory:
|
|
|
|
```bash
|
|
python -m venv .venv
|
|
```
|
|
|
|
Activate the environment:
|
|
|
|
- Windows PowerShell: `.venv\Scripts\Activate.ps1`
|
|
- Windows Command Prompt: `.venv\Scripts\activate.bat`
|
|
- Linux/macOS: `source .venv/bin/activate`
|
|
|
|
Then install and launch:
|
|
|
|
```bash
|
|
python -m pip install --upgrade pip
|
|
python -m pip install -e ".[dev]"
|
|
python -m bedit
|
|
```
|
|
|
|
After installation, the `bedit` command also launches the application.
|
|
|
|
## Project layout
|
|
|
|
```text
|
|
.
|
|
├── pyproject.toml dependencies, package metadata, and `bedit` command
|
|
├── README.md
|
|
├── ui/main_window.ui editable Qt Designer source
|
|
└── src/bedit
|
|
├── __main__.py supports `python -m bedit`
|
|
├── app.py starts Qt and applies the forced light palette
|
|
├── main_window.py behavior and signal connections
|
|
└── ui_main_window.py generated from the Designer file; do not hand-edit
|
|
```
|
|
|
|
## Designing the UI further
|
|
|
|
The project now uses Qt Designer. It is included with PySide6 on most
|
|
installations. Open the existing form with:
|
|
|
|
```bash
|
|
pyside6-designer ui/main_window.ui
|
|
```
|
|
|
|
In Designer, use the Widget Box to add controls, the Object Inspector to select
|
|
them, and the Property Editor to name and configure them. Always put widgets in
|
|
a layout (horizontal, vertical, grid, or form) so the window resizes correctly.
|
|
|
|
Save the form, close the running application if necessary, then regenerate its
|
|
Python wrapper:
|
|
|
|
```bash
|
|
pyside6-uic ui/main_window.ui -o src/bedit/ui_main_window.py
|
|
```
|
|
|
|
Do not hand-edit the generated Python file; change the `.ui` file and regenerate
|
|
it. Add behavior and signal connections in `main_window.py`. Widget names from
|
|
Designer are available there through `self.ui`, such as `self.ui.graphView`.
|
|
|
|
In VS Code, the same commands are available through **Terminal → Run Task**:
|
|
|
|
- **Qt: Open Main Window in Designer** opens the form for visual editing.
|
|
- **Qt: Build Designer Files** compiles resources and then regenerates the UI
|
|
wrapper. It is the default build task, available with `Ctrl+Shift+B`.
|
|
- The separate resource and UI compilation tasks remain available when only one
|
|
generated file needs rebuilding.
|
|
|
|
## A sensible next design pass
|
|
|
|
1. Sketch the main tasks and screens before choosing widgets.
|
|
2. Turn each major area into its own widget class in `src/bedit/widgets/`.
|
|
3. Use a `QStackedWidget` for page-like navigation, or `QDockWidget` for movable
|
|
tool panels in an editor-style application.
|
|
4. Use reusable `QAction` objects for menu commands and any future toolbars.
|
|
5. Keep file/data operations outside widget classes as the application grows.
|
|
6. Add icons through a Qt resource file (`.qrc`) so packaging is reliable.
|
|
7. Test on Windows regularly; fonts, scaling, and native dialogs vary by platform.
|
|
|
|
## Graph and library prototype
|
|
|
|
Documents and libraries use the same recursive format: a library is simply a
|
|
BEdit document used as a copy source. The built-in example defines A, B, and C.
|
|
|
|
- A document can own multiple independent top-level graph or text components.
|
|
Right-click **Current Document** to create one, and double-click a current
|
|
component in the tree to activate it.
|
|
- Drag a component from Libraries onto the workspace. Placement recursively
|
|
copies it with new IDs, leaving no link to the source.
|
|
- Drag components to move them; movement participates in undo and redo.
|
|
- Components, interface terminals, and connections are selectable. Use a rubber
|
|
band or Ctrl-click for multiple selection, Delete to remove items, and the
|
|
standard Cut/Copy/Paste shortcuts to duplicate selected component groups.
|
|
- Click an output port and then an input port to create a connection.
|
|
- Double-click a graph component to open its owned subgraph; use **Up** to return.
|
|
- Graph components show **Pointer**, **Input**, and **Output** tools. Select an
|
|
interface tool and click the canvas to add a visible internal terminal and a
|
|
corresponding external block port. Interface terminals can be moved afterward.
|
|
- Right-click a component on the canvas or in Current Document to edit its name,
|
|
icon shape, icon text, fill color, and border color. The same dialog can hide
|
|
that component's contained subtree from the Libraries tree.
|
|
- Double-click a text component to edit its input list, output list, and
|
|
`implementation.source` JSON.
|
|
- Right-click any graph component under Current Document to add nested graph or
|
|
text blocks. Any current-document component can also be deleted there.
|
|
- The active document hierarchy has its own Document panel; the Libraries panel
|
|
contains only configured external libraries.
|
|
- Select one or more blocks and press `Ctrl+R`, or use the Transform toolbar, to
|
|
rotate them clockwise by 90 degrees. Rotation is saved and supports undo/redo.
|
|
**Apply JSON** updates that source and participates in undo/redo.
|
|
- File → Save writes the complete recursive document to JSON.
|
|
- File → Close Document removes the active document and returns to an empty
|
|
workspace. An open graph uses a light gray, 32-unit dotted canvas.
|
|
- Edit → Settings → Libraries accepts document files or folders of JSON files.
|
|
|
|
Every component owns its ports, declarative icon, properties, and child graph:
|
|
|
|
```json
|
|
{
|
|
"format": "bedit-document",
|
|
"version": 1,
|
|
"roots": [{
|
|
"id": "my-component",
|
|
"name": "My Component",
|
|
"position": {"x": 0, "y": 0},
|
|
"interface": {
|
|
"inputs": [{"id": "in", "name": "Input"}],
|
|
"outputs": [{"id": "out", "name": "Output"}]
|
|
},
|
|
"icon": {
|
|
"shape": "rectangle",
|
|
"fill": "#dbeafe",
|
|
"border": "#245c9c",
|
|
"text": "Component"
|
|
},
|
|
"properties": {},
|
|
"implementation": {
|
|
"kind": "text",
|
|
"source": {
|
|
"equations": ["out = gain * in"],
|
|
"parameters": {"gain": 1.0}
|
|
}
|
|
}
|
|
}]
|
|
}
|
|
```
|
|
|
|
Graph components use `"implementation": {"kind": "graph", "graph": ...}`;
|
|
text components use `"implementation": {"kind": "text", "source": ...}` and
|
|
never own a graph. Supported icon shapes are currently `rectangle` and
|
|
`ellipse`. The recursive model is under `src/bedit/document/`, library loading
|
|
and the live Current Document tree are under `src/bedit/library/`, and graphics
|
|
are isolated under `src/bedit/workspace/`.
|
|
|
|
## Optional tools
|
|
|
|
You do not need another GUI framework. Useful additions are:
|
|
|
|
- **Qt Designer** for drag-and-drop form layout.
|
|
- **Ruff** for formatting/linting (`ruff check .`).
|
|
- **pytest-qt** later for GUI interaction tests.
|
|
- **PyInstaller** or **Nuitka** later to produce a Windows `.exe`.
|
|
|
|
The light colors are defined in `apply_light_theme()` in `src/bedit/app.py`.
|
|
Adjust that palette if you want different light colors. Avoid a large stylesheet
|
|
unless the application needs highly customized controls; palettes preserve more
|
|
of Qt's standard behavior.
|