#include "remoteselector.h"
#include "ui_remoteselector.h"
#include <qbluetoothdeviceinfo.h>
#include <qbluetoothaddress.h>
#include <qbluetoothtransferrequest.h>
#include <qbluetoothtransferreply.h>
#include <qbluetoothlocaldevice.h>
#include <QMovie>
#include <QMessageBox>
#include <QFileDialog>
#include <QCheckBox>
#include "progress.h"
#include "pindisplay.h"
QT_USE_NAMESPACE
RemoteSelector::RemoteSelector(QWidget *parent)
: QDialog(parent), ui(new Ui::RemoteSelector),
m_localDevice(new QBluetoothLocalDevice), m_pindisplay(0),
m_pairingError(false)
{
ui->setupUi(this);
QBluetoothAddress adapterAddress = m_localDevice->address();
m_discoveryAgent = new QBluetoothServiceDiscoveryAgent(adapterAddress);
connect(m_discoveryAgent, SIGNAL(serviceDiscovered(QBluetoothServiceInfo)),
this, SLOT(serviceDiscovered(QBluetoothServiceInfo)));
connect(m_discoveryAgent, SIGNAL(finished()), this, SLOT(discoveryFinished()));
connect(m_discoveryAgent, SIGNAL(canceled()), this, SLOT(discoveryFinished()));
ui->remoteDevices->setColumnWidth(3, 75);
ui->remoteDevices->setColumnWidth(4, 100);
connect(m_localDevice, SIGNAL(pairingDisplayPinCode(QBluetoothAddress,QString)),
this, SLOT(displayPin(QBluetoothAddress,QString)));
connect(m_localDevice, SIGNAL(pairingDisplayConfirmation(QBluetoothAddress,QString)),
this, SLOT(displayConfirmation(QBluetoothAddress,QString)));
connect(m_localDevice, SIGNAL(pairingFinished(QBluetoothAddress,QBluetoothLocalDevice::Pairing)),
this, SLOT(pairingFinished(QBluetoothAddress,QBluetoothLocalDevice::Pairing)));
connect(m_localDevice, SIGNAL(error(QBluetoothLocalDevice::Error)),
this, SLOT(pairingError(QBluetoothLocalDevice::Error)));
ui->busyWidget->setMovie(new QMovie(":/icons/busy.gif"));
ui->busyWidget->movie()->start();
ui->pairingBusy->setMovie(new QMovie(":/icons/pairing.gif"));
ui->pairingBusy->hide();
ui->remoteDevices->clearContents();
ui->remoteDevices->setRowCount(0);
}
RemoteSelector::~RemoteSelector()
{
delete ui;
delete m_discoveryAgent;
delete m_localDevice;
}
void RemoteSelector::startDiscovery(const QBluetoothUuid &uuid)
{
ui->stopButton->setDisabled(false);
if (m_discoveryAgent->isActive())
m_discoveryAgent->stop();
m_discoveryAgent->setUuidFilter(uuid);
m_discoveryAgent->start();
if (!m_discoveryAgent->isActive() ||
m_discoveryAgent->error() != QBluetoothServiceDiscoveryAgent::NoError) {
ui->status->setText(tr("Cannot find remote services."));
} else {
ui->status->setText(tr("Scanning..."));
ui->busyWidget->show();
ui->busyWidget->movie()->start();
}
}
QBluetoothServiceInfo RemoteSelector::service() const
{
return m_service;
}
void RemoteSelector::serviceDiscovered(const QBluetoothServiceInfo &serviceInfo)
{
#if 0
qDebug() << "Discovered service on"
<< serviceInfo.device().name() << serviceInfo.device().address().toString();
qDebug() << "\tService name:" << serviceInfo.serviceName();
qDebug() << "\tDescription:"
<< serviceInfo.attribute(QBluetoothServiceInfo::ServiceDescription).toString();
qDebug() << "\tProvider:"
<< serviceInfo.attribute(QBluetoothServiceInfo::ServiceProvider).toString();
qDebug() << "\tL2CAP protocol service multiplexer:"
<< serviceInfo.protocolServiceMultiplexer();
qDebug() << "\tRFCOMM server channel:" << serviceInfo.serverChannel();
#endif
QString remoteName;
if (serviceInfo.device().name().isEmpty())
remoteName = serviceInfo.device().address().toString();
else
remoteName = serviceInfo.device().name();
QMutableMapIterator<int, QBluetoothServiceInfo> i(m_discoveredServices);
while (i.hasNext()){
i.next();
if (serviceInfo.device().address() == i.value().device().address()){
i.setValue(serviceInfo);
return;
}
}
int row = ui->remoteDevices->rowCount();
ui->remoteDevices->insertRow(row);
QTableWidgetItem *item = new QTableWidgetItem(serviceInfo.device().address().toString());
ui->remoteDevices->setItem(row, 0, item);
item = new QTableWidgetItem(serviceInfo.device().name());
ui->remoteDevices->setItem(row, 1, item);
item = new QTableWidgetItem(serviceInfo.serviceName());
ui->remoteDevices->setItem(row, 2, item);
QBluetoothLocalDevice::Pairing p;
p = m_localDevice->pairingStatus(serviceInfo.device().address());
ui->remoteDevices->blockSignals(true);
item = new QTableWidgetItem();
if ((p&QBluetoothLocalDevice::Paired) || (p&QBluetoothLocalDevice::AuthorizedPaired))
item->setCheckState(Qt::Checked);
else
item->setCheckState(Qt::Unchecked);
ui->remoteDevices->setItem(row, 3, item);
item = new QTableWidgetItem();
if (p&QBluetoothLocalDevice::AuthorizedPaired)
item->setCheckState(Qt::Checked);
else
item->setCheckState(Qt::Unchecked);
ui->remoteDevices->setItem(row, 4, item);
ui->remoteDevices->blockSignals(false);
m_discoveredServices.insert(row, serviceInfo);
}
void RemoteSelector::discoveryFinished()
{
ui->status->setText(tr("Select the device to send to."));
ui->stopButton->setDisabled(true);
ui->busyWidget->movie()->stop();
ui->busyWidget->hide();
}
void RemoteSelector::startDiscovery()
{
startDiscovery(QBluetoothUuid(QBluetoothUuid::ObexObjectPush));
}
void RemoteSelector::on_refreshPB_clicked()
{
startDiscovery();
ui->stopButton->setDisabled(false);
}
void RemoteSelector::on_fileSelectPB_clicked()
{
ui->fileName->setText(QFileDialog::getOpenFileName());
if (m_service.isValid())
ui->sendButton->setDisabled(false);
}
void RemoteSelector::on_sendButton_clicked()
{
QBluetoothTransferManager mgr;
QBluetoothTransferRequest req(m_service.device().address());
m_file = new QFile(ui->fileName->text());
Progress *p = new Progress;
p->setStatus("Sending to: " + m_service.device().name(), "Waiting for start");
p->show();
QBluetoothTransferReply *reply = mgr.put(req, m_file);
reply->setParent(this);
if (reply->error()){
qDebug() << "Failed to send file";
p->finished(reply);
reply->deleteLater();
return;
}
connect(reply, SIGNAL(transferProgress(qint64,qint64)), p, SLOT(uploadProgress(qint64,qint64)));
connect(reply, SIGNAL(finished(QBluetoothTransferReply*)), p, SLOT(finished(QBluetoothTransferReply*)));
connect(p, SIGNAL(rejected()), reply, SLOT(abort()));
}
void RemoteSelector::on_stopButton_clicked()
{
m_discoveryAgent->stop();
}
QString RemoteSelector::addressToName(const QBluetoothAddress &address)
{
QMapIterator<int, QBluetoothServiceInfo> i(m_discoveredServices);
while (i.hasNext()){
i.next();
if (i.value().device().address() == address)
return i.value().device().name();
}
return address.toString();
}
void RemoteSelector::displayPin(const QBluetoothAddress &address, QString pin)
{
if (m_pindisplay)
m_pindisplay->deleteLater();
m_pindisplay = new pinDisplay(QString("Enter pairing pin on: %1").arg(addressToName(address)), pin, this);
m_pindisplay->show();
}
void RemoteSelector::displayConfirmation(const QBluetoothAddress &address, QString pin)
{
Q_UNUSED(address);
if (m_pindisplay)
m_pindisplay->deleteLater();
m_pindisplay = new pinDisplay(QString("Confirm this pin is the same"), pin, this);
connect(m_pindisplay, SIGNAL(accepted()), this, SLOT(displayConfAccepted()));
connect(m_pindisplay, SIGNAL(rejected()), this, SLOT(displayConfReject()));
m_pindisplay->setOkCancel();
m_pindisplay->show();
}
void RemoteSelector::displayConfAccepted()
{
m_localDevice->pairingConfirmation(true);
}
void RemoteSelector::displayConfReject()
{
m_localDevice->pairingConfirmation(false);
}
void RemoteSelector::pairingFinished(const QBluetoothAddress &address, QBluetoothLocalDevice::Pairing status)
{
QBluetoothServiceInfo service;
int row = 0;
ui->pairingBusy->hide();
ui->pairingBusy->movie()->stop();
ui->remoteDevices->blockSignals(true);
for (int i = 0; i < m_discoveredServices.count(); i++){
if (m_discoveredServices.value(i).device().address() == address){
service = m_discoveredServices.value(i);
row = i;
break;
}
}
if (m_pindisplay)
delete m_pindisplay;
QMessageBox msgBox;
if (m_pairingError) {
msgBox.setText("Pairing failed with " + address.toString());
} else if (status == QBluetoothLocalDevice::Paired
|| status == QBluetoothLocalDevice::AuthorizedPaired) {
msgBox.setText("Paired successfully with " + address.toString());
} else {
msgBox.setText("Pairing released with " + address.toString());
}
if (service.isValid()){
if (status == QBluetoothLocalDevice::AuthorizedPaired){
ui->remoteDevices->item(row, 3)->setCheckState(Qt::Checked);
ui->remoteDevices->item(row, 4)->setCheckState(Qt::Checked);
}
else if (status == QBluetoothLocalDevice::Paired){
ui->remoteDevices->item(row, 3)->setCheckState(Qt::Checked);
ui->remoteDevices->item(row, 4)->setCheckState(Qt::Unchecked);
}
else {
ui->remoteDevices->item(row, 3)->setCheckState(Qt::Unchecked);
ui->remoteDevices->item(row, 4)->setCheckState(Qt::Unchecked);
}
}
m_pairingError = false;
msgBox.exec();
ui->remoteDevices->blockSignals(false);
}
void RemoteSelector::pairingError(QBluetoothLocalDevice::Error error)
{
if (error != QBluetoothLocalDevice::PairingError)
return;
m_pairingError = true;
pairingFinished(m_service.device().address(), QBluetoothLocalDevice::Unpaired);
}
void RemoteSelector::on_remoteDevices_cellClicked(int row, int column)
{
Q_UNUSED(column);
m_service = m_discoveredServices.value(row);
if (!ui->fileName->text().isEmpty()) {
ui->sendButton->setDisabled(false);
}
}
void RemoteSelector::on_remoteDevices_itemChanged(QTableWidgetItem* item)
{
int row = item->row();
int column = item->column();
m_service = m_discoveredServices.value(row);
if (column < 3)
return;
if (item->checkState() == Qt::Unchecked && column == 3){
m_localDevice->requestPairing(m_service.device().address(), QBluetoothLocalDevice::Unpaired);
return;
}
else if ((item->checkState() == Qt::Checked && column == 3) ||
(item->checkState() == Qt::Unchecked && column == 4)){
m_localDevice->requestPairing(m_service.device().address(), QBluetoothLocalDevice::Paired);
ui->remoteDevices->blockSignals(true);
ui->remoteDevices->item(row, column)->setCheckState(Qt::PartiallyChecked);
ui->remoteDevices->blockSignals(false);
}
else if (item->checkState() == Qt::Checked && column == 4){
m_localDevice->requestPairing(m_service.device().address(), QBluetoothLocalDevice::AuthorizedPaired);
ui->remoteDevices->blockSignals(true);
ui->remoteDevices->item(row, column)->setCheckState(Qt::PartiallyChecked);
ui->remoteDevices->blockSignals(false);
}
ui->pairingBusy->show();
ui->pairingBusy->movie()->start();
}