parametrize correctly with all types

This commit is contained in:
Jussi Kuokkanen 2023-09-07 18:45:16 +03:00
parent 5dbcc23323
commit f9a660afee
3 changed files with 58 additions and 22 deletions

View File

@ -82,7 +82,7 @@ void AssignableProxy::apply() {
if (opt.has_value()) {
auto proxy = opt.value();
m_connection = new DynamicReadableConnection<uint>{*proxy, data.points};
m_connection = new DynamicReadableConnection<uint>{*proxy, data};
startConnection();
m_value = QVariant();

View File

@ -17,12 +17,17 @@ using namespace fplus;
using namespace mpark::patterns;
using namespace TuxClocker::Device;
class DynamicReadableConnectionData {
public:
struct DynamicReadableConnectionData {
// y = f(x)
QVector<QPointF> points;
// DBus path
QString dynamicReadablePath;
RangeInfo rangeInfo;
};
enum class TargetType {
IntType,
DoubleType
};
Q_DECLARE_METATYPE(DynamicReadableConnectionData)
@ -32,9 +37,14 @@ Q_DECLARE_METATYPE(DynamicReadableConnectionData)
template <typename OutType> // Result of linear interpolation
class DynamicReadableConnection : public AssignableConnection {
public:
DynamicReadableConnection(
DynamicReadableProxy &proxy, QVector<QPointF> points, QObject *parent = nullptr)
: AssignableConnection(parent), m_proxy(proxy), m_points(points) {
DynamicReadableConnection(DynamicReadableProxy &proxy, DynamicReadableConnectionData data,
QObject *parent = nullptr)
: AssignableConnection(parent), m_proxy(proxy), m_points(data.points) {
if (std::holds_alternative<Range<int>>(data.rangeInfo))
m_targetType = TargetType::IntType;
else
m_targetType = TargetType::DoubleType;
auto sorted = sort_by(
[](auto point_l, auto point_r) { return point_l.x() < point_r.x(); }, m_points);
m_points = sorted;
@ -43,23 +53,42 @@ public:
virtual void start() override {
connect(&m_proxy, &DynamicReadableProxy::valueChanged, [this](auto val) {
match(val)(pattern(as<ReadableValue>(arg)) = [this](auto rv) {
match(rv)(pattern(as<uint>(arg)) = [this](auto u) {
emitTargetValue(u);
});
match(rv)(
pattern(as<uint>(arg)) = [this](auto u) { emitTargetValue(u); },
pattern(as<int>(arg)) = [this](int i) { emitTargetValue(i); },
pattern(as<double>(arg)) = [this](
auto d) { emitTargetValue(d); });
});
});
}
virtual void stop() override { disconnect(&m_proxy, nullptr, nullptr, nullptr); }
private:
TargetType m_targetType;
DynamicReadableProxy &m_proxy;
QTimer m_timer;
QVector<QPointF> m_points;
template <typename T> void doEmit(T targetValue) {
template <typename T> void doEmit(T targetValue, QString targetText) {
QDBusVariant arg{QVariant{targetValue}};
QVariant v;
v.setValue(arg);
emit targetValueChanged(v, QString::number(targetValue));
emit targetValueChanged(v, targetText);
}
template <typename T> void emitWithType(T value) {
switch (m_targetType) {
case TargetType::IntType: {
int target = static_cast<int>(value);
doEmit(target, QString::number(target));
return;
}
case TargetType::DoubleType: {
auto target = static_cast<double>(value);
// TODO: don't hardcode precision in different places
doEmit(target, QString::number(target, 'f', 2));
return;
}
}
}
template <typename U> void emitTargetValue(U reading) {
@ -72,16 +101,19 @@ private:
break;
}
}
if (!leftIndex.has_value()) {
// Reading wasn't between points
if (reading > m_points.last().y()) {
// Use y of rightmost point
doEmit((uint) qRound(m_points.last().y()));
emitWithType(m_points.last().y());
return;
} else if (reading < m_points.last().y()) {
// Leftmost
doEmit((uint) qRound(m_points.first().y()));
emitWithType(m_points.last().y());
return;
}
}
if (leftIndex == std::nullopt) {
qWarning("Couldn't calculate target value from reading %s!",
@ -93,8 +125,9 @@ private:
double dx = m_points[li + 1].x() - m_points[li].x();
double dvx = reading - m_points[li].x();
double p = dvx / dx;
OutType interp_y = lerp(m_points[li].y(), m_points[li + 1].y(), p);
doEmit(interp_y);
U interp_y = lerp(m_points[li].y(), m_points[li + 1].y(), p);
emitWithType(interp_y);
}
template <typename T> T lerp(T a, T b, double t) { return a + (t * (b - a)); }

View File

@ -100,6 +100,7 @@ public:
auto data = DynamicReadableConnectionData{
.points = points,
.dynamicReadablePath = proxy->dbusPath(),
.rangeInfo = m_rangeInfo,
};
emit connectionDataChanged(data);
this->close();
@ -133,6 +134,7 @@ public:
[this](auto ir) { m_dragView->setRange(0, 100, ir.min, ir.max); });
m_applyButton->setToolTip(disabledReason());
m_rangeInfo = rangeInfo;
}
void setAssignableName(QString name) {
m_dependableLabel->setText(QString{"Connecting %1 with:"}.arg(name));
@ -147,6 +149,7 @@ signals:
private:
Q_OBJECT
RangeInfo m_rangeInfo;
DeviceModel &m_model;
DeviceProxyModel m_proxyModel;
DragChartView *m_dragView;