![]() |
SWMMVis
6.0.0-alpha.4
Qt6/C++ GIS-based graphical user interface for the SWMMVis engine (6.0.0-alpha.4)
|
Namespaces | |
| namespace | aquifer |
| namespace | controls |
| namespace | core |
| namespace | curve |
| namespace | feature |
| namespace | import |
| namespace | inlet |
| namespace | io |
| namespace | landuse |
| namespace | lid |
| namespace | map |
| namespace | pattern |
| namespace | platform |
| namespace | plot |
| namespace | pollutant |
| namespace | project |
| namespace | sectionview |
| namespace | snowpack |
| namespace | street |
| namespace | timeseries |
| namespace | transect |
| namespace | ui |
Classes | |
| struct | ColumnSpec |
| class | CompoundEditDelegate |
| class | EnumDelegate |
| class | FileBrowseDelegate |
| class | FileColumnDelegate |
| class | FileFilterRegistry |
| Process-wide registry of file filters, populated from engine plugins + built-ins. More... | |
| struct | HydrationAuditEntry |
| One row of the §M.2 status-bar audit table. More... | |
| class | IntegerDelegate |
| class | IntervalDelegate |
| class | NumericDelegate |
| struct | OutputIdentity |
| class | OutputStatsRegistry |
| struct | QueryNode |
| struct | QueryPredicate |
| struct | SaveAsPathResult |
| struct | StorageShapeRow |
| struct | XsectShapeRow |
Enumerations | |
| enum class | FilterKind { InputRead , ResultsRead , ResultsWrite , ReportWrite , StateRead , StateWrite , ProjectRead , ProjectWrite , VectorRead , RasterRead , TabularRead , MapExportWrite , ComponentConfigRead } |
| GUI-side filter category. Superset of openswmm::PluginRole. More... | |
| enum class | RunOutputKind { Rpt , Out } |
| enum class | EditorKind { ReadOnly , Numeric , Integer , Enum , Text , Compound , Interval , FileBrowse , FileColumn } |
| enum class | UnitKind { None , Length , Area , SubcatchArea , Volume , Velocity , FlowRate , Depression , Percent , Rate } |
Functions | |
| QueryPredicate | parseQuery (const QString &whereClause) |
| QStringList | queryFieldNames (const QueryPredicate &pred) |
| bool | evaluateQuery (const QueryPredicate &pred, const QVariantMap &row) |
| SaveAsPathResult | normalizeSaveAsPath (const QString &dialogPath, const QSet< QString > &writableExtensions) |
| QString | resolveRunOutputPath (const QString &inpPath, const QString &override_, RunOutputKind kind) |
| QString | resolveRunOutputPathFromSettings (const QString &inpPath, RunOutputKind kind) |
| const StorageShapeRow * | findStorageShapeRow (int engineId) |
| bool | storageShapeIsGeometric (int shapeId) |
| QString | storageGeomLabel (int shapeId, int ordinal) |
| bool | storageGeomApplies (int shapeId, int ordinal) |
| const XsectShapeRow * | findXsectShapeRow (int engineId) |
| QString | xsectShapeName (int engineId) |
| QString | xsectGeomLabel (int shapeId, int ordinal) |
| bool | xsectGeomApplies (int shapeId, int ordinal) |
| bool | xsectGeomIsPickerIndex (int shapeId, int ordinal) |
Variables | |
| constexpr int | kFileColumnOptionsRole = Qt::UserRole + 21 |
| constexpr int | kStorageTabularId = 0 |
| Engine ids, spelled out so call sites don't hard-code magic numbers. | |
| constexpr int | kStorageFunctionalId = 1 |
| constexpr int | kStorageCylindricalId = 2 |
| constexpr int | kStorageConicalId = 3 |
| constexpr int | kStorageParaboloidId = 4 |
| constexpr int | kStoragePyramidalId = 5 |
| constexpr StorageShapeRow | kStorageShapes [] |
| constexpr int | kXsectIrregularId = SWMM_XSECT_IRREGULAR |
| constexpr int | kXsectStreetId = SWMM_XSECT_STREET |
| constexpr int | kXsectCustomId = SWMM_XSECT_CUSTOM |
| constexpr XsectShapeRow | kXsectShapes [] |
| constexpr std::array< HydrationAuditEntry, 2 > | kStatusBarHydrationAudit |
| The closed §M.2 status-bar list. Update when a new INP-driven widget lands; the Phase CX.1 regression test asserts every entry hydrates correctly at all three §M.1 triggers. | |
|
strong |
Slice Z.5.2 — How a column is edited (or not).
| Enumerator | |
|---|---|
| ReadOnly | Default; flags() omits ItemIsEditable. |
| Numeric | NumericDelegate (QDoubleSpinBox). |
| Integer | IntegerDelegate (QSpinBox). |
| Enum | EnumDelegate (QComboBox) with pre-baked pairs. |
| Text | Plain QLineEdit (default delegate); used for Name column. |
| Compound | CompoundEditDelegate (NodeCompoundEditButton). Used for per-node multi-row attributes (Inflows / DWF / RDII / Treatment) where the cell shows a summary + opens a dedicated dialog. The model returns a NodeCompoundEditRef QVariant for these columns. |
| Interval | IntervalDelegate (editable QComboBox of legacy H:MM presets). The cell stores/edits a clock string; the setter wrappers convert to/from engine seconds. First user: rain gage Recording Interval (DA.2 parity). |
| FileBrowse | FileBrowseDelegate (QLineEdit + "…" QFileDialog button). ColumnSpec::fileFilter carries the dialog's name filter. First user: rain gage Rain File (path) — multi-column series files, spec §4 task 4. |
| FileColumn | FileColumnDelegate (editable QComboBox). Per-row options come from the model via kFileColumnOptionsRole (the row's rain-file column headers). First user: rain gage Rain File Column. |
|
strong |
GUI-side filter category. Superset of openswmm::PluginRole.
| Enumerator | |
|---|---|
| InputRead | SWMM model input ( |
| ResultsRead | SWMM binary output ( |
| ResultsWrite | SWMM binary output ( |
| ReportWrite | SWMM summary report ( |
| StateRead | Hot-start input. Engine-backed ( |
| StateWrite | Hot-start output. Engine-backed ( |
| ProjectRead | SWMMVis project sidecar ( |
| ProjectWrite | SWMMVis project sidecar ( |
| VectorRead | GIS vector layer (Shapefile, GeoJSON, GeoPackage, …). GUI-only. |
| RasterRead | GIS raster layer (GeoTIFF, ASCII grid, NetCDF, …). GUI-only. |
| TabularRead | Observed / tabular data ( |
| MapExportWrite | Map export ( |
| ComponentConfigRead | Process-component config sidecars ( |
|
strong |
|
strong |
Round-4 follow-up 2026-05-12 — semantic unit class. Resolves to a string at render time via UnitSystem::instance() so the Attribute Table header reflects the current flow-units system (US-customary vs SI). Columns without a physical unit set UnitKind::None; the column header then carries no suffix.
| Enumerator | |
|---|---|
| None | No physical unit (counts, ids, names, etc.) |
| Length | ft / m (invert, max depth, offsets, crest height) |
| Area | ft² / m² (ponded area, cross-section) |
| SubcatchArea | ac / ha (subcatchment area; SWMM convention) |
| Volume | ft³ / m³ |
| Velocity | ft/s / m/s |
| FlowRate | CFS / CMS — uses UnitSystem::flowUnitLabel. |
| Depression | in / mm (depression storage, rainfall) |
| Percent | % — always |
| Rate | in/hr / mm/hr (infiltration, seepage) |
| bool openswmmvis::evaluateQuery | ( | const QueryPredicate & | pred, |
| const QVariantMap & | row | ||
| ) |
Evaluate the predicate against one row. When pred.root is null, returns true (no filter).
|
inline |
Look up a shape row by engine id; falls back to FUNCTIONAL for an unknown id so callers never get nullptr.
|
inline |
Look up a shape row by engine id; falls back to the first row (CIRCULAR) for an unknown id so callers never get nullptr.
| SaveAsPathResult openswmmvis::normalizeSaveAsPath | ( | const QString & | dialogPath, |
| const QSet< QString > & | writableExtensions | ||
| ) |
Collapse duplicated writable extensions and compute (inpPath, isProject).
| dialogPath | Raw path returned by QFileDialog::selectedFiles(). Empty input returns an empty result with isProject=false, wasNormalized=false. |
| writableExtensions | Lowercase extensions (no leading dot) that the GUI's FileFilterRegistry recognises as writable formats — today: {"inp", "oswp", "gpkg"}. The normalizer only collapses <ext>.<ext> duplicates when both halves appear in this set, so a user- coined filename like model.bak.bak (custom kind) passes through unchanged. |
Examples (writableExtensions = {inp, oswp, gpkg}): "/p/m.inp" → {"/p/m.inp", isProject=false, wasNormalized=false} "/p/m.inp.inp" → {"/p/m.inp", isProject=false, wasNormalized=true} "/p/m.oswp" → {"/p/m.inp", isProject=true, wasNormalized=false} "/p/m.inp.oswp" → {"/p/m.inp", isProject=true, wasNormalized=true} "/p/m.oswp.inp" → {"/p/m.inp", isProject=false, wasNormalized=true} "/p/m.gpkg.gpkg" → {"/p/m.gpkg", isProject=false, wasNormalized=true} "/p/m.bak.bak" → {"/p/m.bak.bak", isProject=false, wasNormalized=false} "/p/m.inp.inp.inp" → {"/p/m.inp", isProject=false, wasNormalized=true} "" → {"", isProject=false, wasNormalized=false}
| QueryPredicate openswmmvis::parseQuery | ( | const QString & | whereClause | ) |
Parse a WHERE-clause string. Empty input → predicate that matches everything (root is null, error is empty).
| QStringList openswmmvis::queryFieldNames | ( | const QueryPredicate & | pred | ) |
Field names the predicate actually references, deduplicated and in first-seen order. Empty when pred.root is null.
Callers use this to build a row map holding ONLY the columns the query compares, instead of materialising every column of every row. On a 272k-row / 55-column table that is the difference between ~30M cell reads per filter pass and ~272k.
Names are returned exactly as the user spelled them, so the caller must key its row map by these same strings for evaluateQuery to find them (see lookupField in the .cpp — an exact-key hit avoids its case-insensitive linear fallback).
| QString openswmmvis::resolveRunOutputPath | ( | const QString & | inpPath, |
| const QString & | override_, | ||
| RunOutputKind | kind | ||
| ) |
Pure resolver. Reads no global state — the caller is responsible for having looked up the QSettings override (empty string when none).
Resolution precedence:
override — when non-empty, takes effect. Absolute paths pass through unchanged; relative paths are resolved against the directory containing inpPath.<inpStem>.<rpt|out> next to the .inp.Empty inpPath returns an empty string regardless of override.
| QString openswmmvis::resolveRunOutputPathFromSettings | ( | const QString & | inpPath, |
| RunOutputKind | kind | ||
| ) |
Live-QSettings convenience wrapper used by SWMMVis::runActiveProject. Reads the per-project override from QSettings under SWMMVis/Project/<inpPath>/{Report,Output}FilePath (matching Slice AA-4's key layout) and dispatches to the pure resolver above. Tests use the pure variant; production code uses this.
|
inline |
True iff param ordinal (1..3) is a real, directly-editable dimension for shapeId. A cylinder has no side slope, so ordinal 3 is false there.
|
inline |
Shape-specific label for param ordinal (1..3), e.g. "Base Length". Empty when the dimension is unused for the shape or the ordinal is out of range.
|
inline |
True iff shapeId is one of the four geometric shapes — i.e. the ones driven by raw dimensions rather than by a curve or by the A/B/C power law.
|
inline |
True iff geom ordinal (1..4) is a real, directly-editable dimension for shapeId. IRREGULAR / STREET return false for every ordinal (geom1 there is a transect / street index, set only via the dialog); CUSTOM excludes only geom2 (its shape-curve index), keeping geom1 (max depth) inline-editable.
This answers "does this geom MEAN anything for the shape" — it drives labels and tooltips. It is deliberately NOT the editability test: the stored geom values exist regardless of shape, and blanking them made the inline cells look broken. Use xsectGeomIsPickerIndex() to decide what an inline editor may write.
|
inline |
True iff geom ordinal holds a PICKER-OWNED INDEX rather than a dimension: IRREGULAR / STREET geom1 (an index into the transect / street list) and CUSTOM geom2 (an index into the shape-curve list).
These are the only slots an inline numeric editor must refuse. Typing a raw number into them re-points the section at an arbitrary transect / curve — silent model corruption — so they stay read-only and are set through the complex dialog's name picker. Every other geom, including ones the current shape doesn't use, is a plain stored number and is freely editable: a user switching CIRCULAR → RECT_CLOSED expects the width they typed to still be there.
|
inline |
Shape-specific label for geom ordinal (1..4), e.g. "Diameter". Empty string when the geom is unused for the shape or ordinal is out of range.
|
inline |
Shape name for engineId ("CIRCULAR", …), or an empty QString when the id is not one the GUI surfaces. Since Slice SP.3 the table covers all 26 engine shapes, so an empty return now means the id is genuinely unknown (e.g. a model written by a newer engine). Unlike findXsectShapeRow() this does NOT fall back to CIRCULAR — display paths must be able to render "UNKNOWN" instead of confidently naming the wrong shape.
|
inlineconstexpr |
Custom data() role for EditorKind::FileColumn cells — returns the QStringList of column names enumerated from the row's resolved data file (ui/util/externalcolumnfile.h readHeaders).
|
inlineconstexpr |
The closed §M.2 status-bar list. Update when a new INP-driven widget lands; the Phase CX.1 regression test asserts every entry hydrates correctly at all three §M.1 triggers.
|
inlineconstexpr |
|
inlineconstexpr |
|
inlineconstexpr |
|
inlineconstexpr |
|
inlineconstexpr |
|
inlineconstexpr |
Dimension meanings are the legacy solver's (src/legacy/engine/node.c storage_readParams): for the elliptical shapes p1/p2 are the FULL axes (the engine halves them into semi-axes itself); for the pyramid they are the full base length and width. p3 is a run-over-rise side slope, except on the paraboloid where it is the height at the top axes — and where it may not be 0.
|
inlineconstexpr |
Engine ids, spelled out so call sites don't hard-code magic numbers.
|
inlineconstexpr |
CUSTOM is the third tabulated shape: geom1 IS a real dimension (max depth) but geom2 is an index into the shape-curve list, so only geom2 is excluded from inline editing — unlike IRREGULAR / STREET, where geom1 itself is the index and nothing is inline-editable.
|
inlineconstexpr |
IRREGULAR / STREET engine ids — for these, geom1 is an index into the transect / street list (not a length-like dimension), so it is managed only by the complex dialog's name picker, never as a raw inline number.
|
inlineconstexpr |
|
inlineconstexpr |