Commit eda127cb authored by Arjen Hiemstra's avatar Arjen Hiemstra
Browse files

Keep track of and expose sensors that fail to resolve

Rather than silently discarding them, keep track of which configured
sensors fail to produce any actual sensors and expose these as a new
property "missingSensors".

This moves the code to resolve sensors into a new "SensorResolver"
struct that keeps the relevant state, which previously lived only in the
function body, for improved encapsulation.
parent 8a463c40
......@@ -126,6 +126,39 @@ QHash<int, QByteArray> PresetsModel::roleNames() const
return roles;
}
SensorResolver::SensorResolver(SensorFaceController *_controller, const QJsonArray &_expected)
: controller(_controller)
, expected(_expected)
{
}
void SensorResolver::execute()
{
std::transform(expected.begin(), expected.end(), std::back_inserter(queries), [this](const QJsonValue &entry) {
auto query = new SensorQuery{entry.toString()};
query->connect(query, &KSysGuard::SensorQuery::finished, controller, [this](SensorQuery *query) {
query->sortByName();
query->deleteLater();
const auto ids = query->sensorIds();
if (ids.isEmpty()) {
missing.append(query->path());
} else {
std::transform(ids.begin(), ids.end(), std::back_inserter(found), [](const QString &id) {
return id;
});
}
queries.removeOne(query);
if (queries.isEmpty()) {
callback(this);
}
});
query->execute();
return query;
});
}
QVector<QPair<QRegularExpression, QString>> KSysGuard::SensorFaceControllerPrivate::sensorIdReplacements;
QRegularExpression SensorFaceControllerPrivate::oldDiskSensor = QRegularExpression(QStringLiteral("^disk\\/(.+)_\\(\\d+:\\d+\\)"));
QRegularExpression SensorFaceControllerPrivate::oldPartitionSensor = QRegularExpression(QStringLiteral("^partitions(\\/.+)\\/"));
......@@ -248,31 +281,22 @@ QJsonArray SensorFaceControllerPrivate::readAndUpdateSensors(KConfigGroup &confi
return newSensors;
}
void SensorFaceControllerPrivate::resolveSensors(const QJsonArray &partialEntries, std::function<void(const QJsonArray &)> callback)
void SensorFaceControllerPrivate::resolveSensors(const QJsonArray &partialEntries, std::function<void(SensorResolver *)> callback)
{
if (partialEntries.isEmpty()) {
callback(partialEntries);
return;
}
auto resolver = new SensorResolver{q, partialEntries};
resolver->callback = [this, callback](SensorResolver *resolver) {
callback(resolver);
auto sensors = std::make_shared<QJsonArray>();
for (const auto &id : partialEntries) {
auto query = new KSysGuard::SensorQuery{id.toString()};
query->connect(query, &KSysGuard::SensorQuery::finished, q, [this, query, sensors, callback] {
query->sortByName();
const auto ids = query->sensorIds();
delete query;
std::transform(ids.begin(), ids.end(), std::back_inserter(*sensors), [](const QString &id) {
return QJsonValue(id);
});
if (sensors.use_count() == 1) {
// We are the last query
callback(*sensors);
if (!resolver->missing.isEmpty()) {
for (const auto &entry : std::as_const(resolver->missing)) {
missingSensors.append(entry);
}
});
query->execute();
}
Q_EMIT q->missingSensorsChanged();
}
delete resolver;
};
resolver->execute();
}
SensorFace *SensorFaceControllerPrivate::createGui(const QString &qmlPath)
......@@ -359,16 +383,16 @@ SensorFaceController::SensorFaceController(KConfigGroup &config, QQmlEngine *eng
d->contextObj = new KLocalizedContext(this);
d->resolveSensors(d->readAndUpdateSensors(d->sensorsGroup, QStringLiteral("totalSensors")), [this](const QJsonArray &resolvedSensors) {
d->totalSensors = resolvedSensors;
d->resolveSensors(d->readAndUpdateSensors(d->sensorsGroup, QStringLiteral("totalSensors")), [this](SensorResolver *resolver) {
d->totalSensors = resolver->found;
Q_EMIT totalSensorsChanged();
});
d->resolveSensors(d->readAndUpdateSensors(d->sensorsGroup, QStringLiteral("lowPrioritySensorIds")), [this](const QJsonArray &resolvedSensors) {
d->lowPrioritySensorIds = resolvedSensors;
d->resolveSensors(d->readAndUpdateSensors(d->sensorsGroup, QStringLiteral("lowPrioritySensorIds")), [this](SensorResolver *resolver) {
d->lowPrioritySensorIds = resolver->found;
Q_EMIT lowPrioritySensorIdsChanged();
});
d->resolveSensors(d->readAndUpdateSensors(d->sensorsGroup, QStringLiteral("highPrioritySensorIds")), [this](const QJsonArray &resolvedSensors) {
d->highPrioritySensorIds = resolvedSensors;
d->resolveSensors(d->readAndUpdateSensors(d->sensorsGroup, QStringLiteral("highPrioritySensorIds")), [this](SensorResolver *resolver) {
d->highPrioritySensorIds = resolver->found;
Q_EMIT highPrioritySensorIdsChanged();
});
......@@ -459,11 +483,11 @@ void SensorFaceController::setTotalSensors(const QJsonArray &totalSensors)
d->totalSensors = totalSensors;
d->syncTimer->start();
Q_EMIT totalSensorsChanged();
d->resolveSensors(totalSensors, [this](const QJsonArray &resolvedSensors) {
if (resolvedSensors == d->totalSensors) {
d->resolveSensors(totalSensors, [this](SensorResolver *resolver) {
if (resolver->found == d->totalSensors) {
return;
}
d->totalSensors = resolvedSensors;
d->totalSensors = resolver->found;
Q_EMIT totalSensorsChanged();
});
}
......@@ -487,15 +511,20 @@ void SensorFaceController::setHighPrioritySensorIds(const QJsonArray &highPriori
d->syncTimer->start();
d->highPrioritySensorIds = highPrioritySensorIds;
Q_EMIT highPrioritySensorIdsChanged();
d->resolveSensors(highPrioritySensorIds, [this](const QJsonArray &resolvedSensors) {
if (resolvedSensors == d->highPrioritySensorIds) {
d->resolveSensors(highPrioritySensorIds, [this](SensorResolver *resolver) {
if (resolver->found == d->highPrioritySensorIds) {
return;
}
d->highPrioritySensorIds = resolvedSensors;
d->highPrioritySensorIds = resolver->found;
Q_EMIT highPrioritySensorIdsChanged();
});
}
QJsonArray KSysGuard::SensorFaceController::missingSensors() const
{
return d->missingSensors;
}
QVariantMap SensorFaceController::sensorColors() const
{
QVariantMap colors;
......@@ -575,11 +604,11 @@ void SensorFaceController::setLowPrioritySensorIds(const QJsonArray &lowPriority
d->lowPrioritySensorIds = lowPrioritySensorIds;
d->syncTimer->start();
Q_EMIT lowPrioritySensorIdsChanged();
d->resolveSensors(lowPrioritySensorIds, [this](const QJsonArray &resolvedSensors) {
if (resolvedSensors == d->lowPrioritySensorIds) {
d->resolveSensors(lowPrioritySensorIds, [this](SensorResolver *resolver) {
if (resolver->found == d->lowPrioritySensorIds) {
return;
}
d->lowPrioritySensorIds = resolvedSensors;
d->lowPrioritySensorIds = resolver->found;
Q_EMIT lowPrioritySensorIdsChanged();
});
}
......@@ -791,16 +820,19 @@ void SensorFaceController::reloadConfig()
d->faceConfigLoader->load();
}
d->resolveSensors(d->readAndUpdateSensors(d->sensorsGroup, QStringLiteral("totalSensors")), [this](const QJsonArray &resolvedSensors) {
d->totalSensors = resolvedSensors;
d->missingSensors = QJsonArray{};
Q_EMIT missingSensorsChanged();
d->resolveSensors(d->readAndUpdateSensors(d->sensorsGroup, QStringLiteral("totalSensors")), [this](SensorResolver *resolver) {
d->totalSensors = resolver->found;
Q_EMIT totalSensorsChanged();
});
d->resolveSensors(d->readAndUpdateSensors(d->sensorsGroup, QStringLiteral("lowPrioritySensorIds")), [this](const QJsonArray &resolvedSensors) {
d->lowPrioritySensorIds = resolvedSensors;
d->resolveSensors(d->readAndUpdateSensors(d->sensorsGroup, QStringLiteral("lowPrioritySensorIds")), [this](SensorResolver *resolver) {
d->lowPrioritySensorIds = resolver->found;
Q_EMIT lowPrioritySensorIdsChanged();
});
d->resolveSensors(d->readAndUpdateSensors(d->sensorsGroup, QStringLiteral("highPrioritySensorIds")), [this](const QJsonArray &resolvedSensors) {
d->highPrioritySensorIds = resolvedSensors;
d->resolveSensors(d->readAndUpdateSensors(d->sensorsGroup, QStringLiteral("highPrioritySensorIds")), [this](SensorResolver *resolver) {
d->highPrioritySensorIds = resolver->found;
Q_EMIT highPrioritySensorIdsChanged();
});
......
......@@ -156,6 +156,10 @@ class SENSORFACES_EXPORT SensorFaceController : public QObject
* The minimum time that needs to elapse, in milliseconds, between updates of the face.
*/
Q_PROPERTY(int updateRateLimit READ updateRateLimit WRITE setUpdateRateLimit NOTIFY updateRateLimitChanged)
/**
* Contains the paths of missing sensors, if there are any.
*/
Q_PROPERTY(QJsonArray missingSensors READ missingSensors NOTIFY missingSensorsChanged)
public:
/**
......@@ -206,6 +210,8 @@ public:
QJsonArray lowPrioritySensorIds() const;
void setLowPrioritySensorIds(const QJsonArray &ids);
QJsonArray missingSensors() const;
QVariantMap sensorColors() const;
void setSensorColors(const QVariantMap &colors);
......@@ -280,6 +286,7 @@ Q_SIGNALS:
void sensorLabelsChanged();
void updateRateLimitChanged();
void faceConfigurationChanged();
void missingSensorsChanged();
private:
const std::unique_ptr<SensorFaceControllerPrivate> d;
......
......@@ -25,6 +25,7 @@ namespace KSysGuard
{
class SensorFaceController;
class SensorFace;
class SensorQuery;
class FacesModel : public QStandardItemModel
{
......@@ -59,6 +60,21 @@ public:
QHash<int, QByteArray> roleNames() const override;
};
struct SensorResolver {
SensorResolver(SensorFaceController *_controller, const QJsonArray &_expected);
void execute();
SensorFaceController *controller = nullptr;
QJsonArray expected;
QJsonArray found;
QJsonArray missing;
QVector<SensorQuery *> queries;
std::function<void(SensorResolver *)> callback;
};
// This is exported so we can use it in autotests
class SENSORFACES_EXPORT SensorFaceControllerPrivate
{
......@@ -69,7 +85,7 @@ public:
QJsonArray readAndUpdateSensors(KConfigGroup &config, const QString &entryName);
QString replaceDiskId(const QString &entryname) const;
QString replacePartitionId(const QString &entryname) const;
void resolveSensors(const QJsonArray &partialEntries, std::function<void(const QJsonArray &)> callback);
void resolveSensors(const QJsonArray &partialEntries, std::function<void(SensorResolver *)>);
SensorFace *createGui(const QString &qmlPath);
QQuickItem *createConfigUi(const QString &file, const QVariantMap &initialProperties);
......@@ -99,6 +115,7 @@ public:
QJsonArray totalSensors;
QJsonArray highPrioritySensorIds;
QJsonArray lowPrioritySensorIds;
QJsonArray missingSensors;
QTimer *syncTimer;
bool shouldSync = true;
......
......@@ -54,7 +54,7 @@ public:
*/
bool waitForFinished();
Q_SIGNAL void finished(const SensorQuery *query);
Q_SIGNAL void finished(SensorQuery *query);
private:
friend class Sensor;
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment