Files
MARTe-Integrated-Components/Client/streamhub-qt/Model.h
T
2026-06-26 09:11:10 +02:00

121 lines
3.9 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* @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 */