From 95bfd31194eadd58caa048d1929fc9a483ab44f6 Mon Sep 17 00:00:00 2001 From: Chris Adams Date: Fri, 17 Feb 2017 12:05:30 +1000 Subject: [PATCH] [nemo-qml-plugin-systemsettings] Provide BatteryStatus type. Contributes to JB#37501 This commit adds the BatteryStatus type to the system settings plugin and development library, which allows it to be utilised by other areas of the system (e.g., MDM library can use it to determine if the battery has enough charge to perform an OS update). Contributes to JB#37501 --- src/batterystatus.cpp | 247 ++++++++++++++++++++++++++++++++++++++++++ src/batterystatus.h | 86 +++++++++++++++ src/batterystatus_p.h | 71 ++++++++++++ src/plugin/plugin.cpp | 2 + src/src.pro | 5 +- systemsettings.pro | 2 + 6 files changed, 412 insertions(+), 1 deletion(-) create mode 100644 src/batterystatus.cpp create mode 100644 src/batterystatus.h create mode 100644 src/batterystatus_p.h diff --git a/src/batterystatus.cpp b/src/batterystatus.cpp new file mode 100644 index 0000000..755a35d --- /dev/null +++ b/src/batterystatus.cpp @@ -0,0 +1,247 @@ +/* + * Copyright (C) 2017 Jolla Ltd. + * Contact: Raine Makelainen + * + * You may use this file under the terms of the BSD license as follows: + * + * "Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Nemo Mobile nor the names of its contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." + */ + +#include "batterystatus.h" +#include "batterystatus_p.h" + +#include +#include +#include +#include +#include + +#include +#include + +QDBusPendingCallWatcher *getMceRequestCallWatcher(const QString &method) +{ + QDBusInterface mceInterface(MCE_SERVICE, + MCE_REQUEST_PATH, + MCE_REQUEST_IF, + QDBusConnection::systemBus()); + QDBusPendingCall pendingModemsRequest = mceInterface.asyncCall(method); + return new QDBusPendingCallWatcher(pendingModemsRequest); +} + +BatteryStatusPrivate::BatteryStatusPrivate(BatteryStatus *batteryInfo) + : QObject(batteryInfo) + , q(batteryInfo) + , status(BatteryStatus::BatteryStatusUnknown) + , chargerStatus(BatteryStatus::ChargerStatusUnknown) + , chargePercentage(-1) +{ + QDBusServiceWatcher *mceWatcher = new QDBusServiceWatcher(MCE_SERVICE, QDBusConnection::systemBus(), + QDBusServiceWatcher::WatchForOwnerChange, this); + + connect(mceWatcher, &QDBusServiceWatcher::serviceRegistered, + this, &BatteryStatusPrivate::mceRegistered); + connect(mceWatcher, &QDBusServiceWatcher::serviceUnregistered, + this, &BatteryStatusPrivate::mceUnregistered); + + registerSignals(); + + QDBusPendingCallWatcher *chargerState = getMceRequestCallWatcher(MCE_CHARGER_STATE_GET); + QObject::connect(chargerState, &QDBusPendingCallWatcher::finished, + this, &BatteryStatusPrivate::initialChargerState); + + QDBusPendingCallWatcher *batteryStatus = getMceRequestCallWatcher(MCE_BATTERY_STATUS_GET); + QObject::connect(batteryStatus, &QDBusPendingCallWatcher::finished, + this, &BatteryStatusPrivate::initialBatteryStatus); + + QDBusPendingCallWatcher *batteryLevel = getMceRequestCallWatcher(MCE_BATTERY_LEVEL_GET); + QObject::connect(batteryLevel, &QDBusPendingCallWatcher::finished, + this, &BatteryStatusPrivate::initialChargePercentage); +} + +BatteryStatusPrivate::~BatteryStatusPrivate() +{ +} + +void BatteryStatusPrivate::registerSignals() +{ + QDBusConnection systemBus = QDBusConnection::systemBus(); + systemBus.connect(MCE_SERVICE, MCE_SIGNAL_PATH, + MCE_SIGNAL_IF, MCE_CHARGER_STATE_SIG, + this, SLOT(chargerStatusChanged(QString))); + systemBus.connect(MCE_SERVICE, MCE_SIGNAL_PATH, + MCE_SIGNAL_IF, MCE_BATTERY_STATUS_SIG, + this, SLOT(statusChanged(QString))); + systemBus.connect(MCE_SERVICE, MCE_SIGNAL_PATH, + MCE_SIGNAL_IF, MCE_BATTERY_LEVEL_SIG, + this, SLOT(chargePercentageChanged(int))); +} + +BatteryStatus::ChargerStatus BatteryStatusPrivate::parseChargerStatus(const QString &state) +{ + if (state == QLatin1String(MCE_CHARGER_STATE_ON)) { + return BatteryStatus::Connected; + } else if (state == QLatin1String(MCE_CHARGER_STATE_OFF)){ + return BatteryStatus::Disconnected; + } + + return BatteryStatus::ChargerStatusUnknown; +} + +BatteryStatus::Status BatteryStatusPrivate::parseBatteryStatus(const QString &status) +{ + if (status == QLatin1String(MCE_BATTERY_STATUS_LOW)) { + return BatteryStatus::Low; + } else if (status == QLatin1String(MCE_BATTERY_STATUS_OK)) { + return BatteryStatus::Normal; + } else if (status == QLatin1String(MCE_BATTERY_STATUS_EMPTY)) { + return BatteryStatus::Empty; + } else if (status == QLatin1String(MCE_BATTERY_STATUS_FULL)) { + return BatteryStatus::Full; + } + + return BatteryStatus::BatteryStatusUnknown; +} + +void BatteryStatusPrivate::mceRegistered() +{ + registerSignals(); +} + +void BatteryStatusPrivate::mceUnregistered() +{ + chargerStatusChanged(QLatin1String(MCE_CHARGER_STATE_UNKNOWN)); + statusChanged(QLatin1String(MCE_BATTERY_STATUS_UNKNOWN)); + chargePercentageChanged(-1); +} + +void BatteryStatusPrivate::chargerStatusChanged(const QString &status) +{ + BatteryStatus::ChargerStatus newStatus = parseChargerStatus(status); + if (newStatus != chargerStatus) { + chargerStatus = newStatus; + emit q->chargerStatusChanged(chargerStatus); + } +} + +void BatteryStatusPrivate::statusChanged(const QString &s) +{ + BatteryStatus::Status newStatus = parseBatteryStatus(s); + if (newStatus != status) { + status = newStatus; + emit q->statusChanged(status); + } +} + +void BatteryStatusPrivate::chargePercentageChanged(int percentage) +{ + if (percentage != chargePercentage) { + chargePercentage = percentage; + emit q->chargePercentageChanged(chargePercentage); + } +} + +void BatteryStatusPrivate::initialChargerState(QDBusPendingCallWatcher *watcher) +{ + if (watcher->isError() && (watcher->error().type() == QDBusError::ServiceUnknown)) { + // Service unknow => mce not registered. Signal initial state. + emit q->chargerStatusChanged(BatteryStatus::ChargerStatusUnknown); + } else if (watcher->isValid() && watcher->isFinished()) { + QDBusPendingReply reply = *watcher; + chargerStatusChanged(reply.value()); + } + + watcher->deleteLater(); +} + +void BatteryStatusPrivate::initialBatteryStatus(QDBusPendingCallWatcher *watcher) +{ + if (watcher->isError() && (watcher->error().type() == QDBusError::ServiceUnknown)) { + // Service unknown => mce not registered. Signal initial state. + emit q->statusChanged(BatteryStatus::BatteryStatusUnknown); + } else if (watcher->isValid() && watcher->isFinished()) { + QDBusPendingReply reply = *watcher; + statusChanged(reply.value()); + } + + watcher->deleteLater(); +} + +void BatteryStatusPrivate::initialChargePercentage(QDBusPendingCallWatcher *watcher) +{ + if (watcher->isError() && (watcher->error().type() == QDBusError::ServiceUnknown)) { + // Service unknown => mce not registered. Signal initial state. + emit q->chargePercentageChanged(-1); + } else if (watcher->isValid() && watcher->isFinished()) { + QDBusPendingReply reply = *watcher; + chargePercentageChanged(reply.value()); + } + + watcher->deleteLater(); +} + +BatteryStatus::BatteryStatus(QObject *parent) + : QObject(parent) + , d_ptr(new BatteryStatusPrivate(this)) +{ +} + +BatteryStatus::~BatteryStatus() +{ +} + +/** + * @brief BatteryStatus::chargerStatus + * @return Returns charger connected status. Returns Connected when power cord is connected (charging) and + * Disconnected when charger is disconnected (discharging). In case information cannot be read ChargerStatusUnknown + * is returned. + */ +BatteryStatus::ChargerStatus BatteryStatus::chargerStatus() const +{ + Q_D(const BatteryStatus); + return d->chargerStatus; +} + +/** + * @brief BatteryStatus::batteryChargeLevel + * @return Returns battery charge level, in case information cannot be read -1 is returned. + */ +int BatteryStatus::chargePercentage() const +{ + Q_D(const BatteryStatus); + return d->chargePercentage; +} + + +/** + * @brief BatteryStatus::status + * @return Returns battery charge status + */ +BatteryStatus::Status BatteryStatus::status() const +{ + Q_D(const BatteryStatus); + return d->status; +} diff --git a/src/batterystatus.h b/src/batterystatus.h new file mode 100644 index 0000000..ff1e37e --- /dev/null +++ b/src/batterystatus.h @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2017 Jolla Ltd. + * Contact: Raine Makelainen + * + * You may use this file under the terms of the BSD license as follows: + * + * "Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Nemo Mobile nor the names of its contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." + */ + +#ifndef BATTERYSTATUS_H +#define BATTERYSTATUS_H + +#include + +#include + +class BatteryStatusPrivate; +class SYSTEMSETTINGS_EXPORT BatteryStatus : public QObject +{ + Q_OBJECT + Q_ENUMS(ChargerStatus) + Q_ENUMS(Status) + + Q_PROPERTY(ChargerStatus chargerStatus READ chargerStatus NOTIFY chargerStatusChanged) + Q_PROPERTY(int chargePercentage READ chargePercentage NOTIFY chargePercentageChanged) + Q_PROPERTY(Status status READ status NOTIFY statusChanged) + +public: + BatteryStatus(QObject *parent = 0); + ~BatteryStatus(); + + enum ChargerStatus { + ChargerStatusUnknown = -1, + Disconnected = 0, + Connected = 1 + }; + Q_ENUM(ChargerStatus) + + enum Status { + BatteryStatusUnknown = -1, + Full = 0, + Normal = 1, + Low = 2, + Empty = 3 + }; + Q_ENUM(Status) + + ChargerStatus chargerStatus() const; + int chargePercentage() const; + Status status() const; + +signals: + void chargerStatusChanged(ChargerStatus status); + void chargePercentageChanged(int percentage); + void statusChanged(Status status); + +private: + BatteryStatusPrivate *d_ptr; + Q_DISABLE_COPY(BatteryStatus) + Q_DECLARE_PRIVATE(BatteryStatus) +}; + +#endif // BATTERYSTATUS_H diff --git a/src/batterystatus_p.h b/src/batterystatus_p.h new file mode 100644 index 0000000..da54cd7 --- /dev/null +++ b/src/batterystatus_p.h @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2017 Jolla Ltd. + * Contact: Raine Makelainen + * + * You may use this file under the terms of the BSD license as follows: + * + * "Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Nemo Mobile nor the names of its contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." + */ + +#ifndef BATTERYSTATUS_P_H +#define BATTERYSTATUS_P_H + +#include "batterystatus.h" + +class QDBusPendingCallWatcher; + +class BatteryStatusPrivate : public QObject +{ + Q_OBJECT + +public: + BatteryStatusPrivate(BatteryStatus *batteryInfo); + ~BatteryStatusPrivate(); + + void registerSignals(); + + BatteryStatus::ChargerStatus parseChargerStatus(const QString &state); + BatteryStatus::Status parseBatteryStatus(const QString &status); + + BatteryStatus *q; + BatteryStatus::Status status; + BatteryStatus::ChargerStatus chargerStatus; + int chargePercentage; + +public slots: + void mceRegistered(); + void mceUnregistered(); + + void chargerStatusChanged(const QString &status); + void statusChanged(const QString &s); + void chargePercentageChanged(int percentage); + + void initialChargerState(QDBusPendingCallWatcher *watcher); + void initialBatteryStatus(QDBusPendingCallWatcher *watcher); + void initialChargePercentage(QDBusPendingCallWatcher *watcher); +}; + +#endif // BATTERYSTATUS_P_H diff --git a/src/plugin/plugin.cpp b/src/plugin/plugin.cpp index 03b41a6..ca33114 100644 --- a/src/plugin/plugin.cpp +++ b/src/plugin/plugin.cpp @@ -43,6 +43,7 @@ #include "displaysettings.h" #include "aboutsettings.h" #include "developermodesettings.h" +#include "batterystatus.h" #include "diskusage.h" #include "partitionmodel.h" #include "certificatemodel.h" @@ -80,6 +81,7 @@ class SystemSettingsPlugin : public QQmlExtensionPlugin qmlRegisterType(uri, 1, 0, "CertificateModel"); qmlRegisterSingletonType(uri, 1, 0, "VpnModel", vpnmodel_api_factory); qRegisterMetaType("DeveloperModeSettings::Status"); + qmlRegisterType(uri, 1, 0, "BatteryStatus"); qmlRegisterType(uri, 1, 0, "DiskUsage"); } }; diff --git a/src/src.pro b/src/src.pro index 40d7672..172b895 100644 --- a/src/src.pro +++ b/src/src.pro @@ -6,7 +6,7 @@ QT += qml dbus systeminfo QT -= gui CONFIG += c++11 hide_symbols link_pkgconfig -PKGCONFIG += profile mlite5 timed-qt5 libshadowutils blkid libcrypto nemomodels-qt5 +PKGCONFIG += profile mlite5 mce timed-qt5 libshadowutils blkid libcrypto nemomodels-qt5 system(qdbusxml2cpp -p mceiface.h:mceiface.cpp mce.xml) system(qdbusxml2cpp -c ConnmanVpnProxy -p connmanvpnproxy ../dbus/net.connman.vpn.xml -i qdbusxml2cpp_dbus_types.h) @@ -25,6 +25,7 @@ SOURCES += \ connmanvpnproxy.cpp \ connmanvpnconnectionproxy.cpp \ developermodesettings.cpp \ + batterystatus.cpp \ diskusage.cpp \ diskusage_impl.cpp \ partition.cpp \ @@ -44,6 +45,7 @@ PUBLIC_HEADERS = \ connmanvpnproxy.h \ connmanvpnconnectionproxy.h \ developermodesettings.h \ + batterystatus.h \ diskusage.h \ partition.h \ partitionmanager.h \ @@ -53,6 +55,7 @@ PUBLIC_HEADERS = \ HEADERS += \ $$PUBLIC_HEADERS \ qdbusxml2cpp_dbus_types.h \ + batterystatus_p.h \ diskusage_p.h \ partition_p.h \ partitionmanager_p.h diff --git a/systemsettings.pro b/systemsettings.pro index 40e2e1e..9fbcd10 100644 --- a/systemsettings.pro +++ b/systemsettings.pro @@ -4,4 +4,6 @@ src_plugins.subdir = src/plugin src_plugins.target = sub-plugins src_plugins.depends = src +OTHER_FILES += rpm/nemo-qml-plugin-systemsettings.spec + SUBDIRS = src src_plugins tests