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()) { if (opt.has_value()) {
auto proxy = opt.value(); auto proxy = opt.value();
m_connection = new DynamicReadableConnection<uint>{*proxy, data.points}; m_connection = new DynamicReadableConnection<uint>{*proxy, data};
startConnection(); startConnection();
m_value = QVariant(); m_value = QVariant();

View File

@ -17,12 +17,17 @@ using namespace fplus;
using namespace mpark::patterns; using namespace mpark::patterns;
using namespace TuxClocker::Device; using namespace TuxClocker::Device;
class DynamicReadableConnectionData { struct DynamicReadableConnectionData {
public:
// y = f(x) // y = f(x)
QVector<QPointF> points; QVector<QPointF> points;
// DBus path // DBus path
QString dynamicReadablePath; QString dynamicReadablePath;
RangeInfo rangeInfo;
};
enum class TargetType {
IntType,
DoubleType
}; };
Q_DECLARE_METATYPE(DynamicReadableConnectionData) Q_DECLARE_METATYPE(DynamicReadableConnectionData)
@ -32,9 +37,14 @@ Q_DECLARE_METATYPE(DynamicReadableConnectionData)
template <typename OutType> // Result of linear interpolation template <typename OutType> // Result of linear interpolation
class DynamicReadableConnection : public AssignableConnection { class DynamicReadableConnection : public AssignableConnection {
public: public:
DynamicReadableConnection( DynamicReadableConnection(DynamicReadableProxy &proxy, DynamicReadableConnectionData data,
DynamicReadableProxy &proxy, QVector<QPointF> points, QObject *parent = nullptr) QObject *parent = nullptr)
: AssignableConnection(parent), m_proxy(proxy), m_points(points) { : 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 sorted = sort_by(
[](auto point_l, auto point_r) { return point_l.x() < point_r.x(); }, m_points); [](auto point_l, auto point_r) { return point_l.x() < point_r.x(); }, m_points);
m_points = sorted; m_points = sorted;
@ -43,23 +53,42 @@ public:
virtual void start() override { virtual void start() override {
connect(&m_proxy, &DynamicReadableProxy::valueChanged, [this](auto val) { connect(&m_proxy, &DynamicReadableProxy::valueChanged, [this](auto val) {
match(val)(pattern(as<ReadableValue>(arg)) = [this](auto rv) { match(val)(pattern(as<ReadableValue>(arg)) = [this](auto rv) {
match(rv)(pattern(as<uint>(arg)) = [this](auto u) { match(rv)(
emitTargetValue(u); 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); } virtual void stop() override { disconnect(&m_proxy, nullptr, nullptr, nullptr); }
private: private:
TargetType m_targetType;
DynamicReadableProxy &m_proxy; DynamicReadableProxy &m_proxy;
QTimer m_timer; QTimer m_timer;
QVector<QPointF> m_points; QVector<QPointF> m_points;
template <typename T> void doEmit(T targetValue) { template <typename T> void doEmit(T targetValue, QString targetText) {
QDBusVariant arg{QVariant{targetValue}}; QDBusVariant arg{QVariant{targetValue}};
QVariant v; QVariant v;
v.setValue(arg); 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) { template <typename U> void emitTargetValue(U reading) {
@ -72,16 +101,19 @@ private:
break; break;
} }
} }
if (!leftIndex.has_value()) {
// Reading wasn't between points // Reading wasn't between points
if (reading > m_points.last().y()) { if (reading > m_points.last().y()) {
// Use y of rightmost point // Use y of rightmost point
doEmit((uint) qRound(m_points.last().y())); emitWithType(m_points.last().y());
return; return;
} else if (reading < m_points.last().y()) { } else if (reading < m_points.last().y()) {
// Leftmost // Leftmost
doEmit((uint) qRound(m_points.first().y())); emitWithType(m_points.last().y());
return; return;
} }
}
if (leftIndex == std::nullopt) { if (leftIndex == std::nullopt) {
qWarning("Couldn't calculate target value from reading %s!", 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 dx = m_points[li + 1].x() - m_points[li].x();
double dvx = reading - m_points[li].x(); double dvx = reading - m_points[li].x();
double p = dvx / dx; double p = dvx / dx;
OutType interp_y = lerp(m_points[li].y(), m_points[li + 1].y(), p); U interp_y = lerp(m_points[li].y(), m_points[li + 1].y(), p);
doEmit(interp_y);
emitWithType(interp_y);
} }
template <typename T> T lerp(T a, T b, double t) { return a + (t * (b - a)); } 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{ auto data = DynamicReadableConnectionData{
.points = points, .points = points,
.dynamicReadablePath = proxy->dbusPath(), .dynamicReadablePath = proxy->dbusPath(),
.rangeInfo = m_rangeInfo,
}; };
emit connectionDataChanged(data); emit connectionDataChanged(data);
this->close(); this->close();
@ -133,6 +134,7 @@ public:
[this](auto ir) { m_dragView->setRange(0, 100, ir.min, ir.max); }); [this](auto ir) { m_dragView->setRange(0, 100, ir.min, ir.max); });
m_applyButton->setToolTip(disabledReason()); m_applyButton->setToolTip(disabledReason());
m_rangeInfo = rangeInfo;
} }
void setAssignableName(QString name) { void setAssignableName(QString name) {
m_dependableLabel->setText(QString{"Connecting %1 with:"}.arg(name)); m_dependableLabel->setText(QString{"Connecting %1 with:"}.arg(name));
@ -147,6 +149,7 @@ signals:
private: private:
Q_OBJECT Q_OBJECT
RangeInfo m_rangeInfo;
DeviceModel &m_model; DeviceModel &m_model;
DeviceProxyModel m_proxyModel; DeviceProxyModel m_proxyModel;
DragChartView *m_dragView; DragChartView *m_dragView;