From 9d6ceb8145a2fc734eab7a4e78cbff39e3d3d618 Mon Sep 17 00:00:00 2001 From: Ilya Date: Thu, 2 Jul 2026 23:08:20 +0200 Subject: [PATCH] chore: scaffold project, plan, and toolchain Set up PyQt6 + QGraphicsView pipeline-editor skeleton, requirements, pytest headless config, and the actionable implementation plan under docs/plan. Co-Authored-By: Claude Opus 4.8 (1M context) --- .gitignore | 12 ++++ README.md | 53 +++++++++++++++++ docs/plan/README.md | 91 ++++++++++++++++++++++++++++++ pipeline_editor/__init__.py | 3 + pipeline_editor/calc/__init__.py | 1 + pipeline_editor/model/__init__.py | 1 + pipeline_editor/panels/__init__.py | 1 + pipeline_editor/view/__init__.py | 1 + pytest.ini | 4 ++ requirements.txt | 6 ++ tests/conftest.py | 11 ++++ 11 files changed, 184 insertions(+) create mode 100644 .gitignore create mode 100644 README.md create mode 100644 docs/plan/README.md create mode 100644 pipeline_editor/__init__.py create mode 100644 pipeline_editor/calc/__init__.py create mode 100644 pipeline_editor/model/__init__.py create mode 100644 pipeline_editor/panels/__init__.py create mode 100644 pipeline_editor/view/__init__.py create mode 100644 pytest.ini create mode 100644 requirements.txt create mode 100644 tests/conftest.py diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c0064ab --- /dev/null +++ b/.gitignore @@ -0,0 +1,12 @@ +__pycache__/ +*.py[cod] +*.egg-info/ +.pytest_cache/ +.venv/ +venv/ +build/ +dist/ +*.log +.DS_Store +.coverage +htmlcov/ diff --git a/README.md b/README.md new file mode 100644 index 0000000..11c930a --- /dev/null +++ b/README.md @@ -0,0 +1,53 @@ +# Pipeline Network Diagram Editor + +A desktop editor for drawing **pipeline networks** — water lines, power lines, gas, etc. — +built with **PyQt6** on the Qt **QGraphicsView** framework. + +## Features + +- **Node library** with grouped, draggable vector (SVG) symbols (pump, tank, valve, source, sink, junction…). +- **Typed ports** with relation semantics (water / power / gas / …) and per-relation color schemes; + connection compatibility is validated and highlighted. +- **Orthogonal edge routing** along a rectangular grid, with an optional **arc at line crossings**. +- **Edge styles**: line styles plus head/tail decorations (arrow, circle, diamond, none). +- **Grouped property panel** for the selected node/edge — presentation (geometry, title, color) and + physics (length, diameter, flow rate, flow type). Property types: string, int, float, bool, enum, + color, catalogue item, catalogue items, value list. +- **Mock flow calculation** distributing flow across edges, with **animated direction and volume**. +- Editing UX: drag, multi-select, snap-to-grid, undo/redo, copy/paste, save/open (JSON), + export to PNG/SVG, configurable grid & color schemes. + +## Requirements + +- Python 3.11+ +- PyQt6 (with QtSvg) + +On Debian/Ubuntu: `sudo apt install python3-pyqt6 python3-pyqt6.qtsvg` +or `pip install -r requirements.txt`. + +## Run + +```bash +python -m pipeline_editor +``` + +## Test + +Tests run headless: + +```bash +QT_QPA_PLATFORM=offscreen python -m pytest +``` + +## Layout + +``` +pipeline_editor/ + model/ domain: properties, catalogue, relations, ports, nodes, edges, document + view/ QGraphicsView canvas, scene, node/port/edge items, routing + panels/ node library dock, property editor dock + calc/ mock flow solver + animation + resources/ SVG node symbols, color schemes +docs/plan/ actionable implementation plan +tests/ pytest suites for typical scenarios +``` diff --git a/docs/plan/README.md b/docs/plan/README.md new file mode 100644 index 0000000..81085dd --- /dev/null +++ b/docs/plan/README.md @@ -0,0 +1,91 @@ +# Pipeline Network Diagram Editor — Implementation Plan + +A desktop diagram editor for drawing **pipeline networks** (water lines, power lines, +gas, etc.), built with **PyQt6** on the **QGraphicsView / QGraphicsScene** framework. + +## Tool selection (research outcome) + +| Candidate | Verdict | +|-----------|---------| +| **QGraphicsView framework (chosen)** | Maximum control over custom SVG nodes, typed ports, orthogonal grid routing, arc crossings, flow animation. Mature, high item-count performance. | +| QtNodes (paceholder/nodeeditor) | Dataflow-centric, fixed node visuals, v3 breaking API — poor fit for grid-routed pipeline networks. | +| QuickQanava (QML) | Modern but connection routing in QML is the hard part; less control over orthogonal/arc routing. | + +Bindings: **PyQt6 6.10** (apt, works with Python 3.14). Tests: **pytest + pytest-qt**, +headless via `QT_QPA_PLATFORM=offscreen`. + +Sources: +- +- +- +- + +--- + +## Phase 0 — Project scaffolding +- [ ] Repo layout, `requirements.txt`, `README.md`, `.gitignore` +- [ ] `pipeline_editor` package skeleton + `__main__` entry point +- [ ] pytest config + headless conftest (QApplication fixture) + +## Phase 1 — Domain model (no UI) +- [ ] `PropertyType` enum: string, int, float, bool, enum, color, catalogue_item, catalogue_items, value_list +- [ ] `Property` + `PropertyGroup` (grouped, editable/readonly, validation) +- [ ] `Catalogue` / `CatalogueItem` registry +- [ ] `PortRelation` registry (water/power/gas...) with color schemes + compatibility rules +- [ ] `Port` (id, name, relation, side/offset, direction) +- [ ] `NodeModel`, `EdgeModel` (ids, geometry, style, property groups) +- [ ] `DiagramDocument` — holds nodes/edges, emits change signals +- [ ] JSON serialization / deserialization (round-trip) + +## Phase 2 — Node library (feature #1) +- [ ] Bundled SVG node graphics (pump, tank, valve, junction, source, sink, transformer…) +- [ ] `NodeTemplate` = SVG + port configuration, organized into groups +- [ ] Left dock `NodePanel`: grouped tree with vector previews +- [ ] Drag-and-drop node template → canvas creates a node + +## Phase 3 — Canvas, scene & nodes +- [ ] `CanvasView`: zoom (wheel), pan, fit-to-view, rubber-band select +- [ ] Grid background (dots/lines), configurable size, snap-to-grid +- [ ] `NodeItem`: renders SVG, movable, selectable, edges follow on move +- [ ] Multi-select move, delete + +## Phase 4 — Ports & edges (features #2, #3, #5) +- [ ] Focused node reveals `PortItem` handles +- [ ] Port relation coloring + connection-compatibility feedback +- [ ] Drag from port → other node's port (or self) creates an edge +- [ ] Orthogonal routing along rectangular grid +- [ ] Config option: draw **arc** at line intersections/crossings +- [ ] `EdgeItem` styles: line style, head/tail decorations (arrow, circle, diamond, none) + +## Phase 5 — Property panel (feature #4) +- [ ] Right dock `PropertyPanel`: grouped property editors +- [ ] Editor widgets per type (string/int/float/bool/enum/color/catalogue/list) +- [ ] Two-way binding: edit → model → view refresh +- [ ] Geometry/title (presentation) group + physics group (length, diameter, flow rate, flow type) + +## Phase 6 — Mock calculation & flow animation +- [ ] `FlowSolver`: mock flow distribution across edges (conservation-ish heuristic) +- [ ] Per-edge flow value + direction +- [ ] `FlowAnimator`: animate direction (marching dashes) and volume (speed/width) +- [ ] Play/pause/stop controls + +## Phase 7 — Editing UX & configuration (added features) +- [ ] Undo/redo via `QUndoStack` (add/move/delete/connect/edit) +- [ ] Copy / paste / duplicate / delete +- [ ] Save / Open / New document (JSON) +- [ ] Export canvas to PNG / SVG +- [ ] Config dialog: grid size, snap, arc-on-crossing, color scheme, animation speed +- [ ] Multiple color schemes (light/dark + relation palettes) +- [ ] Toolbar + menus + status bar + keyboard shortcuts + +## Phase 8 — Tests (typical scenarios) +- [ ] Model: properties, catalogue, relations, serialization round-trip +- [ ] Routing: orthogonal path + arc-crossing generation +- [ ] Flow solver: conservation & direction on a small network +- [ ] Scene: create node via drop, connect ports, move node moves edge, delete cascades +- [ ] Property panel: edit propagates to model +- [ ] Undo/redo of add/move/connect/delete + +## Phase 9 — Polish +- [ ] README with run/test instructions and screenshots +- [ ] Final pass: lint, docstrings, sample document diff --git a/pipeline_editor/__init__.py b/pipeline_editor/__init__.py new file mode 100644 index 0000000..15f37ac --- /dev/null +++ b/pipeline_editor/__init__.py @@ -0,0 +1,3 @@ +"""Pipeline network diagram editor built on PyQt6 / QGraphicsView.""" + +__version__ = "0.1.0" diff --git a/pipeline_editor/calc/__init__.py b/pipeline_editor/calc/__init__.py new file mode 100644 index 0000000..47ac976 --- /dev/null +++ b/pipeline_editor/calc/__init__.py @@ -0,0 +1 @@ +"""Mock flow calculation and animation.""" diff --git a/pipeline_editor/model/__init__.py b/pipeline_editor/model/__init__.py new file mode 100644 index 0000000..cac9c22 --- /dev/null +++ b/pipeline_editor/model/__init__.py @@ -0,0 +1 @@ +"""Domain model for the pipeline editor.""" diff --git a/pipeline_editor/panels/__init__.py b/pipeline_editor/panels/__init__.py new file mode 100644 index 0000000..9c8f76a --- /dev/null +++ b/pipeline_editor/panels/__init__.py @@ -0,0 +1 @@ +"""Dock panels: node library and property editor.""" diff --git a/pipeline_editor/view/__init__.py b/pipeline_editor/view/__init__.py new file mode 100644 index 0000000..46e4da8 --- /dev/null +++ b/pipeline_editor/view/__init__.py @@ -0,0 +1 @@ +"""Graphics-view canvas, scene and items.""" diff --git a/pytest.ini b/pytest.ini new file mode 100644 index 0000000..03cef0e --- /dev/null +++ b/pytest.ini @@ -0,0 +1,4 @@ +[pytest] +testpaths = tests +qt_api = pyqt6 +addopts = -q diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..4f6e6c7 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,6 @@ +# Runtime +PyQt6>=6.6 + +# Testing +pytest>=7 +pytest-qt>=4 diff --git a/tests/conftest.py b/tests/conftest.py new file mode 100644 index 0000000..f54a4d3 --- /dev/null +++ b/tests/conftest.py @@ -0,0 +1,11 @@ +"""Shared pytest fixtures. Forces a headless Qt platform for CI-safe runs.""" +import os + +os.environ.setdefault("QT_QPA_PLATFORM", "offscreen") + +import pytest + + +@pytest.fixture(scope="session") +def qapp_args(): + return ["pipeline-editor-tests"]