device.cpp Example File

btscanner/device.cpp

  /****************************************************************************
  **
  ** Copyright (C) 2017 The Qt Company Ltd.
  ** Contact: https://www.qt.io/licensing/
  **
  ** This file is part of the QtBluetooth module of the Qt Toolkit.
  **
  ** $QT_BEGIN_LICENSE:BSD$
  ** Commercial License Usage
  ** Licensees holding valid commercial Qt licenses may use this file in
  ** accordance with the commercial license agreement provided with the
  ** Software or, alternatively, in accordance with the terms contained in
  ** a written agreement between you and The Qt Company. For licensing terms
  ** and conditions see https://www.qt.io/terms-conditions. For further
  ** information use the contact form at https://www.qt.io/contact-us.
  **
  ** BSD License Usage
  ** Alternatively, 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 The Qt Company Ltd 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."
  **
  ** $QT_END_LICENSE$
  **
  ****************************************************************************/

  #include "device.h"
  #include "service.h"

  #include <qbluetoothaddress.h>
  #include <qbluetoothdevicediscoveryagent.h>
  #include <qbluetoothlocaldevice.h>
  #include <QMenu>
  #include <QDebug>

  DeviceDiscoveryDialog::DeviceDiscoveryDialog(QWidget *parent)
  :   QDialog(parent), localDevice(new QBluetoothLocalDevice),
      ui(new Ui_DeviceDiscovery)
  {
      ui->setupUi(this);

      /*
       * In case of multiple Bluetooth adapters it is possible to set adapter
       * which will be used. Example code:
       *
       * QBluetoothAddress address("XX:XX:XX:XX:XX:XX");
       * discoveryAgent = new QBluetoothDeviceDiscoveryAgent(address);
       *
       **/

      discoveryAgent = new QBluetoothDeviceDiscoveryAgent();

      connect(ui->inquiryType, SIGNAL(toggled(bool)), this, SLOT(setGeneralUnlimited(bool)));
      connect(ui->scan, SIGNAL(clicked()), this, SLOT(startScan()));

      connect(discoveryAgent, SIGNAL(deviceDiscovered(QBluetoothDeviceInfo)),
              this, SLOT(addDevice(QBluetoothDeviceInfo)));
      connect(discoveryAgent, SIGNAL(finished()), this, SLOT(scanFinished()));

      connect(ui->list, SIGNAL(itemActivated(QListWidgetItem*)),
              this, SLOT(itemActivated(QListWidgetItem*)));

      connect(localDevice, SIGNAL(hostModeStateChanged(QBluetoothLocalDevice::HostMode)),
              this, SLOT(hostModeStateChanged(QBluetoothLocalDevice::HostMode)));

      hostModeStateChanged(localDevice->hostMode());
      // add context menu for devices to be able to pair device
      ui->list->setContextMenuPolicy(Qt::CustomContextMenu);
      connect(ui->list, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(displayPairingMenu(QPoint)));
      connect(localDevice, SIGNAL(pairingFinished(QBluetoothAddress,QBluetoothLocalDevice::Pairing))
          , this, SLOT(pairingDone(QBluetoothAddress,QBluetoothLocalDevice::Pairing)));

  }

  DeviceDiscoveryDialog::~DeviceDiscoveryDialog()
  {
      delete discoveryAgent;
  }

  void DeviceDiscoveryDialog::addDevice(const QBluetoothDeviceInfo &info)
  {
      QString label = QString("%1 %2").arg(info.address().toString()).arg(info.name());
      QList<QListWidgetItem *> items = ui->list->findItems(label, Qt::MatchExactly);
      if (items.empty()) {
          QListWidgetItem *item = new QListWidgetItem(label);
          QBluetoothLocalDevice::Pairing pairingStatus = localDevice->pairingStatus(info.address());
          if (pairingStatus == QBluetoothLocalDevice::Paired || pairingStatus == QBluetoothLocalDevice::AuthorizedPaired )
              item->setTextColor(QColor(Qt::green));
          else
              item->setTextColor(QColor(Qt::black));

          ui->list->addItem(item);
      }

  }

  void DeviceDiscoveryDialog::startScan()
  {
      discoveryAgent->start();
      ui->scan->setEnabled(false);
      ui->inquiryType->setEnabled(false);
  }

  void DeviceDiscoveryDialog::scanFinished()
  {
      ui->scan->setEnabled(true);
      ui->inquiryType->setEnabled(true);
  }

  void DeviceDiscoveryDialog::setGeneralUnlimited(bool unlimited)
  {
      if (unlimited)
          discoveryAgent->setInquiryType(QBluetoothDeviceDiscoveryAgent::GeneralUnlimitedInquiry);
      else
          discoveryAgent->setInquiryType(QBluetoothDeviceDiscoveryAgent::LimitedInquiry);
  }

  void DeviceDiscoveryDialog::itemActivated(QListWidgetItem *item)
  {
      QString text = item->text();

      int index = text.indexOf(' ');

      if (index == -1)
          return;

      QBluetoothAddress address(text.left(index));
      QString name(text.mid(index + 1));

      ServiceDiscoveryDialog d(name, address);
      d.exec();
  }

  void DeviceDiscoveryDialog::on_discoverable_clicked(bool clicked)
  {
      if (clicked)
          localDevice->setHostMode(QBluetoothLocalDevice::HostDiscoverable);
      else
          localDevice->setHostMode(QBluetoothLocalDevice::HostConnectable);
  }

  void DeviceDiscoveryDialog::on_power_clicked(bool clicked)
  {
      if (clicked)
          localDevice->powerOn();
      else
          localDevice->setHostMode(QBluetoothLocalDevice::HostPoweredOff);
  }

  void DeviceDiscoveryDialog::hostModeStateChanged(QBluetoothLocalDevice::HostMode mode)
  {
      if (mode != QBluetoothLocalDevice::HostPoweredOff)
          ui->power->setChecked(true);
      else
         ui->power->setChecked( false);

      if (mode == QBluetoothLocalDevice::HostDiscoverable)
          ui->discoverable->setChecked(true);
      else
          ui->discoverable->setChecked(false);

      bool on = !(mode == QBluetoothLocalDevice::HostPoweredOff);

      ui->scan->setEnabled(on);
      ui->discoverable->setEnabled(on);
  }
  void DeviceDiscoveryDialog::displayPairingMenu(const QPoint &pos)
  {
      if (ui->list->count() == 0)
          return;
      QMenu menu(this);
      QAction *pairAction = menu.addAction("Pair");
      QAction *removePairAction = menu.addAction("Remove Pairing");
      QAction *chosenAction = menu.exec(ui->list->viewport()->mapToGlobal(pos));
      QListWidgetItem *currentItem = ui->list->currentItem();

      QString text = currentItem->text();
      int index = text.indexOf(' ');
      if (index == -1)
          return;

      QBluetoothAddress address (text.left(index));
      if (chosenAction == pairAction) {
          localDevice->requestPairing(address, QBluetoothLocalDevice::Paired);
      } else if (chosenAction == removePairAction) {
          localDevice->requestPairing(address, QBluetoothLocalDevice::Unpaired);
      }
  }
  void DeviceDiscoveryDialog::pairingDone(const QBluetoothAddress &address, QBluetoothLocalDevice::Pairing pairing)
  {
      QList<QListWidgetItem *> items = ui->list->findItems(address.toString(), Qt::MatchContains);

      if (pairing == QBluetoothLocalDevice::Paired || pairing == QBluetoothLocalDevice::AuthorizedPaired ) {
          for (int var = 0; var < items.count(); ++var) {
              QListWidgetItem *item = items.at(var);
              item->setTextColor(QColor(Qt::green));
          }
      } else {
          for (int var = 0; var < items.count(); ++var) {
              QListWidgetItem *item = items.at(var);
              item->setTextColor(QColor(Qt::red));
          }
      }
  }