summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatt Ranostay <matt.ranostay@konsulko.com>2019-03-20 14:22:57 -0700
committerMatt Ranostay <matt.ranostay@konsulko.com>2019-04-04 11:34:09 -0700
commit5ba2e7752c478a386de6c6cf06adb6f9cf7ee79e (patch)
tree678e6edf13d5812a88b6c873b4176927fa0dafe4
parent47903065edab76a0278ab160a7cbbc112180f326 (diff)
libqtappfw: bluetooth: add BluetoothModel support
Switch from using single threaded and incorrect QML processing of ListViews to using models provided from libqtappfw Bug-AGL: SPEC-2270 SPEC-2290 Change-Id: I83f02ab104a18ade95dfd172902e32a808c3d897 Signed-off-by: Matt Ranostay <matt.ranostay@konsulko.com>
-rw-r--r--bluetooth/CMakeLists.txt4
-rw-r--r--bluetooth/bluetooth.cpp47
-rw-r--r--bluetooth/bluetooth.h10
-rw-r--r--bluetooth/bluetoothmodel.cpp192
-rw-r--r--bluetooth/bluetoothmodel.h81
5 files changed, 319 insertions, 15 deletions
diff --git a/bluetooth/CMakeLists.txt b/bluetooth/CMakeLists.txt
index c068a9f..cdefb0d 100644
--- a/bluetooth/CMakeLists.txt
+++ b/bluetooth/CMakeLists.txt
@@ -1,2 +1,2 @@
-add_headers(bluetooth.h bluetoothmessage.h)
-add_sources(bluetooth.cpp bluetoothmessage.cpp)
+add_headers(bluetooth.h bluetoothmessage.h bluetoothmodel.h)
+add_sources(bluetooth.cpp bluetoothmessage.cpp bluetoothmodel.cpp)
diff --git a/bluetooth/bluetooth.cpp b/bluetooth/bluetooth.cpp
index 25ff16e..eb00df4 100644
--- a/bluetooth/bluetooth.cpp
+++ b/bluetooth/bluetooth.cpp
@@ -20,15 +20,27 @@
#include "bluetoothmessage.h"
#include "responsemessage.h"
-Bluetooth::Bluetooth (QUrl &url, QObject * parent) :
+Bluetooth::Bluetooth (QUrl &url, QQmlContext *context, QObject * parent) :
QObject(parent),
+ m_context(context),
m_mloop(nullptr)
{
m_mloop = new MessageEngine(url);
+ m_bluetooth = new BluetoothModel();
QObject::connect(m_mloop, &MessageEngine::connected, this, &Bluetooth::onConnected);
QObject::connect(m_mloop, &MessageEngine::disconnected, this, &Bluetooth::onDisconnected);
QObject::connect(m_mloop, &MessageEngine::messageReceived, this, &Bluetooth::onMessageReceived);
+ BluetoothModelFilter *m_model = new BluetoothModelFilter();
+ m_model->setSourceModel(m_bluetooth);
+ m_model->setFilterFixedString("true");
+ context->setContextProperty("BluetoothPairedModel", m_model);
+
+ m_model = new BluetoothModelFilter();
+ m_model->setSourceModel(m_bluetooth);
+ m_model->setFilterFixedString("false");
+ context->setContextProperty("BluetoothDiscoveryModel", m_model);
+
uuids.insert("a2dp", "0000110a-0000-1000-8000-00805f9b34fb");
uuids.insert("avrcp", "0000110e-0000-1000-8000-00805f9b34fb");
uuids.insert("hfp", "0000111f-0000-1000-8000-00805f9b34fb");
@@ -192,23 +204,42 @@ void Bluetooth::onDisconnected()
}
}
+void Bluetooth::populateDeviceList(QJsonObject data)
+{
+ QJsonArray devices = data.value("devices").toArray();
+
+ m_bluetooth->removeAllDevices();
+
+ for (auto value : devices) {
+ BluetoothDevice *device = m_bluetooth->updateDeviceProperties(nullptr, value.toObject());
+ m_bluetooth->addDevice(device);
+ }
+}
+
void Bluetooth::processDeviceChangesEvent(QJsonObject data)
{
QString action = data.value("action").toString();
+ QString id = data.value("device").toString();
- if (action == "added")
- emit deviceAddedEvent(data);
- else if (action == "changed") {
+ if (action == "added") {
+ BluetoothDevice *device = m_bluetooth->updateDeviceProperties(nullptr, data);
+ m_bluetooth->addDevice(device);
+ } else if (action == "changed") {
auto powered = data.find("powered").value();
if (powered.isBool()) {
m_power = powered.toBool();
+ if (!m_power)
+ m_bluetooth->removeAllDevices();
emit powerChanged(m_power);
} else {
- emit deviceUpdatedEvent(data);
+ BluetoothDevice *device = m_bluetooth->getDevice(id);
+ m_bluetooth->updateDeviceProperties(device, data);
}
- } else if (action == "removed")
- emit deviceRemovedEvent(data);
+ } else if (action == "removed") {
+ BluetoothDevice *device = m_bluetooth->getDevice(id);
+ m_bluetooth->removeDevice(device);
+ }
}
void Bluetooth::onMessageReceived(MessageType type, Message *msg)
@@ -226,7 +257,7 @@ void Bluetooth::onMessageReceived(MessageType type, Message *msg)
ResponseMessage *tmsg = qobject_cast<ResponseMessage*>(msg);
if (tmsg->requestVerb() == "managed_objects") {
- emit deviceListEvent(tmsg->replyData());
+ populateDeviceList(tmsg->replyData());
} else if (tmsg->requestVerb() == "adapter_state") {
m_power = tmsg->replyData().value("powered").toBool();
emit powerChanged(m_power);
diff --git a/bluetooth/bluetooth.h b/bluetooth/bluetooth.h
index 0f38381..6cef0ce 100644
--- a/bluetooth/bluetooth.h
+++ b/bluetooth/bluetooth.h
@@ -22,6 +22,7 @@
#include <QJsonArray>
#include "messageengine.h"
+#include "bluetoothmodel.h"
class Bluetooth : public QObject
{
@@ -30,7 +31,7 @@ class Bluetooth : public QObject
Q_PROPERTY(bool discoverable READ discoverable WRITE setDiscoverable NOTIFY discoverableChanged)
public:
- explicit Bluetooth(QUrl &url, QObject * parent = Q_NULLPTR);
+ explicit Bluetooth(QUrl &url, QQmlContext *context, QObject * parent = Q_NULLPTR);
virtual ~Bluetooth();
void setPower(bool);
@@ -60,16 +61,15 @@ class Bluetooth : public QObject
void connectionEvent(QJsonObject data);
void requestConfirmationEvent(QJsonObject data);
- void deviceAddedEvent(QJsonObject data);
- void deviceRemovedEvent(QJsonObject data);
- void deviceUpdatedEvent(QJsonObject data);
- void deviceListEvent(QJsonObject data);
private:
MessageEngine *m_mloop;
+ QQmlContext *m_context;
+ BluetoothModel *m_bluetooth;
void send_command(QString, QJsonObject);
void set_discovery_filter();
void discovery_command(bool);
+ void populateDeviceList(QJsonObject data);
void processDeviceChangesEvent(QJsonObject data);
// slots
diff --git a/bluetooth/bluetoothmodel.cpp b/bluetooth/bluetoothmodel.cpp
new file mode 100644
index 0000000..f6c3d09
--- /dev/null
+++ b/bluetooth/bluetoothmodel.cpp
@@ -0,0 +1,192 @@
+#include "bluetoothmodel.h"
+#include <QDebug>
+
+BluetoothDevice::BluetoothDevice(const QString &id,
+ const QString &address,
+ const QString &name,
+ const bool paired,
+ const bool connected)
+ : m_id(id), m_address(address), m_name(name), m_paired(paired),
+ m_connected(connected)
+{
+}
+
+QString BluetoothDevice::id() const
+{
+ return m_id;
+}
+
+QString BluetoothDevice::address() const
+{
+ return m_address;
+}
+
+QString BluetoothDevice::name() const
+{
+ return m_name;
+}
+
+bool BluetoothDevice::paired() const
+{
+ return m_paired;
+}
+
+bool BluetoothDevice::connected() const
+{
+ return m_connected;
+}
+
+void BluetoothDevice::setId(const QString id)
+{
+ m_id = id;
+}
+
+void BluetoothDevice::setAddress(const QString address)
+{
+ m_address = address;
+}
+
+void BluetoothDevice::setName(const QString name)
+{
+ m_name = name;
+}
+
+void BluetoothDevice::setPaired(const bool paired)
+{
+ m_paired = paired;
+}
+
+void BluetoothDevice::setConnected(const bool connected)
+{
+ m_connected = connected;
+}
+
+BluetoothModel::BluetoothModel(QObject *parent)
+ : QAbstractListModel(parent)
+{
+}
+
+void BluetoothModel::addDevice(BluetoothDevice *device)
+{
+ beginInsertRows(QModelIndex(), rowCount(), rowCount());
+ m_devices << device;
+ endInsertRows();
+}
+
+void BluetoothModel::removeDevice(BluetoothDevice *device)
+{
+ int row = m_devices.indexOf(device);
+ beginRemoveRows(QModelIndex(), row, row);
+ m_devices.removeAt(row);
+ endRemoveRows();
+ delete device;
+}
+
+void BluetoothModel::removeAllDevices()
+{
+ beginRemoveRows(QModelIndex(), 0, m_devices.count() - 1);
+ qDeleteAll(m_devices.begin(), m_devices.end());
+ m_devices.clear();
+ endRemoveRows();
+}
+
+int BluetoothModel::rowCount(const QModelIndex &parent) const
+{
+ Q_UNUSED(parent);
+ return m_devices.count();
+}
+
+QVariant BluetoothModel::data(const QModelIndex &index, int role) const
+{
+ if (index.row() < 0 || index.row() >= m_devices.count())
+ return QVariant();
+
+ const BluetoothDevice *device = m_devices[index.row()];
+
+ switch (role) {
+ case IdRole:
+ return device->id();
+ case AddressRole:
+ return device->address();
+ case NameRole:
+ return device->name();
+ case PairedRole:
+ return device->paired();
+ case ConnectedRole:
+ return device->connected();
+ }
+
+ return QVariant();
+}
+
+QHash<int, QByteArray> BluetoothModel::roleNames() const {
+ QHash<int, QByteArray> roles;
+ roles[IdRole] = "id";
+ roles[AddressRole] = "address";
+ roles[NameRole] = "name";
+ roles[PairedRole] = "paired";
+ roles[ConnectedRole] = "connected";
+
+ return roles;
+}
+
+QModelIndex BluetoothModel::indexOf(BluetoothDevice *device)
+{
+ int row = m_devices.indexOf(device);
+
+ return index(row);
+}
+
+BluetoothDevice *BluetoothModel::getDevice(QString id)
+{
+ for (auto device : m_devices) {
+ if (device->id() == id)
+ return device;
+ }
+
+ return nullptr;
+}
+
+BluetoothDevice *BluetoothModel::updateDeviceProperties(BluetoothDevice *device, QJsonObject data)
+{
+ QJsonObject properties = data.value("properties").toObject();
+ QString id = data.value("device").toString();
+ QString address = properties.value("address").toString();
+ QString name = properties.value("name").toString();
+ bool paired = properties.value("paired").toBool();
+ bool connected = properties.value("connected").toBool();
+
+ if (device == nullptr)
+ return new BluetoothDevice(id, address, name, paired, connected);
+
+ device->setId(id);
+
+ if (!address.isEmpty())
+ device->setAddress(address);
+
+ if (!name.isEmpty())
+ device->setName(name);
+
+ if (properties.contains("paired"))
+ device->setPaired(paired);
+
+ if (properties.contains("connected"))
+ device->setConnected(connected);
+
+ emit dataChanged(indexOf(device), indexOf(device));
+
+ return device;
+}
+
+BluetoothModelFilter::BluetoothModelFilter(QObject *parent) : QSortFilterProxyModel(parent)
+{
+}
+
+bool BluetoothModelFilter::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const
+{
+ BluetoothModel *model = qobject_cast<BluetoothModel *>(sourceModel());
+ QModelIndex index = model->index(sourceRow);
+ bool paired = model->data(index, BluetoothModel::BluetoothRoles::PairedRole).toBool();
+
+ return ((paired ? "true" : "false") == filterRegExp().pattern());
+}
diff --git a/bluetooth/bluetoothmodel.h b/bluetooth/bluetoothmodel.h
new file mode 100644
index 0000000..0fc07aa
--- /dev/null
+++ b/bluetooth/bluetoothmodel.h
@@ -0,0 +1,81 @@
+#ifndef BLUETOOTH_MODEL_H
+#define BLUETOOTH_MODEL_H
+
+#include <QAbstractListModel>
+#include <QSortFilterProxyModel>
+#include <QStringList>
+#include <QtQml/QQmlContext>
+#include <QJsonObject>
+
+class BluetoothDevice
+{
+ public:
+ BluetoothDevice(const QString &id,
+ const QString &address,
+ const QString &name,
+ const bool paired,
+ const bool connected);
+ QString id() const;
+ QString address() const;
+ QString name() const;
+ bool paired() const;
+ bool connected() const;
+ void setId(const QString id);
+ void setAddress(const QString address);
+ void setName(const QString name);
+ void setPaired(const bool paired);
+ void setConnected(const bool connected);
+
+ private:
+ QString m_id;
+ QString m_address;
+ QString m_name;
+ bool m_paired;
+ bool m_connected;
+};
+
+class BluetoothModel : public QAbstractListModel
+{
+ Q_OBJECT
+
+ public:
+ enum BluetoothRoles {
+ IdRole = Qt::UserRole + 1,
+ AddressRole,
+ NameRole,
+ PairedRole,
+ ConnectedRole
+ };
+
+ BluetoothModel(QObject *parent = Q_NULLPTR);
+
+ void addDevice(BluetoothDevice *device);
+ void removeDevice(BluetoothDevice *device);
+ void removeAllDevices();
+ BluetoothDevice *getDevice(QString address);
+ BluetoothDevice *updateDeviceProperties(BluetoothDevice *device, QJsonObject data);
+ int rowCount(const QModelIndex &parent = QModelIndex()) const;
+ QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
+
+ signals:
+ void propertiesChanged(int connected);
+
+ protected:
+ QHash<int, QByteArray> roleNames() const;
+
+ private:
+ QList<BluetoothDevice *> m_devices;
+ QModelIndex indexOf(BluetoothDevice *device);
+};
+
+class BluetoothModelFilter : public QSortFilterProxyModel
+{
+ Q_OBJECT
+
+ public:
+ BluetoothModelFilter(QObject *parent = nullptr);
+
+ protected:
+ bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const;
+};
+#endif // BLUETOOTH_MODEL_H