File indexing completed on 2024-04-28 05:31:45

0001 /*
0002     SPDX-FileCopyrightText: 2020 Arjen Hiemstra <ahiemstra@heimr.nl>
0003 
0004     SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #include "SensorQuery.h"
0008 
0009 #include <QCollator>
0010 #include <QDBusPendingCallWatcher>
0011 #include <QDBusReply>
0012 #include <QRegularExpression>
0013 
0014 #include "SensorDaemonInterface_p.h"
0015 #include "sensors_logging.h"
0016 
0017 using namespace KSysGuard;
0018 
0019 class SensorQuery::Private
0020 {
0021 public:
0022     enum class State { Initial, Running, Finished };
0023 
0024     void updateResult(const QDBusPendingReply<SensorInfoMap> &reply);
0025 
0026     QString path;
0027     State state = State::Initial;
0028     QList<QPair<QString, SensorInfo>> result;
0029 
0030     QDBusPendingCallWatcher *watcher = nullptr;
0031 };
0032 
0033 KSysGuard::SensorQuery::SensorQuery(const QString &path, QObject *parent)
0034     : QObject(parent)
0035     , d(std::make_unique<Private>())
0036 {
0037     d->path = path;
0038 }
0039 
0040 KSysGuard::SensorQuery::~SensorQuery()
0041 {
0042 }
0043 
0044 QString KSysGuard::SensorQuery::path() const
0045 {
0046     return d->path;
0047 }
0048 
0049 void KSysGuard::SensorQuery::setPath(const QString &path)
0050 {
0051     if (path == d->path) {
0052         return;
0053     }
0054 
0055     if (d->state != Private::State::Initial) {
0056         qCWarning(LIBKSYSGUARD_SENSORS) << "Cannot modify a running or finished query";
0057         return;
0058     }
0059 
0060     d->path = path;
0061 }
0062 
0063 bool KSysGuard::SensorQuery::execute()
0064 {
0065     if (d->state != Private::State::Initial) {
0066         return false;
0067     }
0068 
0069     d->state = Private::State::Running;
0070 
0071     auto watcher = SensorDaemonInterface::instance()->allSensors();
0072     d->watcher = watcher;
0073     connect(watcher, &QDBusPendingCallWatcher::finished, this, [watcher, this]() {
0074         watcher->deleteLater();
0075         d->watcher = nullptr;
0076         d->state = Private::State::Finished;
0077         d->updateResult(QDBusPendingReply<SensorInfoMap>(*watcher));
0078         Q_EMIT finished(this);
0079     });
0080 
0081     return true;
0082 }
0083 
0084 bool KSysGuard::SensorQuery::waitForFinished()
0085 {
0086     if (!d->watcher) {
0087         return false;
0088     }
0089 
0090     d->watcher->waitForFinished();
0091     return true;
0092 }
0093 
0094 QStringList KSysGuard::SensorQuery::sensorIds() const
0095 {
0096     QStringList ids;
0097     std::transform(d->result.cbegin(), d->result.cend(), std::back_inserter(ids), [](auto entry) {
0098         return entry.first;
0099     });
0100     return ids;
0101 }
0102 
0103 void KSysGuard::SensorQuery::sortByName()
0104 {
0105     QCollator collator;
0106     collator.setNumericMode(true);
0107     std::sort(d->result.begin(), d->result.end(), [this, &collator](const QPair<QString, SensorInfo> &left, const QPair<QString, SensorInfo> &right) {
0108         return collator.compare(left.second.name, right.second.name) < 0;
0109     });
0110 }
0111 
0112 QList<QPair<QString, SensorInfo>> KSysGuard::SensorQuery::result() const
0113 {
0114     return d->result;
0115 }
0116 
0117 void KSysGuard::SensorQuery::Private::updateResult(const QDBusPendingReply<SensorInfoMap> &reply)
0118 {
0119     if (path.isEmpty()) { // add everything
0120         const SensorInfoMap response = reply.value();
0121         for (auto it = response.constBegin(); it != response.constEnd(); it++) {
0122             result.append(qMakePair(it.key(), it.value()));
0123         }
0124         return;
0125     }
0126 
0127     auto regexp = QRegularExpression{QStringLiteral("^") % path % QStringLiteral("$")};
0128 
0129     const auto sensorIds = reply.value().keys();
0130     for (auto id : sensorIds) {
0131         if (id == path || regexp.match(id).hasMatch()) {
0132             result.append(qMakePair(id, reply.value().value(id)));
0133         }
0134     }
0135 }