BioSignalPi  v2
remoteselector.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd.
4 ** Contact: http://www.qt.io/licensing/
5 **
6 ** This file is part of the QtBluetooth module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:BSD$
9 ** You may use this file under the terms of the BSD license as follows:
10 **
11 ** "Redistribution and use in source and binary forms, with or without
12 ** modification, are permitted provided that the following conditions are
13 ** met:
14 ** * Redistributions of source code must retain the above copyright
15 ** notice, this list of conditions and the following disclaimer.
16 ** * Redistributions in binary form must reproduce the above copyright
17 ** notice, this list of conditions and the following disclaimer in
18 ** the documentation and/or other materials provided with the
19 ** distribution.
20 ** * Neither the name of The Qt Company Ltd nor the names of its
21 ** contributors may be used to endorse or promote products derived
22 ** from this software without specific prior written permission.
23 **
24 **
25 ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26 ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27 ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28 ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
29 ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30 ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
31 ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32 ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33 ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34 ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35 ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
36 **
37 ** $QT_END_LICENSE$
38 **
39 ****************************************************************************/
40 
41 #include "remoteselector.h"
42 #include "ui_remoteselector.h"
43 
44 #include <qbluetoothdeviceinfo.h>
45 #include <qbluetoothaddress.h>
46 #include <qbluetoothtransferrequest.h>
47 #include <qbluetoothtransferreply.h>
48 #include <qbluetoothlocaldevice.h>
49 
50 #include <QMovie>
51 #include <QMessageBox>
52 #include <QFileDialog>
53 #include <QCheckBox>
54 
55 #include "progress.h"
56 #include "pindisplay.h"
57 
58 QT_USE_NAMESPACE
59 
61 : QDialog(parent), ui(new Ui::RemoteSelector),
62  m_localDevice(new QBluetoothLocalDevice), m_pindisplay(0),
63  m_pairingError(false)
64 {
65  ui->setupUi(this);
66 
67  //Using default Bluetooth adapter
68  QBluetoothAddress adapterAddress = m_localDevice->address();
69 
70  /*
71  * In case of multiple Bluetooth adapters it is possible to
72  * set which adapter will be used by providing MAC Address.
73  * Example code:
74  *
75  * QBluetoothAddress adapterAddress("XX:XX:XX:XX:XX:XX");
76  * m_discoveryAgent = new QBluetoothServiceDiscoveryAgent(adapterAddress);
77  */
78 
79  m_discoveryAgent = new QBluetoothServiceDiscoveryAgent(adapterAddress);
80 
81  connect(m_discoveryAgent, SIGNAL(serviceDiscovered(QBluetoothServiceInfo)),
82  this, SLOT(serviceDiscovered(QBluetoothServiceInfo)));
83  connect(m_discoveryAgent, SIGNAL(finished()), this, SLOT(discoveryFinished()));
84  connect(m_discoveryAgent, SIGNAL(canceled()), this, SLOT(discoveryFinished()));
85 
86  ui->remoteDevices->setColumnWidth(3, 75);
87  ui->remoteDevices->setColumnWidth(4, 100);
88 
89  connect(m_localDevice, SIGNAL(pairingDisplayPinCode(QBluetoothAddress,QString)),
90  this, SLOT(displayPin(QBluetoothAddress,QString)));
91  connect(m_localDevice, SIGNAL(pairingDisplayConfirmation(QBluetoothAddress,QString)),
92  this, SLOT(displayConfirmation(QBluetoothAddress,QString)));
93  connect(m_localDevice, SIGNAL(pairingFinished(QBluetoothAddress,QBluetoothLocalDevice::Pairing)),
94  this, SLOT(pairingFinished(QBluetoothAddress,QBluetoothLocalDevice::Pairing)));
95  connect(m_localDevice, SIGNAL(error(QBluetoothLocalDevice::Error)),
96  this, SLOT(pairingError(QBluetoothLocalDevice::Error)));
97 
98  ui->busyWidget->setMovie(new QMovie(":/icons/busy.gif"));
99  ui->busyWidget->movie()->start();
100 
101  ui->pairingBusy->setMovie(new QMovie(":/icons/pairing.gif"));
102  ui->pairingBusy->hide();
103 
104  ui->remoteDevices->clearContents();
105  ui->remoteDevices->setRowCount(0);
106 }
107 
109 {
110  delete ui;
111  delete m_discoveryAgent;
112  delete m_localDevice;
113 }
114 
115 void RemoteSelector::startDiscovery(const QBluetoothUuid &uuid)
116 {
117  ui->stopButton->setDisabled(false);
118  if (m_discoveryAgent->isActive())
119  m_discoveryAgent->stop();
120 
121  m_discoveryAgent->setUuidFilter(uuid);
122  m_discoveryAgent->start();
123 
124  if (!m_discoveryAgent->isActive() ||
125  m_discoveryAgent->error() != QBluetoothServiceDiscoveryAgent::NoError) {
126  ui->status->setText(tr("Cannot find remote services."));
127  } else {
128  ui->status->setText(tr("Scanning..."));
129  ui->busyWidget->show();
130  ui->busyWidget->movie()->start();
131  }
132 }
133 
134 QBluetoothServiceInfo RemoteSelector::service() const
135 {
136  return m_service;
137 }
138 
139 void RemoteSelector::serviceDiscovered(const QBluetoothServiceInfo &serviceInfo)
140 {
141 #if 0
142  qDebug() << "Discovered service on"
143  << serviceInfo.device().name() << serviceInfo.device().address().toString();
144  qDebug() << "\tService name:" << serviceInfo.serviceName();
145  qDebug() << "\tDescription:"
146  << serviceInfo.attribute(QBluetoothServiceInfo::ServiceDescription).toString();
147  qDebug() << "\tProvider:"
148  << serviceInfo.attribute(QBluetoothServiceInfo::ServiceProvider).toString();
149  qDebug() << "\tL2CAP protocol service multiplexer:"
150  << serviceInfo.protocolServiceMultiplexer();
151  qDebug() << "\tRFCOMM server channel:" << serviceInfo.serverChannel();
152 #endif
153 
154  QString remoteName;
155  if (serviceInfo.device().name().isEmpty())
156  remoteName = serviceInfo.device().address().toString();
157  else
158  remoteName = serviceInfo.device().name();
159 
160 // QListWidgetItem *item =
161 // new QListWidgetItem(QString::fromLatin1("%1\t%2\t%3").arg(serviceInfo.device().address().toString(),
162 // serviceInfo.device().name(), serviceInfo.serviceName()));
163 
164  QMutableMapIterator<int, QBluetoothServiceInfo> i(m_discoveredServices);
165  while (i.hasNext()){
166  i.next();
167  if (serviceInfo.device().address() == i.value().device().address()){
168  i.setValue(serviceInfo);
169  return;
170  }
171  }
172 
173  int row = ui->remoteDevices->rowCount();
174  ui->remoteDevices->insertRow(row);
175  QTableWidgetItem *item = new QTableWidgetItem(serviceInfo.device().address().toString());
176  ui->remoteDevices->setItem(row, 0, item);
177  item = new QTableWidgetItem(serviceInfo.device().name());
178  ui->remoteDevices->setItem(row, 1, item);
179  item = new QTableWidgetItem(serviceInfo.serviceName());
180 
181  ui->remoteDevices->setItem(row, 2, item);
182 
183  QBluetoothLocalDevice::Pairing p;
184 
185  p = m_localDevice->pairingStatus(serviceInfo.device().address());
186 
187  ui->remoteDevices->blockSignals(true);
188 
189  item = new QTableWidgetItem();
190  if ((p&QBluetoothLocalDevice::Paired) || (p&QBluetoothLocalDevice::AuthorizedPaired))
191  item->setCheckState(Qt::Checked);
192  else
193  item->setCheckState(Qt::Unchecked);
194  ui->remoteDevices->setItem(row, 3, item);
195 
196  item = new QTableWidgetItem();
197  if (p&QBluetoothLocalDevice::AuthorizedPaired)
198  item->setCheckState(Qt::Checked);
199  else
200  item->setCheckState(Qt::Unchecked);
201 
202  ui->remoteDevices->setItem(row, 4, item);
203 
204  ui->remoteDevices->blockSignals(false);
205 
206 
207  m_discoveredServices.insert(row, serviceInfo);
208 }
209 
210 void RemoteSelector::discoveryFinished()
211 {
212  ui->status->setText(tr("Select the device to send to."));
213  ui->stopButton->setDisabled(true);
214  ui->busyWidget->movie()->stop();
215  ui->busyWidget->hide();
216 }
217 
219 {
220  startDiscovery(QBluetoothUuid(QBluetoothUuid::ObexObjectPush));
221 }
222 
223 void RemoteSelector::on_refreshPB_clicked()
224 {
225  startDiscovery();
226  ui->stopButton->setDisabled(false);
227 }
228 
229 void RemoteSelector::on_fileSelectPB_clicked()
230 {
231  ui->fileName->setText(QFileDialog::getOpenFileName());
232  if (m_service.isValid())
233  ui->sendButton->setDisabled(false);
234 }
235 
236 void RemoteSelector::on_sendButton_clicked()
237 {
238  QBluetoothTransferManager mgr;
239  QBluetoothTransferRequest req(m_service.device().address());
240 
241  m_file = new QFile(ui->fileName->text());
242 
243  Progress *p = new Progress;
244  p->setStatus("Sending to: " + m_service.device().name(), "Waiting for start");
245  p->show();
246 
247  QBluetoothTransferReply *reply = mgr.put(req, m_file);
248  //mgr is default parent
249  //ensure that mgr doesn't take reply down when leaving scope
250  reply->setParent(this);
251  if (reply->error()){
252  qDebug() << "Failed to send file";
253  p->finished(reply);
254  reply->deleteLater();
255  return;
256  }
257 
258  connect(reply, SIGNAL(transferProgress(qint64,qint64)), p, SLOT(uploadProgress(qint64,qint64)));
259  connect(reply, SIGNAL(finished(QBluetoothTransferReply*)), p, SLOT(finished(QBluetoothTransferReply*)));
260  connect(p, SIGNAL(rejected()), reply, SLOT(abort()));
261 }
262 
263 void RemoteSelector::on_stopButton_clicked()
264 {
265  m_discoveryAgent->stop();
266 }
267 
268 QString RemoteSelector::addressToName(const QBluetoothAddress &address)
269 {
270  QMapIterator<int, QBluetoothServiceInfo> i(m_discoveredServices);
271  while (i.hasNext()){
272  i.next();
273  if (i.value().device().address() == address)
274  return i.value().device().name();
275  }
276  return address.toString();
277 }
278 
279 void RemoteSelector::displayPin(const QBluetoothAddress &address, QString pin)
280 {
281  if (m_pindisplay)
282  m_pindisplay->deleteLater();
283  m_pindisplay = new pinDisplay(QString("Enter pairing pin on: %1").arg(addressToName(address)), pin, this);
284  m_pindisplay->show();
285 }
286 
287 void RemoteSelector::displayConfirmation(const QBluetoothAddress &address, QString pin)
288 {
289  Q_UNUSED(address);
290 
291  if (m_pindisplay)
292  m_pindisplay->deleteLater();
293  m_pindisplay = new pinDisplay(QString("Confirm this pin is the same"), pin, this);
294  connect(m_pindisplay, SIGNAL(accepted()), this, SLOT(displayConfAccepted()));
295  connect(m_pindisplay, SIGNAL(rejected()), this, SLOT(displayConfReject()));
296  m_pindisplay->setOkCancel();
297  m_pindisplay->show();
298 }
299 
300 void RemoteSelector::displayConfAccepted()
301 {
302  m_localDevice->pairingConfirmation(true);
303 }
304 void RemoteSelector::displayConfReject()
305 {
306  m_localDevice->pairingConfirmation(false);
307 }
308 
309 void RemoteSelector::pairingFinished(const QBluetoothAddress &address, QBluetoothLocalDevice::Pairing status)
310 {
311  QBluetoothServiceInfo service;
312  int row = 0;
313 
314  ui->pairingBusy->hide();
315  ui->pairingBusy->movie()->stop();
316 
317  ui->remoteDevices->blockSignals(true);
318 
319  for (int i = 0; i < m_discoveredServices.count(); i++){
320  if (m_discoveredServices.value(i).device().address() == address){
321  service = m_discoveredServices.value(i);
322  row = i;
323  break;
324  }
325  }
326 
327  if (m_pindisplay)
328  delete m_pindisplay;
329 
330  QMessageBox msgBox;
331  if (m_pairingError) {
332  msgBox.setText("Pairing failed with " + address.toString());
333  } else if (status == QBluetoothLocalDevice::Paired
334  || status == QBluetoothLocalDevice::AuthorizedPaired) {
335  msgBox.setText("Paired successfully with " + address.toString());
336  } else {
337  msgBox.setText("Pairing released with " + address.toString());
338  }
339 
340  if (service.isValid()){
341  if (status == QBluetoothLocalDevice::AuthorizedPaired){
342  ui->remoteDevices->item(row, 3)->setCheckState(Qt::Checked);
343  ui->remoteDevices->item(row, 4)->setCheckState(Qt::Checked);
344  }
345  else if (status == QBluetoothLocalDevice::Paired){
346  ui->remoteDevices->item(row, 3)->setCheckState(Qt::Checked);
347  ui->remoteDevices->item(row, 4)->setCheckState(Qt::Unchecked);
348  }
349  else {
350  ui->remoteDevices->item(row, 3)->setCheckState(Qt::Unchecked);
351  ui->remoteDevices->item(row, 4)->setCheckState(Qt::Unchecked);
352  }
353  }
354 
355  m_pairingError = false;
356  msgBox.exec();
357 
358  ui->remoteDevices->blockSignals(false);
359 }
360 
361 void RemoteSelector::pairingError(QBluetoothLocalDevice::Error error)
362 {
363  if (error != QBluetoothLocalDevice::PairingError)
364  return;
365 
366  m_pairingError = true;
367  pairingFinished(m_service.device().address(), QBluetoothLocalDevice::Unpaired);
368 }
369 
370 void RemoteSelector::on_remoteDevices_cellClicked(int row, int column)
371 {
372  Q_UNUSED(column);
373 
374  m_service = m_discoveredServices.value(row);
375  if (!ui->fileName->text().isEmpty()) {
376  ui->sendButton->setDisabled(false);
377  }
378 }
379 
380 void RemoteSelector::on_remoteDevices_itemChanged(QTableWidgetItem* item)
381 {
382  int row = item->row();
383  int column = item->column();
384  m_service = m_discoveredServices.value(row);
385 
386  if (column < 3)
387  return;
388 
389  if (item->checkState() == Qt::Unchecked && column == 3){
390  m_localDevice->requestPairing(m_service.device().address(), QBluetoothLocalDevice::Unpaired);
391  return; // don't continue and start movie
392  }
393  else if ((item->checkState() == Qt::Checked && column == 3) ||
394  (item->checkState() == Qt::Unchecked && column == 4)){
395  m_localDevice->requestPairing(m_service.device().address(), QBluetoothLocalDevice::Paired);
396  ui->remoteDevices->blockSignals(true);
397  ui->remoteDevices->item(row, column)->setCheckState(Qt::PartiallyChecked);
398  ui->remoteDevices->blockSignals(false);
399  }
400  else if (item->checkState() == Qt::Checked && column == 4){
401  m_localDevice->requestPairing(m_service.device().address(), QBluetoothLocalDevice::AuthorizedPaired);
402  ui->remoteDevices->blockSignals(true);
403  ui->remoteDevices->item(row, column)->setCheckState(Qt::PartiallyChecked);
404  ui->remoteDevices->blockSignals(false);
405  }
406  ui->pairingBusy->show();
407  ui->pairingBusy->movie()->start();
408 }
Definition: pindisplay.h:47
void setStatus(QString title, QString filename)
Definition: progress.cpp:65
QBluetoothServiceInfo service() const
RemoteSelector(QWidget *parent=0)