diff options
-rw-r--r-- | packaging/android/build.sh | 26 | ||||
-rw-r--r-- | qt-ui/btdeviceselectiondialog.cpp | 214 | ||||
-rw-r--r-- | qt-ui/btdeviceselectiondialog.h | 7 | ||||
-rw-r--r-- | qt-ui/btdeviceselectiondialog.ui | 26 | ||||
-rw-r--r-- | qtserialbluetooth.cpp | 2 |
5 files changed, 202 insertions, 73 deletions
diff --git a/packaging/android/build.sh b/packaging/android/build.sh index b9565ea67..c0d1031ac 100644 --- a/packaging/android/build.sh +++ b/packaging/android/build.sh @@ -1,6 +1,6 @@ #!/bin/bash set -e - +PLATFORM=$(uname) # (trick to get the absolute path, either if we're called with a # absolute path or a relative path) pushd $(dirname $0)/../../ @@ -8,9 +8,15 @@ export SUBSURFACE_SOURCE=$PWD popd # Configure where we can find things here export ANDROID_NDK_ROOT=$SUBSURFACE_SOURCE/../android-ndk-r10e -export ANDROID_SDK_ROOT=$SUBSURFACE_SOURCE/../android-sdk-linux export QT5_ANDROID=$SUBSURFACE_SOURCE/../Qt/5.5 -export ANDROID_NDK_HOST=linux-x86 +export ANDROID_SDK_ROOT=$SUBSURFACE_SOURCE/../android-sdk-linux +if [ $PLATFORM = Darwin ] ; then + export ANDROID_SDK_ROOT=$SUBSURFACE_SOURCE/../android-sdk-macosx + export ANDROID_NDK_HOST=darwin-x86_64 +else + export ANDROID_SDK_ROOT=$SUBSURFACE_SOURCE/../android-sdk-linux + export ANDROID_NDK_HOST=linux-x86 +fi # Which versions are we building against? SQLITE_VERSION=3081002 @@ -53,7 +59,12 @@ export CPPFLAGS="--sysroot=${SYSROOT}" export CXXFLAGS="--sysroot=${SYSROOT}" # Junk needed for qt-android-cmake export ANDROID_STANDALONE_TOOLCHAIN=${BUILDROOT}/ndk-$ARCH -export JAVA_HOME=/usr +if [ $PLATFORM = Darwin ] ; then + JAVA_HOME=$(/usr/libexec/java_home) + export JAVA_HOME +else + export JAVA_HOME=/usr +fi if [ ! -e sqlite-autoconf-${SQLITE_VERSION}.tar.gz ] ; then wget http://www.sqlite.org/2015/sqlite-autoconf-${SQLITE_VERSION}.tar.gz @@ -239,8 +250,13 @@ else fi # somehting in the qt-android-cmake-thingies mangles your path, so thats why we need to hard-code ant and pkg-config here. +if [ $PLATFORM = Darwin ] ; then + ANT=/usr/local/bin/ant +else + ANT=/usr/bin/ant +fi cmake $MOBILE_CMAKE \ - -DQT_ANDROID_ANT=/usr/bin/ant \ + -DQT_ANDROID_ANT=${ANT} \ -DPKG_CONFIG_EXECUTABLE=/usr/bin/pkg-config \ -DQT_ANDROID_SDK_ROOT=$ANDROID_SDK_ROOT \ -DQT_ANDROID_NDK_ROOT=$ANDROID_NDK_ROOT \ diff --git a/qt-ui/btdeviceselectiondialog.cpp b/qt-ui/btdeviceselectiondialog.cpp index 9b97da3a9..007fe940e 100644 --- a/qt-ui/btdeviceselectiondialog.cpp +++ b/qt-ui/btdeviceselectiondialog.cpp @@ -11,14 +11,6 @@ BtDeviceSelectionDialog::BtDeviceSelectionDialog(QWidget *parent) : localDevice(new QBluetoothLocalDevice), ui(new Ui::BtDeviceSelectionDialog) { - // Check if Bluetooth is available on this device - if (!localDevice->isValid()) { - QMessageBox::warning(this, tr("Warning"), - "This should never happen, please contact the Subsurface developers " - "and tell them that the Bluetooth download mode doesn't work."); - return; - } - ui->setupUi(this); // Quit button callbacks @@ -29,36 +21,41 @@ BtDeviceSelectionDialog::BtDeviceSelectionDialog(QWidget *parent) : // Disable the save button because there is no device selected ui->save->setEnabled(false); - connect(ui->discoveredDevicesList, SIGNAL(itemActivated(QListWidgetItem*)), - this, SLOT(itemActivated(QListWidgetItem*))); + connect(ui->discoveredDevicesList, SIGNAL(itemClicked(QListWidgetItem*)), + this, SLOT(itemClicked(QListWidgetItem*))); - // Set UI information about the local device - ui->deviceAddress->setText(localDevice->address().toString()); - ui->deviceName->setText(localDevice->name()); + // Populate the list with local bluetooth devices + QList<QBluetoothHostInfo> localAvailableDevices = localDevice->allDevices(); + int availableDevicesSize = localAvailableDevices.size(); - connect(localDevice, SIGNAL(hostModeStateChanged(QBluetoothLocalDevice::HostMode)), - this, SLOT(hostModeStateChanged(QBluetoothLocalDevice::HostMode))); + if (availableDevicesSize > 1) { + int defaultDeviceIndex = -1; - // Initialize the state of the local device and activate/deactive the scan button - hostModeStateChanged(localDevice->hostMode()); + for (int it = 0; it < availableDevicesSize; it++) { + QBluetoothHostInfo localAvailableDevice = localAvailableDevices.at(it); + ui->localSelectedDevice->addItem(localAvailableDevice.name(), + QVariant::fromValue(localAvailableDevice.address())); - // Intialize the discovery agent - remoteDeviceDiscoveryAgent = new QBluetoothDeviceDiscoveryAgent(); + if (localDevice->address() == localAvailableDevice.address()) + defaultDeviceIndex = it; + } - connect(remoteDeviceDiscoveryAgent, SIGNAL(deviceDiscovered(QBluetoothDeviceInfo)), - this, SLOT(addRemoteDevice(QBluetoothDeviceInfo))); - connect(remoteDeviceDiscoveryAgent, SIGNAL(finished()), - this, SLOT(remoteDeviceScanFinished())); + // Positionate the current index to the default device and register to index changes events + ui->localSelectedDevice->setCurrentIndex(defaultDeviceIndex); + connect(ui->localSelectedDevice, SIGNAL(currentIndexChanged(int)), + this, SLOT(localDeviceChanged(int))); + } else { + // If there is only one local Bluetooth adapter hide the combobox and the label + ui->selectDeviceLabel->hide(); + ui->localSelectedDevice->hide(); + } - // Add context menu for devices to be able to pair them - ui->discoveredDevicesList->setContextMenuPolicy(Qt::CustomContextMenu); - connect(ui->discoveredDevicesList, SIGNAL(customContextMenuRequested(QPoint)), - this, SLOT(displayPairingMenu(QPoint))); - connect(localDevice, SIGNAL(pairingFinished(QBluetoothAddress, QBluetoothLocalDevice::Pairing)), - this, SLOT(pairingFinished(QBluetoothAddress, QBluetoothLocalDevice::Pairing))); + // Update the UI information about the local device + updateLocalDeviceInformation(); - connect(localDevice, SIGNAL(error(QBluetoothLocalDevice::Error)), - this, SLOT(error(QBluetoothLocalDevice::Error))); + // Initialize the device discovery agent + if (localDevice->isValid()) + initializeDeviceDiscoveryAgent(); } BtDeviceSelectionDialog::~BtDeviceSelectionDialog() @@ -86,6 +83,12 @@ void BtDeviceSelectionDialog::on_save_clicked() // Save the selected device selectedRemoteDeviceInfo = QSharedPointer<QBluetoothDeviceInfo>(new QBluetoothDeviceInfo(remoteDeviceInfo)); + if (remoteDeviceDiscoveryAgent->isActive()) { + // Stop the SDP agent if the clear button is pressed and enable the Scan button + remoteDeviceDiscoveryAgent->stop(); + ui->scan->setEnabled(true); + } + // Close the device selection dialog and set the result code to Accepted accept(); } @@ -95,6 +98,12 @@ void BtDeviceSelectionDialog::on_clear_clicked() ui->dialogStatus->setText("Remote devices list was cleaned."); ui->discoveredDevicesList->clear(); ui->save->setEnabled(false); + + if (remoteDeviceDiscoveryAgent->isActive()) { + // Stop the SDP agent if the clear button is pressed and enable the Scan button + remoteDeviceDiscoveryAgent->stop(); + ui->scan->setEnabled(true); + } } void BtDeviceSelectionDialog::on_scan_clicked() @@ -108,21 +117,6 @@ void BtDeviceSelectionDialog::remoteDeviceScanFinished() { ui->dialogStatus->setText("Scanning finished."); ui->scan->setEnabled(true); - -#if defined(Q_OS_ANDROID) - // Check if there is a selected device and activate the Save button if it is paired - QListWidgetItem *currentItem = ui->discoveredDevicesList->currentItem(); - - if (currentItem != NULL) { - QBluetoothDeviceInfo remoteDeviceInfo = currentItem->data(Qt::UserRole).value<QBluetoothDeviceInfo>(); - QBluetoothLocalDevice::Pairing pairingStatus = localDevice->pairingStatus(remoteDeviceInfo.address()); - - if (pairingStatus != QBluetoothLocalDevice::Unpaired) { - ui->save->setEnabled(true); - ui->dialogStatus->setText("Scanning finished. You can press the Save button and start the download."); - } - } -#endif } void BtDeviceSelectionDialog::hostModeStateChanged(QBluetoothLocalDevice::HostMode mode) @@ -137,12 +131,12 @@ void BtDeviceSelectionDialog::hostModeStateChanged(QBluetoothLocalDevice::HostMo void BtDeviceSelectionDialog::addRemoteDevice(const QBluetoothDeviceInfo &remoteDeviceInfo) { - QString deviceLable = QString("%1 (%2)").arg(remoteDeviceInfo.name()).arg(remoteDeviceInfo.address().toString()); - QList<QListWidgetItem *> itemsWithSameSignature = ui->discoveredDevicesList->findItems(deviceLable, Qt::MatchStartsWith); + QString deviceLabel = QString("%1 (%2)").arg(remoteDeviceInfo.name()).arg(remoteDeviceInfo.address().toString()); + QList<QListWidgetItem *> itemsWithSameSignature = ui->discoveredDevicesList->findItems(deviceLabel, Qt::MatchStartsWith); // Check if the remote device is already in the list if (itemsWithSameSignature.empty()) { - QListWidgetItem *item = new QListWidgetItem(deviceLable); + QListWidgetItem *item = new QListWidgetItem(deviceLabel); QBluetoothLocalDevice::Pairing pairingStatus = localDevice->pairingStatus(remoteDeviceInfo.address()); item->setData(Qt::UserRole, QVariant::fromValue(remoteDeviceInfo)); @@ -161,7 +155,7 @@ void BtDeviceSelectionDialog::addRemoteDevice(const QBluetoothDeviceInfo &remote } } -void BtDeviceSelectionDialog::itemActivated(QListWidgetItem *item) +void BtDeviceSelectionDialog::itemClicked(QListWidgetItem *item) { QBluetoothDeviceInfo remoteDeviceInfo = item->data(Qt::UserRole).value<QBluetoothDeviceInfo>(); QBluetoothLocalDevice::Pairing pairingStatus = localDevice->pairingStatus(remoteDeviceInfo.address()); @@ -171,19 +165,36 @@ void BtDeviceSelectionDialog::itemActivated(QListWidgetItem *item) .arg(remoteDeviceInfo.address().toString())); ui->save->setEnabled(false); } else { -#if defined(Q_OS_ANDROID) - if (remoteDeviceDiscoveryAgent->isActive()) { - ui->dialogStatus->setText(QString("The device %1 can be used for connection. Wait until the device scanning is done and press the Save button.") - .arg(remoteDeviceInfo.address().toString())); - return; - } -#endif ui->dialogStatus->setText(QString("The device %1 can be used for connection. You can press the Save button.") .arg(remoteDeviceInfo.address().toString())); ui->save->setEnabled(true); } } +void BtDeviceSelectionDialog::localDeviceChanged(int index) +{ + QBluetoothAddress localDeviceSelectedAddress = ui->localSelectedDevice->itemData(index, Qt::UserRole).value<QBluetoothAddress>(); + + // Delete the old localDevice + if (localDevice) + delete localDevice; + + // Create a new local device using the selected address + localDevice = new QBluetoothLocalDevice(localDeviceSelectedAddress); + + ui->dialogStatus->setText(QString("The local device was changed.")); + + // Clear the discovered devices list + on_clear_clicked(); + + // Update the UI information about the local device + updateLocalDeviceInformation(); + + // Initialize the device discovery agent + if (localDevice->isValid()) + initializeDeviceDiscoveryAgent(); +} + void BtDeviceSelectionDialog::displayPairingMenu(const QPoint &pos) { QMenu menu(this); @@ -261,7 +272,28 @@ void BtDeviceSelectionDialog::pairingFinished(const QBluetoothAddress &address, void BtDeviceSelectionDialog::error(QBluetoothLocalDevice::Error error) { ui->dialogStatus->setText(QString("Local device error: %1.") - .arg((error == QBluetoothLocalDevice::PairingError)? "Pairing error" : "Unknown error")); + .arg((error == QBluetoothLocalDevice::PairingError)? "Pairing error. If the remote device requires a custom PIN code, " + "please try to pair the devices using your operating system. " + : "Unknown error")); +} + +void BtDeviceSelectionDialog::deviceDiscoveryError(QBluetoothDeviceDiscoveryAgent::Error error) +{ + QString errorDescription; + + switch (error) { + case QBluetoothDeviceDiscoveryAgent::PoweredOffError: + errorDescription = QString("The Bluetooth adaptor is powered off, power it on before doing discovery."); + break; + case QBluetoothDeviceDiscoveryAgent::InputOutputError: + errorDescription = QString("Writing or reading from the device resulted in an error."); + break; + default: + errorDescription = QString("An unknown error has occurred."); + break; + } + + ui->dialogStatus->setText(QString("Device discovery error: %1.").arg(errorDescription)); } QString BtDeviceSelectionDialog::getSelectedDeviceAddress() @@ -281,3 +313,69 @@ QString BtDeviceSelectionDialog::getSelectedDeviceName() return QString(); } + +void BtDeviceSelectionDialog::updateLocalDeviceInformation() +{ + // Check if the selected Bluetooth device can be accessed + if (!localDevice->isValid()) { + QString na = QString("Not available"); + + // Update the UI information + ui->deviceAddress->setText(na); + ui->deviceName->setText(na); + + // Announce the user that there is a problem with the selected local Bluetooth adapter + ui->dialogStatus->setText(QString("The local Bluetooth adapter cannot be accessed.")); + + // Disable the buttons + ui->save->setEnabled(false); + ui->scan->setEnabled(false); + ui->clear->setEnabled(false); + ui->changeDeviceState->setEnabled(false); + + return; + } + + // Set UI information about the local device + ui->deviceAddress->setText(localDevice->address().toString()); + ui->deviceName->setText(localDevice->name()); + + connect(localDevice, SIGNAL(hostModeStateChanged(QBluetoothLocalDevice::HostMode)), + this, SLOT(hostModeStateChanged(QBluetoothLocalDevice::HostMode))); + + // Initialize the state of the local device and activate/deactive the scan button + hostModeStateChanged(localDevice->hostMode()); + + // Add context menu for devices to be able to pair them + ui->discoveredDevicesList->setContextMenuPolicy(Qt::CustomContextMenu); + connect(ui->discoveredDevicesList, SIGNAL(customContextMenuRequested(QPoint)), + this, SLOT(displayPairingMenu(QPoint))); + connect(localDevice, SIGNAL(pairingFinished(QBluetoothAddress, QBluetoothLocalDevice::Pairing)), + this, SLOT(pairingFinished(QBluetoothAddress, QBluetoothLocalDevice::Pairing))); + + connect(localDevice, SIGNAL(error(QBluetoothLocalDevice::Error)), + this, SLOT(error(QBluetoothLocalDevice::Error))); +} + +void BtDeviceSelectionDialog::initializeDeviceDiscoveryAgent() +{ + // Intialize the discovery agent + remoteDeviceDiscoveryAgent = new QBluetoothDeviceDiscoveryAgent(localDevice->address()); + + // Test if the discovery agent was successfully created + if (remoteDeviceDiscoveryAgent->error() == QBluetoothDeviceDiscoveryAgent::InvalidBluetoothAdapterError) { + ui->dialogStatus->setText(QString("The device discovery agent was not created because the %1 address does not " + "match the physical adapter address of any local Bluetooth device.") + .arg(localDevice->address().toString())); + ui->scan->setEnabled(false); + ui->clear->setEnabled(false); + return; + } + + connect(remoteDeviceDiscoveryAgent, SIGNAL(deviceDiscovered(QBluetoothDeviceInfo)), + this, SLOT(addRemoteDevice(QBluetoothDeviceInfo))); + connect(remoteDeviceDiscoveryAgent, SIGNAL(finished()), + this, SLOT(remoteDeviceScanFinished())); + connect(remoteDeviceDiscoveryAgent, SIGNAL(error(QBluetoothDeviceDiscoveryAgent::Error)), + this, SLOT(deviceDiscoveryError(QBluetoothDeviceDiscoveryAgent::Error))); +} diff --git a/qt-ui/btdeviceselectiondialog.h b/qt-ui/btdeviceselectiondialog.h index 0a486635f..b6c34e8b8 100644 --- a/qt-ui/btdeviceselectiondialog.h +++ b/qt-ui/btdeviceselectiondialog.h @@ -33,16 +33,21 @@ private slots: void remoteDeviceScanFinished(); void hostModeStateChanged(QBluetoothLocalDevice::HostMode mode); void addRemoteDevice(const QBluetoothDeviceInfo &remoteDeviceInfo); - void itemActivated(QListWidgetItem *item); + void itemClicked(QListWidgetItem *item); void displayPairingMenu(const QPoint &pos); void pairingFinished(const QBluetoothAddress &address,QBluetoothLocalDevice::Pairing pairing); void error(QBluetoothLocalDevice::Error error); + void deviceDiscoveryError(QBluetoothDeviceDiscoveryAgent::Error error); + void localDeviceChanged(int); private: Ui::BtDeviceSelectionDialog *ui; QBluetoothLocalDevice *localDevice; QBluetoothDeviceDiscoveryAgent *remoteDeviceDiscoveryAgent; QSharedPointer<QBluetoothDeviceInfo> selectedRemoteDeviceInfo; + + void updateLocalDeviceInformation(); + void initializeDeviceDiscoveryAgent(); }; #endif // BTDEVICESELECTIONDIALOG_H diff --git a/qt-ui/btdeviceselectiondialog.ui b/qt-ui/btdeviceselectiondialog.ui index c28bdcbe8..95c09d1c7 100644 --- a/qt-ui/btdeviceselectiondialog.ui +++ b/qt-ui/btdeviceselectiondialog.ui @@ -122,35 +122,35 @@ <bool>false</bool> </property> <layout class="QFormLayout" name="formLayout_2"> - <item row="0" column="0"> - <widget class="QLabel" name="deviceNameLable"> + <item row="2" column="0"> + <widget class="QLabel" name="deviceNameLabel"> <property name="text"> <string>Name: </string> </property> </widget> </item> - <item row="0" column="1"> + <item row="2" column="1"> <widget class="QLineEdit" name="deviceName"> <property name="readOnly"> <bool>true</bool> </property> </widget> </item> - <item row="1" column="0"> - <widget class="QLabel" name="deviceAddressLable"> + <item row="3" column="0"> + <widget class="QLabel" name="deviceAddressLabel"> <property name="text"> <string>Address:</string> </property> </widget> </item> - <item row="1" column="1"> + <item row="3" column="1"> <widget class="QLineEdit" name="deviceAddress"> <property name="readOnly"> <bool>true</bool> </property> </widget> </item> - <item row="2" column="1"> + <item row="4" column="1"> <widget class="QCheckBox" name="deviceState"> <property name="enabled"> <bool>false</bool> @@ -175,7 +175,7 @@ </property> </widget> </item> - <item row="3" column="1"> + <item row="5" column="1"> <widget class="QPushButton" name="changeDeviceState"> <property name="sizePolicy"> <sizepolicy hsizetype="Expanding" vsizetype="Minimum"> @@ -194,6 +194,16 @@ </property> </widget> </item> + <item row="1" column="1"> + <widget class="QComboBox" name="localSelectedDevice"/> + </item> + <item row="1" column="0"> + <widget class="QLabel" name="selectDeviceLabel"> + <property name="text"> + <string>Select device:</string> + </property> + </widget> + </item> </layout> </widget> </item> diff --git a/qtserialbluetooth.cpp b/qtserialbluetooth.cpp index 95f3611cf..5a982d68b 100644 --- a/qtserialbluetooth.cpp +++ b/qtserialbluetooth.cpp @@ -80,7 +80,7 @@ static int qt_serial_open(serial_t **out, dc_context_t *context, const char* dev loop.exec(); } } -#elif defined(Q_OS_ANDROID) +#elif defined(Q_OS_ANDROID) || (QT_VERSION >= 0x050500 && defined(Q_OS_MAC)) // Try to connect to the device using the uuid of the Serial Port Profile service QBluetoothAddress remoteDeviceAddress(devaddr); serial_port->socket->connectToService(remoteDeviceAddress, QBluetoothUuid(QBluetoothUuid::SerialPort)); |