qt: display unit and current value in Assignables

This commit is contained in:
Jussi Kuokkanen 2022-04-25 19:40:15 +03:00
parent 3aedbf474b
commit 7268ef989e
5 changed files with 106 additions and 8 deletions

View File

@ -8,7 +8,8 @@ namespace TC = TuxClocker;
class AssignableItemData {
public:
AssignableItemData() {m_enabled = false;}
AssignableItemData(TC::Device::AssignableInfo info) : m_info(info) {
AssignableItemData(TC::Device::AssignableInfo info, std::optional<QString> unit) : m_info(info) {
m_unit = unit;
m_enabled = false;
}
TC::Device::AssignableInfo assignableInfo() {return m_info;}
@ -17,8 +18,10 @@ public:
void setCommittal(bool on) {m_enabled = on;}
void setValue(QVariant v) {m_targetValue = v;}
QVariant value() {return m_targetValue;}
std::optional<QString> unit() {return m_unit;}
private:
bool m_enabled;
TC::Device::AssignableInfo m_info;
std::optional<QString> m_unit;
QVariant m_targetValue;
};

View File

@ -10,10 +10,14 @@ namespace TCD = TuxClocker::DBus;
using namespace TuxClocker::Device;
Q_DECLARE_METATYPE(TCD::Result<int>)
Q_DECLARE_METATYPE(TCD::Result<QString>)
Q_DECLARE_METATYPE(TCD::Result<QDBusVariant>)
AssignableProxy::AssignableProxy(QString path, QDBusConnection conn,
QObject *parent) : QObject(parent) {
qDBusRegisterMetaType<TCD::Result<int>>();
qDBusRegisterMetaType<TCD::Result<QString>>();
qDBusRegisterMetaType<TCD::Result<QDBusVariant>>();
m_iface = new QDBusInterface("org.tuxclocker",
path, "org.tuxclocker.Assignable", conn, this);
}
@ -58,3 +62,31 @@ void AssignableProxy::startConnection(std::shared_ptr<AssignableConnection> conn
emit connectionStarted();
m_assignableConnection->start();
}
// DBus type to the more precise C++ type
std::optional<AssignmentArgument> toAssignmentArgument(TCD::Result<QDBusVariant> res) {
if (res.error)
return std::nullopt;
auto type = static_cast<QMetaType::Type>(res.value.variant().type());
auto v = res.value.variant();
switch (type) {
case QMetaType::Int:
return v.value<int>();
case QMetaType::UInt:
return v.value<uint>();
case QMetaType::Double:
return v.value<double>();
default:
return std::nullopt;
}
}
std::optional<AssignmentArgument> AssignableProxy::currentValue() {
QDBusReply<TCD::Result<QDBusVariant>> reply = m_iface->call("currentValue");
if (!reply.isValid())
return std::nullopt;
return toAssignmentArgument(reply.value());
}

View File

@ -22,6 +22,7 @@ public:
// Stop connection and clear current connection
void stopConnection();
void setValue(QVariant v) {m_value = v;}
std::optional<TC::Device::AssignmentArgument> currentValue();
signals:
void applied(std::optional<TC::Device::AssignmentError>);
void connectionValueChanged(std::variant<QVariant, TC::Device::AssignmentError>,

View File

@ -2,8 +2,6 @@
#include "AssignableProxy.hpp"
#include "DynamicReadableProxy.hpp"
#include "qnamespace.h"
#include "qstandarditemmodel.h"
#include <fplus/fplus.hpp>
#include <QApplication>
#include <QDBusReply>
@ -23,12 +21,15 @@ Q_DECLARE_METATYPE(DynamicReadableProxy*)
Q_DECLARE_METATYPE(TCDBus::Enumeration)
Q_DECLARE_METATYPE(TCDBus::Range)
Q_DECLARE_METATYPE(EnumerationVec)
Q_DECLARE_METATYPE(TCDBus::Result<QString>)
DeviceModel::DeviceModel(TC::TreeNode<TCDBus::DeviceNode> root, QObject *parent) :
QStandardItemModel(parent) {
qDBusRegisterMetaType<TCDBus::Enumeration>();
qDBusRegisterMetaType<QVector<TCDBus::Enumeration>>();
qDBusRegisterMetaType<TCDBus::Range>();
qDBusRegisterMetaType<TCDBus::Result<QString>>();
/* Data storage:
- Interface column should store assignable info for editors
- Name colums should store the interface type for filtering
@ -107,6 +108,15 @@ std::optional<const AssignableProxy*>
std::nullopt;
}
QString fromAssignmentArgument(AssignmentArgument a_arg) {
return p::match(a_arg) (
pattern(as<int>(arg)) = [](auto i) {return QString::number(i);},
pattern(as<uint>(arg)) = [](auto u) {return QString::number(u);},
pattern(as<double>(arg)) = [](auto d) {return QString::number(d);},
pattern(_) = [] {return QString("");}
);
}
QStandardItem *DeviceModel::createAssignable(TC::TreeNode<TCDBus::DeviceNode> node,
QDBusConnection conn, AssignableItemData itemData) {
auto ifaceItem = new AssignableItem(this);
@ -132,8 +142,41 @@ QStandardItem *DeviceModel::createAssignable(TC::TreeNode<TCDBus::DeviceNode> no
QVariant v;
v.setValue(itemData);
ifaceItem->setData(v, AssignableRole);
ifaceItem->setText("No value set");
// Set initial text to current value (one-time at startup)
QString text("No value set");
auto unit = itemData.unit();
auto currentValue = proxy->currentValue();
if (currentValue.has_value()) {
p::match(itemData.assignableInfo()) (
pattern(as<EnumerationVec>(arg)) = [&](auto e_vec) {
/* Find index from EnumVec (O(n) doesn't matter since we only search once here)
This should never be anything other than an uint but in theory it could be
whatever at this point */
try {
auto index = std::get<uint>(currentValue.value());
for (auto &e : e_vec) {
if (index == e.key) {
text = QString::fromStdString(e.name);
break;
}
}
} catch (std::bad_variant_access &e) {}
//text = QString::fromStdString(e_vec[std::get<uint>(currentValue.value())].name);
},
pattern(as<RangeInfo>(_)) = [&]() {
auto base = fromAssignmentArgument(currentValue.value());
if (unit.has_value())
text = QString("%1 %2").arg(base, unit.value());
else
text = base;
}
);
}
ifaceItem->setText(text);
connect(ifaceItem, &AssignableItem::assignableDataChanged,
[=](QVariant v) {
// Only show checkbox when value has been changed
@ -199,6 +242,12 @@ QVariant DeviceModel::data(const QModelIndex &index, int role) const {
return QStandardItemModel::data(index, role);
}
std::optional<QString> fromDBusResult(TCDBus::Result<QString> res) {
if (res.error)
return std::nullopt;
return res.value;
}
std::optional<QStandardItem*> DeviceModel::setupAssignable(
TC::TreeNode<TCDBus::DeviceNode> node, QDBusConnection conn) {
QDBusInterface ifaceNode("org.tuxclocker", node.value().path,
@ -207,6 +256,13 @@ std::optional<QStandardItem*> DeviceModel::setupAssignable(
auto a_info =
qvariant_cast<QDBusVariant>(ifaceNode.property("assignableInfo"))
.variant();
// Get unit of Assignable
auto dbusUnit = qvariant_cast<TCDBus::Result<QString>>(ifaceNode.property("unit"));
auto unit = fromDBusResult(dbusUnit);
// Get initial value
/* TODO: bad hack: this code can only differentiate between
arrays and structs: make it based on signature instead */
auto d_arg = qvariant_cast<QDBusArgument>(a_info);
@ -214,13 +270,13 @@ std::optional<QStandardItem*> DeviceModel::setupAssignable(
case QDBusArgument::StructureType: {
TCDBus::Range r;
d_arg >> r;
AssignableItemData data(r.toAssignableInfo());
AssignableItemData data(r.toAssignableInfo(), unit);
return createAssignable(node, conn, data);
}
case QDBusArgument::ArrayType: {
QVector<TCDBus::Enumeration> e;
d_arg >> e;
AssignableItemData data(toEnumVec(e));
AssignableItemData data(toEnumVec(e), unit);
return createAssignable(node, conn, data);
}
default:

View File

@ -60,7 +60,13 @@ void DeviceModelDelegate::setModelData(QWidget *editor,
data.setValue(a_editor->assignableData());
QVariant v;
v.setValue(data);
model->setData(index, a_editor->displayData(), Qt::DisplayRole);
// TODO: add unit
auto text = (data.unit().has_value()) ?
QString("%1 %2").arg(a_editor->displayData(), data.unit().value()) :
a_editor->displayData();
model->setData(index, text, Qt::DisplayRole);
model->setData(index, v, DeviceModel::AssignableRole);
}
}