Implemented qt port + e2e

This commit is contained in:
Martino Ferrari
2026-06-26 09:11:10 +02:00
parent 0d7d8f396b
commit 4702d0a217
146 changed files with 57272 additions and 128 deletions
+120
View File
@@ -0,0 +1,120 @@
/**
* @file Model.h
* @brief Domain types for the Qt StreamHub client.
*
* Mirrors the ImGui client's App.h domain model, but uses QColor instead of
* ImVec4 and adds no Qt widget dependencies (pure data).
*/
#pragma once
#include "Protocol.h" // SignalMeta, SourceStats (reused, framework-free)
#include "SignalBuffer.h" // SignalBuffer, LTTBDecimate (reused)
#include <QColor>
#include <string>
#include <vector>
#include <cstdint>
namespace shq {
using StreamHubClient::SignalMeta;
using StreamHubClient::SourceStats;
using StreamHubClient::SignalBuffer;
/** One signal as known to the client. */
struct SignalView {
SignalMeta meta;
SignalBuffer buf{1000000};
QColor color{137, 180, 250}; /* Catppuccin blue */
double lineWidth = 1.5;
int marker = -1; /* -1 = none, else MarkerStyle index */
bool visible = true;
};
/** One connected UDPStreamer source. */
struct Source {
std::string id;
std::string label;
std::string addr;
std::string state = "disconnected";
uint32_t port = 0;
bool configured = false;
int publishMode = 0;
std::vector<SignalView> signals;
SourceStats stats;
};
/** Trigger configuration + live state (hub-side trigger semantics). */
struct TriggerCfgState {
/* Config (sent to hub via setTrigger) */
std::string signalKey; /* full key "src:sig" or "src:sig[i]" */
int edge = 0; /* 0=rising 1=falling 2=both */
double threshold = 0.0;
double windowSec = 0.1; /* 100 µs .. 10 s */
double prePercent = 20.0;
bool single = false; /* false=normal true=single */
/* Live (driven by hub triggerState broadcasts) */
std::string status = "idle"; /* idle|armed|collecting|triggered */
bool stopped = false;
bool hasTrigTime = false;
double trigTime = 0.0;
};
/** Per-signal vertical scale state (oscilloscope style). */
struct VScale {
int mode = 0; /* 0=auto 1=range 2=manual */
double divValue = 1.0; /* units per division (manual) */
double offset = 0.0; /* raw value at center (manual) */
double screenPos = 0.0; /* position offset in divisions from center */
bool digitalInMixed = false;
/* Resolved each frame: */
double resolvedDiv = 1.0;
double resolvedOffset = 0.0;
};
/** Assignment of one signal to a plot panel. */
struct PlotAssignment {
int sourceIdx = -1;
int signalIdx = -1;
VScale vs;
};
/*---------------------------------------------------------------------------*/
/* Plot layouts (mirror the web UI: cols×rows) */
/*---------------------------------------------------------------------------*/
enum class PlotLayout {
k1x1 = 0, k2x1, k1x2, k3x1, k1x3, k2x2, k4x1, k1x4, kCount
};
inline const char* const* layoutNames() {
static const char* const names[] = {
"1\u00d71", "2\u00d71", "1\u00d72", "3\u00d71",
"1\u00d73", "2\u00d72", "4\u00d71", "1\u00d74"
};
return names;
}
inline void layoutDims(PlotLayout l, int& cols, int& rows) {
switch (l) {
case PlotLayout::k1x1: cols = 1; rows = 1; break;
case PlotLayout::k2x1: cols = 2; rows = 1; break;
case PlotLayout::k1x2: cols = 1; rows = 2; break;
case PlotLayout::k3x1: cols = 3; rows = 1; break;
case PlotLayout::k1x3: cols = 1; rows = 3; break;
case PlotLayout::k2x2: cols = 2; rows = 2; break;
case PlotLayout::k4x1: cols = 4; rows = 1; break;
case PlotLayout::k1x4: cols = 1; rows = 4; break;
default: cols = 1; rows = 1; break;
}
}
inline int layoutSlots(PlotLayout l) {
int c, r; layoutDims(l, c, r); return c * r;
}
static const int kMaxPlotSlots = 8;
} /* namespace shq */