A Visual Basic 6-inspired RAD IDE for Python, built with PyQt6.
Draw a window, drop widgets on it with absolute positioning, set properties in a panel, double-click a widget to write its event handler in an integrated code editor, then press F5 to run. PyRAD generates clean, hand-readable PyQt6 source where your handler code is preserved verbatim across regenerations.
Status: active development. Phases 1–4 complete (see
PyRAD_Progress.md). Phase 5 (multi-form projects + PyInstaller build) is next.
- Absolute-positioning canvas inside a fake VB6-style window wrapper.
- 21 widget types (buttons, labels, line/text edits, checkboxes, radios, combos, lists, spin/slider, group/frame, tab/scroll, progress, date/time/datetime, calendar, table, tree).
- 8-directional resize handles with per-direction cursors and min-size clamping.
- Rubber-band multi-select, Shift/Ctrl-click additive selection, group move.
- Format menu: align L/R/T/B, center H/V, make same width/height/size — operates on multi-selection, anchored on the primary widget.
- Right-click context menu: cut/copy/paste/delete, bring-to-front/send-to-back, view code.
- Form resize by dragging the wrapper's right/bottom edge.
- Light/dark themes via
ThemeManager.
- Python syntax highlighting, line numbers, folding, current-line highlight, auto-indent, 4-space tabs, brace matching.
- Find (
Ctrl+F), Replace (Ctrl+H), Goto line (Ctrl+G). - Region-marker generation: code between
# region PyRAD: USER CODEis preserved across regenerations; code between# region PyRAD: GENERATEDis rewritten. - Generated regions auto-fold on load so the user sees signatures, not boilerplate.
- Double-click a widget on the canvas → switches to the Code tab and creates/jumps to its primary event handler (e.g.
on_Button1_clicked); matchingconnect()calls are auto-emitted into the generated region. - Events group in the Properties panel — double-click any signal to wire a handler.
F5runs the project;Shift+F5stops. Workflow: save project → save editor → regenerate code → launch aspython -usubprocess (inherits the IDE's venv so PyQt6 is available out of the box).- Live stdout/stderr stream to the Output dock (stderr in red). Exit code shown on termination. Status bar mirrors run state.
QUndoStack-based command pattern covers every design-surface mutation: add / delete / move / resize / align / z-order / property change / form resize.- Edit menu shows dynamic labels (e.g.
Undo Add QPushButton) and enables/disables off the stack. - Property-panel edits coalesce via
QUndoCommand.mergeWith— one undo per logical change, not per keystroke. - Deleted widgets are kept alive (reparented to the form widget) so undo restores the exact same instance with all state and signal connections intact.
- Project format: JSON
.pyrad(legacy.pyformsfiles still load). - Code generator emits absolute-positioning PyQt6 with
objectName-based variable names (self.Button1,self.Label1, …). Auto-numbering per type viaWidgetFactory._type_counters. - Generated code is a runnable
QMainWindowscript. The IDE preserves your handler code across every regeneration.
- Linux, Windows, or macOS
- Python 3.11+
- A Qt 6.5+ environment (the bundled
setup.shprovisions this in a venv so the system Qt version does not matter)
./setup.sh # creates ./venv and installs requirements.txt
./run.sh # launches the IDErun.sh will auto-invoke setup.sh on first run if ./venv is missing.
python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txt
python pyrad.pyPyRAD/
├── pyrad.py # Entry point
├── run.sh / setup.sh # Convenience scripts
├── requirements.txt # PyQt6, PyQt6-QScintilla, pytest, pytest-qt, …
├── PyRAD_ProjectPlan.md # Master feature specification
├── PyRAD_Progress.md # Session log + current status
├── projects/ # User project storage
├── src/
│ ├── main_window.py # IDE shell, menus, docks
│ ├── design_surface.py # Canvas, FormWidget, WindowWrapper, handles
│ ├── code_editor.py # QScintilla editor panel
│ ├── runner.py # QProcess-based AppRunner
│ ├── commands.py # QUndoCommand subclasses
│ ├── toolbox.py # Widget palette
│ ├── properties_panel.py # Property grid + Events group
│ ├── code_generator.py # PyQt6 source emitter
│ ├── project_manager.py # .pyrad JSON save/load
│ ├── theme_manager.py # Light/dark QSS
│ ├── widget_factory.py # Widget creation & auto-naming
│ └── widget_properties/ # Per-widget property editors (21 modules)
└── tests/ # pytest + pytest-qt suite
QT_QPA_PLATFORM=offscreen ./venv/bin/python -m pytest tests/Currently 128 tests. The runner-subprocess tests in tests/test_runner.py segfault when run after the GUI test suite in the same process (pre-existing pytest-qt + QProcess interaction); they pass cleanly in isolation:
QT_QPA_PLATFORM=offscreen ./venv/bin/python -m pytest tests/test_runner.pyRead PyRAD_ProjectPlan.md (master spec) and PyRAD_Progress.md (what's done, what's next) before changing anything. Architecture invariants worth knowing up front:
- PyQt6 only. No PySide6, no PyQt5.
- The design canvas uses absolute positioning. Never add a layout manager to the form canvas.
- Generated files keep both region markers; user code between them is preserved verbatim.
- All inter-component communication via Qt signals/slots.
- All new UI panels must participate in
ThemeManager.theme_changed.
Not yet licensed — the repository is private while the author decides on a final license. Do not assume permission to redistribute or modify until a license file is added.
PyRAD is developed by Chuck Finch / Fragillidae Software.
