Index: denali.pro.user =================================================================== diff -u -raa8f2c87c14c68d1fda6da2540d47144990a596c -rb252cd2777aadbce2d04aa32cc275f193de0cf52 --- denali.pro.user (.../denali.pro.user) (revision aa8f2c87c14c68d1fda6da2540d47144990a596c) +++ denali.pro.user (.../denali.pro.user) (revision b252cd2777aadbce2d04aa32cc275f193de0cf52) @@ -1,6 +1,6 @@ - + EnvironmentId Index: en_US.udic =================================================================== diff -u -raa8f2c87c14c68d1fda6da2540d47144990a596c -rb252cd2777aadbce2d04aa32cc275f193de0cf52 --- en_US.udic (.../en_US.udic) (revision aa8f2c87c14c68d1fda6da2540d47144990a596c) +++ en_US.udic (.../en_US.udic) (revision b252cd2777aadbce2d04aa32cc275f193de0cf52) @@ -175,3 +175,4 @@ Addr BCuff Mesur +ApplicationPOST Index: sources/bluetooth/BluetoothInterface.cpp =================================================================== diff -u -raa8f2c87c14c68d1fda6da2540d47144990a596c -rb252cd2777aadbce2d04aa32cc275f193de0cf52 --- sources/bluetooth/BluetoothInterface.cpp (.../BluetoothInterface.cpp) (revision aa8f2c87c14c68d1fda6da2540d47144990a596c) +++ sources/bluetooth/BluetoothInterface.cpp (.../BluetoothInterface.cpp) (revision b252cd2777aadbce2d04aa32cc275f193de0cf52) @@ -113,6 +113,9 @@ this , &BluetoothInterface ::onAgentDiscoverCancel ); connect(_agent , static_cast(&QBluetoothDeviceDiscoveryAgent::error), this , &BluetoothInterface ::onAgentDiscoverError ); + + connect(this , SIGNAL(didDeviceSelect(BluetoothDeviceData)), + this , SLOT( onDeviceSelect(BluetoothDeviceData))); } /*! @@ -177,12 +180,12 @@ vInfo.isValid() , \ vInfo.deviceUuid().toString() )); #define NOTIFY_SCAN_FOUND notifyStateChange(MBluetooth(MBluetooth::eIS_Scan_Found , \ - _temp.address().toString() , \ - _temp.name(), "" , \ - _local->pairingStatus(_temp.address()) , \ + vInfo.address().toString() , \ + vInfo.name(), "" , \ + _local->pairingStatus(vInfo.address()) , \ 0 , \ - _temp.isValid() , \ - _temp.deviceUuid().toString() )); + vInfo.isValid() , \ + vInfo.deviceUuid().toString() )); #define NOTIFY_SCAN_START notifyStateChange(MBluetooth(MBluetooth::eIS_Scan_Start )); #define NOTIFY_SCAN_REJECT notifyStateChange(MBluetooth(MBluetooth::eIS_Scan_Reject )); #define NOTIFY_SCAN_NOTFOUND notifyStateChange(MBluetooth(MBluetooth::eIS_Scan_NotFound ,"", "" )); @@ -336,15 +339,7 @@ */ void BluetoothInterface::ondoScan() { - if ( ! isValid() ) return; // POST failed. - - if (_agent && _agent->isActive()) { - NOTIFY_SCAN_REJECT - return; - } - - NOTIFY_SCAN_START - _agent->start(QBluetoothDeviceDiscoveryAgent::LowEnergyMethod); + startScan(); } // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -395,10 +390,12 @@ NOTIFY_SCAN_DISCOVER if (vInfo.coreConfigurations() & QBluetoothDeviceInfo::LowEnergyCoreConfiguration) { if ( isDeviceSupported( vInfo.name() ) ) { - _temp = QBluetoothDeviceInfo(vInfo.address(), vInfo.name(), QBluetoothDeviceInfo::HealthBloodPressureMonitor); + BluetoothDeviceData data; + data.addr = vInfo.address().toString(); + data.name = vInfo.name(); + data.pair = _local->pairingStatus(vInfo.address()); + emit didDeviceChange(data); NOTIFY_SCAN_FOUND - if (_agent->isActive()) - _agent->stop(); } } } @@ -429,7 +426,6 @@ void BluetoothInterface::onAgentDiscoverFinish() { NOTIFY_SCAN_DONE - connectToDevice(); } /*! @@ -441,7 +437,6 @@ void BluetoothInterface::onAgentDiscoverCancel() { NOTIFY_SCAN_STOP - connectToDevice(); } /*! @@ -742,7 +737,50 @@ } } + /*! + * \brief BluetoothInterface::onDeviceSelect + * \details the signal which will be called from a View created in the QML namespace to safely set the current selected device. + * \param vDevice + */ +void BluetoothInterface::onDeviceSelect(const BluetoothDeviceData &vDevice) { + _temp = QBluetoothDeviceInfo(QBluetoothAddress(vDevice.addr), vDevice.name, QBluetoothDeviceInfo::HealthBloodPressureMonitor); + connectToDevice(); +} + +/*! + * \brief BluetoothInterface::startScan + * \details Stars the agent device scan + * \return true if the agent can successfully start the scan. + */ +bool BluetoothInterface::startScan() +{ + if ( ! isValid() ) return false; // POST failed. + + if (_agent && _agent->isActive()) { + NOTIFY_SCAN_REJECT + return false; + } + + NOTIFY_SCAN_START + _agent->start(QBluetoothDeviceDiscoveryAgent::LowEnergyMethod); + return true; +} + +/*! + * \brief BluetoothInterface::stopScan + * \details Stops the agent device scan + * \return true if the agent is currently active and is stopped or false if it was not active. + */ +bool BluetoothInterface::stopScan() +{ + if (! _agent->isActive()) return false; + _agent->stop(); + // No NOTIFICATION here. will be send in the corresponding slot of the finish/cancel agent scan. + return true; +} + +/*! * \brief BluetoothInterface::initDevice * \return Initializes the device by making a new device and initializes its connections */ Index: sources/bluetooth/BluetoothInterface.h =================================================================== diff -u -raa8f2c87c14c68d1fda6da2540d47144990a596c -rb252cd2777aadbce2d04aa32cc275f193de0cf52 --- sources/bluetooth/BluetoothInterface.h (.../BluetoothInterface.h) (revision aa8f2c87c14c68d1fda6da2540d47144990a596c) +++ sources/bluetooth/BluetoothInterface.h (.../BluetoothInterface.h) (revision b252cd2777aadbce2d04aa32cc275f193de0cf52) @@ -116,7 +116,12 @@ void onServiceError ( QLowEnergyService::ServiceError vError ); void onServiceStateChanged ( QLowEnergyService::ServiceState vState ); + void onDeviceSelect (const BluetoothDeviceData &vDevice); + private: + bool startScan (); + bool stopScan (); + void initConnections (); void initConnectionsDevice (); void initConnectionsService (QLowEnergyService *vService); @@ -155,6 +160,8 @@ signals: void didStateChange (const BluetoothData &vData); void didActionReceive (const UIBloodPressureData &vData); + void didDeviceChange (const BluetoothDeviceData &vDevice); + void didDeviceSelect (const BluetoothDeviceData &vDevice); SAFE_CALL(doStart ) SAFE_CALL(doScan ) Index: sources/gui/qml/pages/settings/SettingsBluetoothCuff.qml =================================================================== diff -u -re4a0e2fc4c7ae0cbce0d670772276bf7f5ff3845 -rb252cd2777aadbce2d04aa32cc275f193de0cf52 --- sources/gui/qml/pages/settings/SettingsBluetoothCuff.qml (.../SettingsBluetoothCuff.qml) (revision e4a0e2fc4c7ae0cbce0d670772276bf7f5ff3845) +++ sources/gui/qml/pages/settings/SettingsBluetoothCuff.qml (.../SettingsBluetoothCuff.qml) (revision b252cd2777aadbce2d04aa32cc275f193de0cf52) @@ -45,67 +45,42 @@ property int labelHeight: 25 anchors.top : _image.top - anchors.topMargin : 100 anchors.left : parent.left anchors.leftMargin : 50 spacing : 10 Label { id : _deviceTitle - text : vBluetooth.devicePair ? qsTr("Found Paired Device") : qsTr("Found Device") + text : qsTr("Devices") } - Row { id : _deviceNameRow - leftPadding : 25 - Label { id : _deviceNameLabel - height : _deviceColumn.labelHeight - text : qsTr("Name") - labelWidth : 125 - verticalAlignment : Text.AlignVCenter + ListView { id: _deviceList + ScrollBar { + anchors.fill: _deviceList + flickable : _deviceList } - Label { id : _deviceName - height : _deviceColumn.labelHeight - text : ": " + vBluetooth.deviceName - font.pixelSize : Fonts.fontPixelNotification - verticalAlignment : Text.AlignVCenter + clip : true + spacing : 5 + width : 500 + height : 300 + model : vBluetooth + delegate: TouchRect { id: _deviceTouchrect + clip : true + radius : 10 + width : 500 - 10 // give room to scrollbar + height : 70 + color : Colors.transparent + border.color: pair ? Colors.borderButton : Colors.borderButtonUnselected + text { + text: addr + '\n' + name + anchors.horizontalCenter: undefined + anchors.left: _deviceTouchrect.left + anchors.leftMargin: 5 + } + onClicked: { + vBluetooth.didDeviceSelect(addr, name); + } } } - Row { - leftPadding : 25 - Label { id : _deviceAddressLabel - height : _deviceColumn.labelHeight - text : qsTr("Address") - labelWidth : 125 - verticalAlignment : Text.AlignVCenter - - } - Label { id : _deviceAddress - height : _deviceColumn.labelHeight - text : ": " + vBluetooth.deviceAddr - font.pixelSize : Fonts.fontPixelNotification - verticalAlignment : Text.AlignVCenter - } - } } - // Column { id : _debugColumn - // anchors.bottom : _scanButton.top - // anchors.left : parent.left - // anchors.leftMargin : 100 - // - // TouchRect { id : _connectButton - // text.text : qsTr("CONNECT") - // width : 300 - // isDefault : false - // enabled : vBluetooth.scanEnabled - // onClicked : vBluetooth.doConnectToDevice() - // } - // - // TouchRect { id : _notifyButton - // text.text : qsTr("NOTIFY") - // width : 300 - // isDefault : false - // enabled : vBluetooth.scanEnabled - // onClicked : vBluetooth.doEnableNotify() - // } - // } TouchRect { id : _scanButton anchors.bottom : parent.bottom anchors.bottomMargin: Variables.mainMenuHeight * 2 + Variables.minVGap Index: sources/model/MModel.h =================================================================== diff -u -raa8f2c87c14c68d1fda6da2540d47144990a596c -rb252cd2777aadbce2d04aa32cc275f193de0cf52 --- sources/model/MModel.h (.../MModel.h) (revision aa8f2c87c14c68d1fda6da2540d47144990a596c) +++ sources/model/MModel.h (.../MModel.h) (revision b252cd2777aadbce2d04aa32cc275f193de0cf52) @@ -265,6 +265,7 @@ REGISTER_METATYPE( SettingsData ) \ REGISTER_METATYPE( WifiNetworkData ) \ REGISTER_METATYPE( BluetoothData ) \ + REGISTER_METATYPE( BluetoothDeviceData ) \ /* Data */ \ REGISTER_METATYPE( HDOperationModeData ) \ REGISTER_METATYPE( PreTreatmentStatesData ) \ Index: sources/model/settings/MBluetooth.h =================================================================== diff -u -re4a0e2fc4c7ae0cbce0d670772276bf7f5ff3845 -rb252cd2777aadbce2d04aa32cc275f193de0cf52 --- sources/model/settings/MBluetooth.h (.../MBluetooth.h) (revision e4a0e2fc4c7ae0cbce0d670772276bf7f5ff3845) +++ sources/model/settings/MBluetooth.h (.../MBluetooth.h) (revision b252cd2777aadbce2d04aa32cc275f193de0cf52) @@ -16,7 +16,7 @@ // Qt #include -#include +#include // Project #include "main.h" // Doxygen : do not remove @@ -76,6 +76,20 @@ }; Q_ENUM(InterfaceStates) + struct BluetoothDevice { + QString addr = ""; + QString name = ""; + bool pair = 0; + bool operator ==(const BluetoothDevice &vDevice) const { + return vDevice.addr == addr && + vDevice.name == name && + vDevice.pair == pair ; + } + QString toString() const { + return addr + "," + pair + "," + name; + } + }; + InterfaceStates state ; QString localAddr = ""; QString localName = ""; @@ -117,4 +131,6 @@ }; } -typedef Model::MBluetooth BluetoothData; +typedef Model::MBluetooth BluetoothData; +typedef Model::MBluetooth::BluetoothDevice BluetoothDeviceData; +typedef QList BluetoothDeviceListData; Index: sources/view/settings/VBluetooth.cpp =================================================================== diff -u -raa8f2c87c14c68d1fda6da2540d47144990a596c -rb252cd2777aadbce2d04aa32cc275f193de0cf52 --- sources/view/settings/VBluetooth.cpp (.../VBluetooth.cpp) (revision aa8f2c87c14c68d1fda6da2540d47144990a596c) +++ sources/view/settings/VBluetooth.cpp (.../VBluetooth.cpp) (revision b252cd2777aadbce2d04aa32cc275f193de0cf52) @@ -21,23 +21,40 @@ #include "GuiController.h" #include "BluetoothInterface.h" -VIEW_DEF_CLASS(VBluetooth) - using namespace Bluetooth; using namespace Model; +View::VBluetooth::VBluetooth(QObject *parent) : QAbstractListModel(parent) { + initConnections(); +} + /*! * \brief VBluetooth::initConnections * Makes the necessary connections. Called inside VIEW_DEF_CLASS */ void View::VBluetooth::initConnections() { - connect(&_BluetoothInterface, SIGNAL(didStateChange (BluetoothData )), - this , SLOT( onStateChange (Model::MBluetooth ))); + connect(&_BluetoothInterface, SIGNAL(didStateChange (BluetoothData )), + this , SLOT( onStateChange (BluetoothData ))); + connect(&_BluetoothInterface, SIGNAL(didDeviceChange(BluetoothDeviceData)), + this , SLOT( onDeviceChange(BluetoothDeviceData))); + connect(this , SIGNAL(didDeviceSelect(QString, QString )), + this , SLOT( onDeviceSelect(QString, QString ))); } -void View::VBluetooth::onStateChange(const Model::MBluetooth &vData) +int View::VBluetooth::rowCount(const QModelIndex &) const { + return _devices.count(); +} + +void View::VBluetooth::reset() { + beginResetModel(); + _devices.clear(); + endResetModel(); +} + +void View::VBluetooth::onStateChange(const BluetoothData &vData) +{ if ( vData.state == MBluetooth::eIS_Local_Error_POST ) { isInvalid( true ); notify( vData.state ); @@ -56,9 +73,9 @@ switch (vData.state) { // The device name is not always available and the interface may be in investigation. - case MBluetooth::eIS_Scan_Found : case MBluetooth::eIS_Scan_NotFound : case MBluetooth::eIS_Scan_Discover : + case MBluetooth::eIS_Scan_Found : deviceAddr (vData.deviceAddr ); deviceName (vData.deviceName ); devicePair (vData.devicePair ); @@ -79,8 +96,37 @@ detailValue (vData.detailValue ); break; - default: + case MBluetooth::eIS_Scan_Start : + reset(); break; + case MBluetooth::eIS_Idle : + case MBluetooth::eIS_Local_Connect : + case MBluetooth::eIS_Local_Error_Invalid : + case MBluetooth::eIS_Local_Error_POST : + case MBluetooth::eIS_Local_Error_Off : + case MBluetooth::eIS_Local_Error_IO : + case MBluetooth::eIS_Local_Error : + case MBluetooth::eIS_Local_Disconnect : + case MBluetooth::eIS_Scan_Reject : + case MBluetooth::eIS_Scan_Stop : + case MBluetooth::eIS_Scan_Done : + case MBluetooth::eIS_Device_Init : + case MBluetooth::eIS_Device_Start : + case MBluetooth::eIS_Device_Connect : + case MBluetooth::eIS_Device_Error_Init : + case MBluetooth::eIS_Device_Error : + case MBluetooth::eIS_Device_Done : + case MBluetooth::eIS_Device_Disconnect : + case MBluetooth::eIS_Service_Start : + case MBluetooth::eIS_Service_Error : + case MBluetooth::eIS_Service_Discover : + case MBluetooth::eIS_Service_Detail : + case MBluetooth::eIS_Service_Detail_Invalid : + case MBluetooth::eIS_Service_Detail_Error : + case MBluetooth::eIS_Service_Detail_Done : + case MBluetooth::eIS_Service_Done : + case MBluetooth::eIS_Close : + break; } error (vData.error ); @@ -89,6 +135,30 @@ notify( vData.state ); } +void View::VBluetooth::onDeviceChange(const BluetoothDeviceData &vDevice) +{ + int row = 0; + while (row < _devices.count()) ++row; + beginInsertRows(QModelIndex(), row, row); + _devices.insert(row, vDevice); + endInsertRows(); + + qDebug() << _devices.count(); + + for (auto device: _devices) { + qDebug() << device.addr << device.name << device.pair; + } + +} + +void View::VBluetooth::onDeviceSelect(const QString &vAddr, const QString &vName) +{ + BluetoothDeviceData data; + data.addr = vAddr; + data.name = vName; + emit _BluetoothInterface.didDeviceSelect(data); +} + QString View::VBluetooth::toText(MBluetooth::InterfaceStates vState) const { QString message; Index: sources/view/settings/VBluetooth.h =================================================================== diff -u -raa8f2c87c14c68d1fda6da2540d47144990a596c -rb252cd2777aadbce2d04aa32cc275f193de0cf52 --- sources/view/settings/VBluetooth.h (.../VBluetooth.h) (revision aa8f2c87c14c68d1fda6da2540d47144990a596c) +++ sources/view/settings/VBluetooth.h (.../VBluetooth.h) (revision b252cd2777aadbce2d04aa32cc275f193de0cf52) @@ -15,7 +15,7 @@ #pragma once // Qt -#include +#include // Project #include "main.h" // Doxygen : do not remove @@ -33,7 +33,7 @@ * \brief The VBluetooth class * \details View for BluetoothInterface. */ -class VBluetooth : public QObject { +class VBluetooth : public QAbstractListModel { Q_OBJECT // friends @@ -58,14 +58,57 @@ PROPERTY(QString , detailName , "" ) PROPERTY(QString , detailValue , "" ) + + // List Model +public: + enum DataRole { + ToStringRole = Qt::DisplayRole , + AddrRole = Qt::UserRole , + NameRole , + PairRole , + }; + Q_ENUM(DataRole) + +private: + BluetoothDeviceListData _devices {}; + int rowCount(const QModelIndex & = QModelIndex()) const; + void reset(); + QVariant data(const QModelIndex &index, int role) const + { + if (index.row() < rowCount()) + switch (role) { + case ToStringRole : return _devices.at(index.row()).toString(); + case AddrRole : return _devices.at(index.row()).addr; + case NameRole : return _devices.at(index.row()).name; + case PairRole : return _devices.at(index.row()).pair; + default: return QVariant(); + } + return QVariant(); + } + + QHash roleNames() const + { + static const QHash roles { + { ToStringRole, "toString" }, + { AddrRole, "addr" }, + { NameRole, "name" }, + { PairRole, "pair" } + }; + return roles; + } + VIEW_DEC_CLASS(VBluetooth) signals: + void didDeviceSelect(const QString &vAddr, const QString &vName); private slots: - void onStateChange (const Model::MBluetooth &vData); + void onStateChange (const BluetoothData &vData ); + void onDeviceChange (const BluetoothDeviceData &vDevice); - QString toText ( Model::MBluetooth::InterfaceStates vState) const; + void onDeviceSelect(const QString &vAddr, const QString &vName); + + QString toText (Model::MBluetooth::InterfaceStates vState) const; void notify (Model::MBluetooth::InterfaceStates vState); public slots: