diff --git a/autotests/CMakeLists.txt b/autotests/CMakeLists.txt --- a/autotests/CMakeLists.txt +++ b/autotests/CMakeLists.txt @@ -8,6 +8,7 @@ qt5_add_dbus_interface(bluezqt_autotests_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/interfaces/org.freedesktop.DBus.Properties.xml dbusproperties_tst) qt5_add_dbus_interface(bluezqt_autotests_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/interfaces/org.bluez.Adapter1.xml bluezadapter1_tst) +qt5_add_dbus_interface(bluezqt_autotests_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/interfaces/org.bluez.Battery1.xml bluezbattery1_tst) qt5_add_dbus_interface(bluezqt_autotests_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/interfaces/org.bluez.Device1.xml bluezdevice1_tst) qt5_add_dbus_interface(bluezqt_autotests_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/interfaces/org.bluez.MediaPlayer1.xml bluezmediaplayer1_tst) qt5_add_dbus_interface(bluezqt_autotests_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/interfaces/org.bluez.MediaTransport1.xml bluezmediatransport1_tst) @@ -28,6 +29,7 @@ agentmanagertest obexmanagertest adaptertest + batterytest devicetest inputtest mediaplayertest diff --git a/autotests/autotests.cpp b/autotests/autotests.cpp --- a/autotests/autotests.cpp +++ b/autotests/autotests.cpp @@ -21,6 +21,7 @@ #include "autotests.h" #include "device.h" #include "adapter.h" +#include "battery.h" #include "mediaplayer.h" #include "mediaplayertrack.h" #include "mediatransport.h" @@ -176,6 +177,7 @@ { qRegisterMetaType("DevicePtr"); qRegisterMetaType("AdapterPtr"); + qRegisterMetaType("BatteryPtr"); qRegisterMetaType("MediaPlayerPtr"); qRegisterMetaType("MediaTransportPtr"); } diff --git a/autotests/batterytest.h b/autotests/batterytest.h new file mode 100644 --- /dev/null +++ b/autotests/batterytest.h @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2019 Kai Uwe Broulik + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) version 3, or any + * later version accepted by the membership of KDE e.V. (or its + * successor approved by the membership of KDE e.V.), which shall + * act as a proxy defined in Section 6 of version 3 of the license. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + */ + +#ifndef BATTERYTEST_H +#define BATTERYTEST_H + +#include + +#include "bluezbattery1_tst.h" + +#include "manager.h" +#include "device.h" +#include "battery.h" + +class BatteryTest : public QObject +{ + Q_OBJECT + +public: + explicit BatteryTest(); + +private Q_SLOTS: + void initTestCase(); + void cleanupTestCase(); + + void getPropertiesTest(); + +private: + struct BatteryUnit + { + BluezQt::DevicePtr device; + org::bluez::Battery1 *dbusBattery; + }; + + BluezQt::Manager *m_manager; + QList m_units; +}; + +#endif // BATTERYTEST_H diff --git a/autotests/batterytest.cpp b/autotests/batterytest.cpp new file mode 100644 --- /dev/null +++ b/autotests/batterytest.cpp @@ -0,0 +1,142 @@ +/* + * Copyright (C) 2019 Kai Uwe Broulik + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) version 3, or any + * later version accepted by the membership of KDE e.V. (or its + * successor approved by the membership of KDE e.V.), which shall + * act as a proxy defined in Section 6 of version 3 of the license. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + */ + +#include "batterytest.h" +#include "autotests.h" +#include "pendingcall.h" +#include "initmanagerjob.h" + +#include + +namespace BluezQt +{ +extern void bluezqt_initFakeBluezTestRun(); +} + +using namespace BluezQt; + +BatteryTest::BatteryTest() + : m_manager(nullptr) +{ + Autotests::registerMetatypes(); +} + +void BatteryTest::initTestCase() +{ + QDBusConnection connection = QDBusConnection::sessionBus(); + QString service = QStringLiteral("org.kde.bluezqt.fakebluez"); + + bluezqt_initFakeBluezTestRun(); + + FakeBluez::start(); + FakeBluez::runTest(QStringLiteral("bluez-standard")); + + // Create adapter + QString adapter = QStringLiteral("/org/bluez/hci0"); + QVariantMap adapterProps; + adapterProps[QStringLiteral("Path")] = QVariant::fromValue(QDBusObjectPath(adapter)); + adapterProps[QStringLiteral("Address")] = QStringLiteral("1C:E5:C3:BC:94:7E"); + adapterProps[QStringLiteral("Name")] = QStringLiteral("TestAdapter"); + FakeBluez::runAction(QStringLiteral("devicemanager"), QStringLiteral("create-adapter"), adapterProps); + + // Create devices + QVariantMap deviceProps; + QVariantMap batteryProps; + + QString device1 = adapter + QLatin1String("/dev_40_79_6A_0C_39_75"); + deviceProps[QStringLiteral("Path")] = QVariant::fromValue(QDBusObjectPath(device1)); + deviceProps[QStringLiteral("Adapter")] = QVariant::fromValue(QDBusObjectPath(adapter)); + deviceProps[QStringLiteral("Address")] = QStringLiteral("40:79:6A:0C:39:75"); + deviceProps[QStringLiteral("Name")] = QStringLiteral("TestDevice"); + deviceProps[QStringLiteral("UUIDs")] = QStringList(QStringLiteral("00001124-0000-1000-8000-00805F9B34FB")); + batteryProps[QStringLiteral("Percentage")] = uchar(42); + deviceProps[QStringLiteral("Battery")] = batteryProps; + FakeBluez::runAction(QStringLiteral("devicemanager"), QStringLiteral("create-device"), deviceProps); + + QString device2 = adapter + QLatin1String("/dev_50_79_6A_0C_39_75"); + deviceProps[QStringLiteral("Path")] = QVariant::fromValue(QDBusObjectPath(device2)); + deviceProps[QStringLiteral("Adapter")] = QVariant::fromValue(QDBusObjectPath(adapter)); + deviceProps[QStringLiteral("Address")] = QStringLiteral("50:79:6A:0C:39:75"); + deviceProps[QStringLiteral("Name")] = QStringLiteral("TestDevice2"); + deviceProps[QStringLiteral("UUIDs")] = QStringList(QStringLiteral("00001124-0000-1000-8000-00805F9B34FB")); + batteryProps[QStringLiteral("Percentage")] = uchar(0); + deviceProps[QStringLiteral("Battery")] = batteryProps; + FakeBluez::runAction(QStringLiteral("devicemanager"), QStringLiteral("create-device"), deviceProps); + + QString device3 = adapter + QLatin1String("/dev_60_79_6B_0C_39_55"); + deviceProps[QStringLiteral("Path")] = QVariant::fromValue(QDBusObjectPath(device3)); + deviceProps[QStringLiteral("Adapter")] = QVariant::fromValue(QDBusObjectPath(adapter)); + deviceProps[QStringLiteral("Address")] = QStringLiteral("60:79:6B:0C:39:55"); + deviceProps[QStringLiteral("Name")] = QStringLiteral("TestDevice3"); + deviceProps[QStringLiteral("UUIDs")] = QStringList(QStringLiteral("00001124-0000-1000-8000-00805F9B34FB")); + batteryProps[QStringLiteral("Percentage")] = uchar(99); + deviceProps[QStringLiteral("Battery")] = batteryProps; + FakeBluez::runAction(QStringLiteral("devicemanager"), QStringLiteral("create-device"), deviceProps); + + QString device4 = adapter + QLatin1String("/dev_70_79_6B_0C_39_55"); + deviceProps[QStringLiteral("Path")] = QVariant::fromValue(QDBusObjectPath(device4)); + deviceProps[QStringLiteral("Adapter")] = QVariant::fromValue(QDBusObjectPath(adapter)); + deviceProps[QStringLiteral("Address")] = QStringLiteral("70:79:6B:0C:39:55"); + deviceProps[QStringLiteral("Name")] = QStringLiteral("TestDevice4"); + deviceProps[QStringLiteral("UUIDs")] = QStringList(QStringLiteral("00001124-0000-1000-8000-00805F9B34FB")); + batteryProps[QStringLiteral("Percentage")] = uchar(100); + deviceProps[QStringLiteral("Battery")] = batteryProps; + FakeBluez::runAction(QStringLiteral("devicemanager"), QStringLiteral("create-device"), deviceProps); + + m_manager = new Manager(); + InitManagerJob *initJob = m_manager->init(); + initJob->exec(); + QVERIFY(!initJob->error()); + + for (DevicePtr device : m_manager->devices()) { + QVERIFY(device->battery()); + + BatteryUnit u; + u.device = device; + u.dbusBattery = new org::bluez::Battery1(service, + device->ubi(), + connection, + this); + m_units.append(u); + } + + QCOMPARE(m_manager->adapters().count(), 1); + QCOMPARE(m_manager->devices().count(), 4); +} + +void BatteryTest::cleanupTestCase() +{ + for (const BatteryUnit &unit : m_units) { + delete unit.dbusBattery; + } + + delete m_manager; + + FakeBluez::stop(); +} + +void BatteryTest::getPropertiesTest() +{ + for (const BatteryUnit &unit : m_units) { + QCOMPARE(unit.device->battery()->percentage(), unit.dbusBattery->percentage()); + } +} + +QTEST_MAIN(BatteryTest) diff --git a/autotests/fakebluez/CMakeLists.txt b/autotests/fakebluez/CMakeLists.txt --- a/autotests/fakebluez/CMakeLists.txt +++ b/autotests/fakebluez/CMakeLists.txt @@ -9,6 +9,7 @@ devicemanager.cpp adapterinterface.cpp deviceinterface.cpp + batteryinterface.cpp inputinterface.cpp mediaplayerinterface.cpp mediatransportinterface.cpp diff --git a/autotests/fakebluez/batteryinterface.h b/autotests/fakebluez/batteryinterface.h new file mode 100644 --- /dev/null +++ b/autotests/fakebluez/batteryinterface.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2019 Kai Uwe Broulik + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) version 3, or any + * later version accepted by the membership of KDE e.V. (or its + * successor approved by the membership of KDE e.V.), which shall + * act as a proxy defined in Section 6 of version 3 of the license. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + */ + +#ifndef BATTERYINTERFACE_H +#define BATTERYINTERFACE_H + +#include "object.h" + +#include + +class QDBusMessage; +class QDBusObjectPath; + +class BatteryObject : public QObject +{ +public: + explicit BatteryObject(const QDBusObjectPath &path, QObject *parent = nullptr); +}; + +class BatteryInterface : public QDBusAbstractAdaptor, public Object +{ + Q_OBJECT + Q_CLASSINFO("D-Bus Interface", "org.bluez.Battery1") + Q_PROPERTY(uchar Percentage READ percentage) + +public: + explicit BatteryInterface(const QDBusObjectPath &path, const QVariantMap &properties, QObject *parent = nullptr); + + uchar percentage() const; +}; + +#endif // BATTERYINTERFACE_H diff --git a/autotests/fakebluez/batteryinterface.cpp b/autotests/fakebluez/batteryinterface.cpp new file mode 100644 --- /dev/null +++ b/autotests/fakebluez/batteryinterface.cpp @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2019 Kai Uwe Broulik + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) version 3, or any + * later version accepted by the membership of KDE e.V. (or its + * successor approved by the membership of KDE e.V.), which shall + * act as a proxy defined in Section 6 of version 3 of the license. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + */ + +#include "batteryinterface.h" + +#include + +// BatteryObject +BatteryObject::BatteryObject(const QDBusObjectPath &path, QObject *parent) + : QObject(parent) +{ + QDBusConnection::sessionBus().registerObject(path.path(), this); +} + +// BatteryInterface +BatteryInterface::BatteryInterface(const QDBusObjectPath &path, const QVariantMap &properties, QObject *parent) + : QDBusAbstractAdaptor(parent) +{ + setPath(path); + setObjectParent(parent); + setProperties(properties); + setName(QStringLiteral("org.bluez.Battery1")); +} + +uchar BatteryInterface::percentage() const +{ + return Object::property(QStringLiteral("Percentage")).value(); +} diff --git a/autotests/fakebluez/deviceinterface.cpp b/autotests/fakebluez/deviceinterface.cpp --- a/autotests/fakebluez/deviceinterface.cpp +++ b/autotests/fakebluez/deviceinterface.cpp @@ -20,6 +20,7 @@ #include "deviceinterface.h" #include "objectmanager.h" +#include "batteryinterface.h" #include "mediaplayerinterface.h" #include "mediatransportinterface.h" #include "inputinterface.h" @@ -50,6 +51,19 @@ // Alias needs special handling setAlias(properties.value(QStringLiteral("Alias")).toString()); + // Create Battery1 + if (properties.contains(QStringLiteral("Battery"))) { + const QVariantMap &inputProps = qdbus_cast(properties.value(QStringLiteral("Battery"))); + BatteryInterface *input = new BatteryInterface(path, inputProps, parent); + + ObjectManager *manager = ObjectManager::self(); + manager->addObject(input); + + QVariantMap props = properties; + props.remove(QStringLiteral("Battery")); + setProperties(props); + } + // Create Input1 if (properties.contains(QStringLiteral("Input"))) { const QVariantMap &inputProps = qdbus_cast(properties.value(QStringLiteral("Input"))); diff --git a/autotests/interfaces/org.bluez.Battery1.xml b/autotests/interfaces/org.bluez.Battery1.xml new file mode 100644 --- /dev/null +++ b/autotests/interfaces/org.bluez.Battery1.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -4,6 +4,7 @@ manager_p.cpp adapter.cpp adapter_p.cpp + battery.cpp device.cpp device_p.cpp gattapplication.cpp @@ -67,6 +68,7 @@ qt5_add_dbus_interface(bluezqt_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/interfaces/org.freedesktop.DBus.Properties.xml dbusproperties) qt5_add_dbus_interface(bluezqt_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/interfaces/org.bluez.Adapter1.xml bluezadapter1) qt5_add_dbus_interface(bluezqt_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/interfaces/org.bluez.AgentManager1.xml bluezagentmanager1) +qt5_add_dbus_interface(bluezqt_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/interfaces/org.bluez.Battery1.xml bluezbattery1) qt5_add_dbus_interface(bluezqt_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/interfaces/org.bluez.GattCharacteristic1.xml bluezgattcharacteristic1) qt5_add_dbus_interface(bluezqt_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/interfaces/org.bluez.GattManager1.xml bluezgattmanager1) qt5_add_dbus_interface(bluezqt_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/interfaces/org.bluez.ProfileManager1.xml bluezprofilemanager1) diff --git a/src/battery.h b/src/battery.h new file mode 100644 --- /dev/null +++ b/src/battery.h @@ -0,0 +1,83 @@ +/* + * BluezQt - Asynchronous BlueZ wrapper library + * + * Copyright (C) 2019 Kai Uwe Broulik + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) version 3, or any + * later version accepted by the membership of KDE e.V. (or its + * successor approved by the membership of KDE e.V.), which shall + * act as a proxy defined in Section 6 of version 3 of the license. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + */ + +#ifndef BLUEZQT_BATTERY_H +#define BLUEZQT_BATTERY_H + +#include + +#include "types.h" +#include "bluezqt_export.h" + +namespace BluezQt +{ + +/** + * @class BluezQt::Battery battery.h + * + * %Device battery. + * + * This class represents a battery interface. + */ +class BLUEZQT_EXPORT Battery : public QObject +{ + Q_OBJECT + Q_PROPERTY(int percentage READ percentage NOTIFY percentageChanged) + +public: + /** + * Destroys a Battery object. + */ + ~Battery(); + + /** + * Returns a shared pointer from this. + * + * @return BatteryPtr + */ + BatteryPtr toSharedPtr() const; + + /** + * Returns the battery percentage. + * + * @return battery percentage + */ + int percentage() const; + +Q_SIGNALS: + /** + * Indicates that battery's percentage has changed. + */ + void percentageChanged(int percentage); + +private: + explicit Battery(const QString &path, const QVariantMap &properties); + + class BatteryPrivate *const d; + + friend class BatteryPrivate; + friend class DevicePrivate; +}; + +} // namespace BluezQt + +#endif // BLUEZQT_BATTERY_H diff --git a/src/battery.cpp b/src/battery.cpp new file mode 100644 --- /dev/null +++ b/src/battery.cpp @@ -0,0 +1,80 @@ +/* + * BluezQt - Asynchronous Bluez wrapper library + * + * Copyright (C) 2019 Kai Uwe Broulik + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) version 3, or any + * later version accepted by the membership of KDE e.V. (or its + * successor approved by the membership of KDE e.V.), which shall + * act as a proxy defined in Section 6 of version 3 of the license. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + */ + +#include "battery.h" +#include "battery_p.h" +#include "utils.h" +#include "macros.h" + +#include + +namespace BluezQt +{ + +BatteryPrivate::BatteryPrivate(const QString &path, const QVariantMap &properties) + : QObject() + , m_path(path) +{ + // Init properties + m_percentage = properties.value(QStringLiteral("Percentage")).toInt(); +} + +void BatteryPrivate::propertiesChanged(const QString &interface, const QVariantMap &changed, const QStringList &invalidated) +{ + Q_UNUSED(invalidated) + + if (interface != Strings::orgBluezBattery1()) { + return; + } + + QVariantMap::const_iterator i; + for (i = changed.constBegin(); i != changed.constEnd(); ++i) { + const QVariant &value = i.value(); + const QString &property = i.key(); + + if (property == QLatin1String("Percentage")) { + PROPERTY_CHANGED2(m_percentage, value.toInt(), percentageChanged) + } + } +} + +Battery::Battery(const QString &path, const QVariantMap &properties) + : d(new BatteryPrivate(path, properties)) +{ +} + +Battery::~Battery() +{ + delete d; +} + +BatteryPtr Battery::toSharedPtr() const +{ + return d->q.toStrongRef(); +} + +int Battery::percentage() const +{ + return d->m_percentage; +} + +} // namespace BluezQt diff --git a/src/imports/declarativedevicesmodel.h b/src/battery_p.h copy from src/imports/declarativedevicesmodel.h copy to src/battery_p.h --- a/src/imports/declarativedevicesmodel.h +++ b/src/battery_p.h @@ -1,7 +1,7 @@ /* * BluezQt - Asynchronous Bluez wrapper library * - * Copyright (C) 2014 David Rosca + * Copyright (C) 2019 Kai Uwe Broulik * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,39 +20,31 @@ * License along with this library. If not, see . */ -#ifndef DECLARATIVEDEVICESMODEL_H -#define DECLARATIVEDEVICESMODEL_H +#ifndef BLUEZQT_BATTERY_P_H +#define BLUEZQT_BATTERY_P_H -#include +#include -#include "devicesmodel.h" +#include "battery.h" -class DeclarativeManager; +namespace BluezQt +{ -class DeclarativeDevicesModel : public QSortFilterProxyModel +class BatteryPrivate : public QObject { Q_OBJECT - Q_PROPERTY(DeclarativeManager* manager READ manager WRITE setManager) public: - enum DeclarativeDeviceRoles { - DeviceRole = BluezQt::DevicesModel::LastRole + 1, - AdapterRole = BluezQt::DevicesModel::LastRole + 2, - MediaPlayerRole = BluezQt::DevicesModel::LastRole + 3 - }; - - explicit DeclarativeDevicesModel(QObject *parent = nullptr); + explicit BatteryPrivate(const QString &path, const QVariantMap &properties); - DeclarativeManager *manager() const; - void setManager(DeclarativeManager *manager); + void propertiesChanged(const QString &interface, const QVariantMap &changed, const QStringList &invalidated); - QHash roleNames() const override; - QVariant data(const QModelIndex &index, int role) const override; + QWeakPointer q; -private: - DeclarativeManager *m_manager; - BluezQt::DevicesModel *m_model; + QString m_path; + int m_percentage = 0; }; -#endif // DECLARATIVEMANAGER_H +} // namespace BluezQt +#endif // BLUEZQT_BATTERY_P_H diff --git a/src/device.h b/src/device.h --- a/src/device.h +++ b/src/device.h @@ -62,6 +62,7 @@ Q_PROPERTY(bool connected READ isConnected NOTIFY connectedChanged) Q_PROPERTY(QStringList uuids READ uuids NOTIFY uuidsChanged) Q_PROPERTY(QString modalias READ modalias NOTIFY modaliasChanged) + Q_PROPERTY(BatteryPtr battery READ battery NOTIFY batteryChanged) Q_PROPERTY(InputPtr input READ input NOTIFY inputChanged) Q_PROPERTY(MediaPlayerPtr mediaPlayer READ mediaPlayer NOTIFY mediaPlayerChanged) Q_PROPERTY(MediaTransportPtr mediaTransport READ mediaTransport NOTIFY mediaTransportChanged) @@ -297,6 +298,14 @@ */ QString modalias() const; + /** + * Returns the battery interface for the device. + * + * @return null if device has no battery + * @since 5.66 + */ + BatteryPtr battery() const; + /** * Returns the input interface for the device. * @@ -509,6 +518,11 @@ */ void modaliasChanged(const QString &modalias); + /** + * Indicates that device's battery has changed. + */ + void batteryChanged(BatteryPtr battery); + /** * Indicates that device's input have changed. */ diff --git a/src/device.cpp b/src/device.cpp --- a/src/device.cpp +++ b/src/device.cpp @@ -164,6 +164,11 @@ return d->m_modalias; } +BatteryPtr Device::battery() const +{ + return d->m_battery; +} + InputPtr Device::input() const { return d->m_input; diff --git a/src/device_p.h b/src/device_p.h --- a/src/device_p.h +++ b/src/device_p.h @@ -74,6 +74,7 @@ bool m_connected; QStringList m_uuids; QString m_modalias; + BatteryPtr m_battery; InputPtr m_input; MediaPlayerPtr m_mediaPlayer; MediaTransportPtr m_mediaTransport; diff --git a/src/device_p.cpp b/src/device_p.cpp --- a/src/device_p.cpp +++ b/src/device_p.cpp @@ -23,6 +23,8 @@ #include "device_p.h" #include "device.h" #include "adapter.h" +#include "battery.h" +#include "battery_p.h" #include "input.h" #include "input_p.h" #include "mediaplayer.h" @@ -87,7 +89,12 @@ QVariantMapMap::const_iterator it; for (it = interfaces.constBegin(); it != interfaces.constEnd(); ++it) { - if (it.key() == Strings::orgBluezInput1()) { + if (it.key() == Strings::orgBluezBattery1()) { + m_battery = BatteryPtr(new Battery(path, it.value())); + m_battery->d->q = m_battery.toWeakRef(); + Q_EMIT q.lock()->batteryChanged(m_battery); + changed = true; + } else if (it.key() == Strings::orgBluezInput1()) { m_input = InputPtr(new Input(path, it.value())); m_input->d->q = m_input.toWeakRef(); Q_EMIT q.lock()->inputChanged(m_input); @@ -115,7 +122,11 @@ bool changed = false; for (const QString &interface : interfaces) { - if (interface == Strings::orgBluezInput1() && m_input && m_input->d->m_path == path) { + if (interface == Strings::orgBluezBattery1() && m_battery && m_battery->d->m_path == path) { + m_battery.clear(); + Q_EMIT q.lock()->batteryChanged(m_battery); + changed = true; + } else if (interface == Strings::orgBluezInput1() && m_input && m_input->d->m_path == path) { m_input.clear(); Q_EMIT q.lock()->inputChanged(m_input); changed = true; @@ -142,7 +153,9 @@ void DevicePrivate::propertiesChanged(const QString &interface, const QVariantMap &changed, const QStringList &invalidated) { - if (interface == Strings::orgBluezInput1() && m_input) { + if (interface == Strings::orgBluezBattery1() && m_battery) { + m_battery->d->propertiesChanged(interface, changed, invalidated); + } else if (interface == Strings::orgBluezInput1() && m_input) { m_input->d->propertiesChanged(interface, changed, invalidated); } else if (interface == Strings::orgBluezMediaPlayer1() && m_mediaPlayer) { m_mediaPlayer->d->propertiesChanged(interface, changed, invalidated); diff --git a/src/imports/CMakeLists.txt b/src/imports/CMakeLists.txt --- a/src/imports/CMakeLists.txt +++ b/src/imports/CMakeLists.txt @@ -1,6 +1,7 @@ set(bluezqtextensionplugin_SRCS declarativemanager.cpp declarativeadapter.cpp + declarativebattery.cpp declarativedevice.cpp declarativeinput.cpp declarativemediaplayer.cpp diff --git a/src/imports/bluezqtextensionplugin.cpp b/src/imports/bluezqtextensionplugin.cpp --- a/src/imports/bluezqtextensionplugin.cpp +++ b/src/imports/bluezqtextensionplugin.cpp @@ -23,6 +23,7 @@ #include "bluezqtextensionplugin.h" #include "declarativemanager.h" #include "declarativeadapter.h" +#include "declarativebattery.h" #include "declarativedevice.h" #include "declarativeinput.h" #include "declarativemediaplayer.h" @@ -78,6 +79,7 @@ qmlRegisterSingletonType(uri, 1, 0, "Manager", manager_singleton); qmlRegisterType(uri, 1, 0, "DevicesModelPrivate"); qmlRegisterUncreatableType(uri, 1, 0, "Adapter", QStringLiteral("Adapter cannot be created")); + qmlRegisterUncreatableType(uri, 1, 0, "Battery", QStringLiteral("Battery cannot be created")); qmlRegisterUncreatableType(uri, 1, 0, "Device", QStringLiteral("Device cannot be created")); qmlRegisterUncreatableType(uri, 1, 0, "Input", QStringLiteral("Input cannot be created")); qmlRegisterUncreatableType(uri, 1, 0, "MediaPlayer", QStringLiteral("MediaPlayer cannot be created")); diff --git a/src/imports/declarativebattery.h b/src/imports/declarativebattery.h new file mode 100644 --- /dev/null +++ b/src/imports/declarativebattery.h @@ -0,0 +1,45 @@ +/* + * BluezQt - Asynchronous BlueZ wrapper library + * + * Copyright (C) 2019 Kai Uwe Broulik + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) version 3, or any + * later version accepted by the membership of KDE e.V. (or its + * successor approved by the membership of KDE e.V.), which shall + * act as a proxy defined in Section 6 of version 3 of the license. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + */ + +#ifndef DECLARATIVEBATTERY_H +#define DECLARATIVEBATTERY_H + +#include "battery.h" + +class DeclarativeBattery : public QObject +{ + Q_OBJECT + Q_PROPERTY(int percentage READ percentage NOTIFY percentageChanged) + +public: + explicit DeclarativeBattery(const BluezQt::BatteryPtr &battery, QObject *parent = nullptr); + + int percentage() const; + +Q_SIGNALS: + void percentageChanged(int percentage); + +private: + BluezQt::BatteryPtr m_battery; +}; + +#endif // DECLARATIVEBATTERY_H diff --git a/src/imports/declarativebattery.cpp b/src/imports/declarativebattery.cpp new file mode 100644 --- /dev/null +++ b/src/imports/declarativebattery.cpp @@ -0,0 +1,35 @@ +/* + * BluezQt - Asynchronous BlueZ wrapper library + * + * Copyright (C) 2019 Kai Uwe Broulik + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) version 3, or any + * later version accepted by the membership of KDE e.V. (or its + * successor approved by the membership of KDE e.V.), which shall + * act as a proxy defined in Section 6 of version 3 of the license. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + */ + +#include "declarativebattery.h" + +DeclarativeBattery::DeclarativeBattery(const BluezQt::BatteryPtr &battery, QObject *parent) + : QObject(parent) + , m_battery(battery) +{ + connect(m_battery.data(), &BluezQt::Battery::percentageChanged, this, &DeclarativeBattery::percentageChanged); +} + +int DeclarativeBattery::percentage() const +{ + return m_battery->percentage(); +} diff --git a/src/imports/declarativedevice.h b/src/imports/declarativedevice.h --- a/src/imports/declarativedevice.h +++ b/src/imports/declarativedevice.h @@ -26,6 +26,7 @@ #include "device.h" class DeclarativeAdapter; +class DeclarativeBattery; class DeclarativeInput; class DeclarativeMediaPlayer; @@ -94,6 +95,8 @@ QString modalias() const; + DeclarativeBattery *battery() const; + DeclarativeInput *input() const; DeclarativeMediaPlayer *mediaPlayer() const; @@ -126,15 +129,18 @@ void connectedChanged(bool connected); void uuidsChanged(const QStringList &uuids); void modaliasChanged(const QString &modalias); + void batteryChanged(DeclarativeBattery *battery); void inputChanged(DeclarativeInput *input); void mediaPlayerChanged(DeclarativeMediaPlayer *mediaPlayer); private: + void updateBattery(); void updateInput(); void updateMediaPlayer(); BluezQt::DevicePtr m_device; DeclarativeAdapter *m_adapter; + DeclarativeBattery *m_battery; DeclarativeInput *m_input; DeclarativeMediaPlayer *m_mediaPlayer; }; diff --git a/src/imports/declarativedevice.cpp b/src/imports/declarativedevice.cpp --- a/src/imports/declarativedevice.cpp +++ b/src/imports/declarativedevice.cpp @@ -22,6 +22,7 @@ #include "declarativedevice.h" #include "declarativeadapter.h" +#include "declarativebattery.h" #include "declarativeinput.h" #include "declarativemediaplayer.h" @@ -31,6 +32,7 @@ : QObject(adapter) , m_device(device) , m_adapter(adapter) + , m_battery(nullptr) , m_input(nullptr) , m_mediaPlayer(nullptr) { @@ -51,6 +53,7 @@ connect(m_device.data(), &BluezQt::Device::modaliasChanged, this, &DeclarativeDevice::modaliasChanged); connect(m_device.data(), &BluezQt::Device::mediaPlayerChanged, this, &DeclarativeDevice::updateMediaPlayer); connect(m_device.data(), &BluezQt::Device::inputChanged, this, &DeclarativeDevice::updateInput); + connect(m_device.data(), &BluezQt::Device::batteryChanged, this, &DeclarativeDevice::updateBattery); connect(m_device.data(), &BluezQt::Device::deviceRemoved, this, [this]() { Q_EMIT deviceRemoved(this); @@ -164,6 +167,11 @@ return m_device->modalias(); } +DeclarativeBattery *DeclarativeDevice::battery() const +{ + return m_battery; +} + DeclarativeInput *DeclarativeDevice::input() const { return m_input; @@ -209,6 +217,20 @@ return m_device->cancelPairing(); } +void DeclarativeDevice::updateBattery() +{ + if (m_battery) { + m_battery->deleteLater(); + m_battery = nullptr; + } + + if (m_device->battery()) { + m_battery = new DeclarativeBattery(m_device->battery(), this); + } + + Q_EMIT batteryChanged(m_battery); +} + void DeclarativeDevice::updateInput() { if (m_input) { diff --git a/src/imports/declarativedevicesmodel.h b/src/imports/declarativedevicesmodel.h --- a/src/imports/declarativedevicesmodel.h +++ b/src/imports/declarativedevicesmodel.h @@ -38,7 +38,8 @@ enum DeclarativeDeviceRoles { DeviceRole = BluezQt::DevicesModel::LastRole + 1, AdapterRole = BluezQt::DevicesModel::LastRole + 2, - MediaPlayerRole = BluezQt::DevicesModel::LastRole + 3 + MediaPlayerRole = BluezQt::DevicesModel::LastRole + 3, + BatteryRole = BluezQt::DevicesModel::LastRole + 4 }; explicit DeclarativeDevicesModel(QObject *parent = nullptr); diff --git a/src/imports/declarativedevicesmodel.cpp b/src/imports/declarativedevicesmodel.cpp --- a/src/imports/declarativedevicesmodel.cpp +++ b/src/imports/declarativedevicesmodel.cpp @@ -23,6 +23,7 @@ #include "declarativedevicesmodel.h" #include "declarativemanager.h" #include "declarativeadapter.h" +#include "declarativebattery.h" #include "declarativedevice.h" #include "declarativemediaplayer.h" @@ -52,6 +53,7 @@ roles[DeviceRole] = QByteArrayLiteral("Device"); roles[AdapterRole] = QByteArrayLiteral("Adapter"); roles[MediaPlayerRole] = QByteArrayLiteral("MediaPlayer"); + roles[BatteryRole] = QByteArrayLiteral("Battery"); return roles; } @@ -76,9 +78,13 @@ if (DeclarativeDevice *device = m_manager->declarativeDeviceFromPtr(dev)) { return QVariant::fromValue(device->mediaPlayer()); } - // fallthrough - Q_FALLTHROUGH(); - default: - return QSortFilterProxyModel::data(index, role); + break; + case BatteryRole: + if (DeclarativeDevice *device = m_manager->declarativeDeviceFromPtr(dev)) { + return QVariant::fromValue(device->battery()); + } + break; } + + return QSortFilterProxyModel::data(index, role); } diff --git a/src/interfaces/org.bluez.Battery1.xml b/src/interfaces/org.bluez.Battery1.xml new file mode 100644 --- /dev/null +++ b/src/interfaces/org.bluez.Battery1.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/src/types.h b/src/types.h --- a/src/types.h +++ b/src/types.h @@ -30,6 +30,7 @@ class Manager; class Adapter; +class Battery; class Device; class Input; class GattManager; @@ -55,6 +56,7 @@ typedef QSharedPointer ManagerPtr; typedef QSharedPointer AdapterPtr; +typedef QSharedPointer BatteryPtr; typedef QSharedPointer DevicePtr; typedef QSharedPointer InputPtr; typedef QSharedPointer GattManagerPtr; diff --git a/src/utils.h b/src/utils.h --- a/src/utils.h +++ b/src/utils.h @@ -39,6 +39,7 @@ QString orgFreedesktopDBusProperties(); QString orgBluez(); QString orgBluezAdapter1(); +QString orgBluezBattery1(); QString orgBluezDevice1(); QString orgBluezInput1(); QString orgBluezGattManager1(); diff --git a/src/utils.cpp b/src/utils.cpp --- a/src/utils.cpp +++ b/src/utils.cpp @@ -42,6 +42,7 @@ QString orgFreedesktopDBusProperties; QString orgBluez; QString orgBluezAdapter1; + QString orgBluezBattery1; QString orgBluezDevice1; QString orgBluezInput1; QString orgBluezGattManager1; @@ -67,6 +68,7 @@ orgFreedesktopDBusProperties = QStringLiteral("org.freedesktop.DBus.Properties"); orgBluez = QStringLiteral("org.bluez"); orgBluezAdapter1 = QStringLiteral("org.bluez.Adapter1"); + orgBluezBattery1 = QStringLiteral("org.bluez.Battery1"); orgBluezDevice1 = QStringLiteral("org.bluez.Device1"); orgBluezInput1 = QStringLiteral("org.bluez.Input1"); orgBluezGattManager1 = QStringLiteral("org.bluez.GattManager1"); @@ -113,6 +115,11 @@ return globalData->orgBluezAdapter1; } +QString Strings::orgBluezBattery1() +{ + return globalData->orgBluezBattery1; +} + QString Strings::orgBluezDevice1() { return globalData->orgBluezDevice1;