137 lines
5.6 KiB
C++
137 lines
5.6 KiB
C++
#include "WifiConnectDialog.h"
|
||
|
||
#include <QFormLayout>
|
||
#include <QVBoxLayout>
|
||
#include <QLineEdit>
|
||
#include <QPushButton>
|
||
#include <QLabel>
|
||
#include <QIntValidator>
|
||
#include <QThread>
|
||
#include <QPointer>
|
||
#include <QApplication>
|
||
#include <QProgressDialog>
|
||
|
||
#include "adb/AdbUtils.h"
|
||
#include "dao/WifiConnectionDAO.h"
|
||
|
||
WifiConnectDialog::WifiConnectDialog(QWidget *parent) : QDialog(parent) {
|
||
setWindowTitle("Подключить по Wi-Fi");
|
||
setModal(true);
|
||
|
||
auto *form = new QFormLayout;
|
||
m_ip = new QLineEdit(this);
|
||
m_ip->setPlaceholderText("192.168.1.50");
|
||
m_port = new QLineEdit(this);
|
||
m_port->setPlaceholderText("37123");
|
||
m_port->setValidator(new QIntValidator(1, 65535, this));
|
||
m_code = new QLineEdit(this);
|
||
m_code->setPlaceholderText("6-значный код");
|
||
|
||
form->addRow("IP", m_ip);
|
||
form->addRow("Порт", m_port);
|
||
form->addRow("Код", m_code);
|
||
|
||
m_btn = new QPushButton("Подключить", this);
|
||
connect(m_btn, &QPushButton::clicked, this, &WifiConnectDialog::onConnect);
|
||
|
||
m_status = new QLabel(this);
|
||
m_status->setWordWrap(true);
|
||
m_status->setStyleSheet("color: #555; font-size: 11px;");
|
||
|
||
auto *layout = new QVBoxLayout(this);
|
||
layout->addLayout(form);
|
||
layout->addWidget(m_btn);
|
||
layout->addWidget(m_status);
|
||
|
||
// Подсказка оператору: где взять реквизиты.
|
||
auto *hint = new QLabel(
|
||
"Телефон → Для разработчиков → Беспроводная отладка →\n"
|
||
"«Подключение с помощью кода»: введите показанные IP:порт и код.", this);
|
||
hint->setWordWrap(true);
|
||
hint->setStyleSheet("color: #888; font-size: 10px;");
|
||
layout->addWidget(hint);
|
||
}
|
||
|
||
void WifiConnectDialog::setStatus(const QString &text) {
|
||
if (m_status) m_status->setText(text);
|
||
}
|
||
|
||
void WifiConnectDialog::onConnect() {
|
||
const QString ip = m_ip->text().trimmed();
|
||
const int port = m_port->text().trimmed().toInt();
|
||
const QString code = m_code->text().trimmed();
|
||
if (ip.isEmpty() || port <= 0 || code.isEmpty()) {
|
||
setStatus("Заполните IP, порт и код.");
|
||
return;
|
||
}
|
||
|
||
m_btn->setEnabled(false);
|
||
setStatus("Спаривание и подключение…");
|
||
|
||
// Лоадер на время онбординга (бесконечный индикатор, без кнопки отмены).
|
||
auto *progress = new QProgressDialog("Спаривание и подключение…", QString(), 0, 0, this);
|
||
progress->setWindowTitle("Подключение по Wi-Fi");
|
||
progress->setWindowModality(Qt::WindowModal);
|
||
progress->setCancelButton(nullptr);
|
||
progress->setMinimumDuration(0);
|
||
progress->setAutoClose(false);
|
||
progress->setAutoReset(false);
|
||
progress->setWindowFlags(progress->windowFlags()
|
||
& ~Qt::WindowCloseButtonHint & ~Qt::WindowContextHelpButtonHint);
|
||
progress->show();
|
||
|
||
// Результат онбординга, заполняется в фоновом потоке.
|
||
struct Res { bool ok = false; QString msg; };
|
||
auto *res = new Res;
|
||
|
||
auto *worker = QThread::create([res, ip, port, code]() {
|
||
if (!AdbUtils::adbPair(ip, port, code)) {
|
||
res->msg = "Не удалось спарить — проверьте порт и код (код одноразовый, "
|
||
"переоткройте экран спаривания на телефоне).";
|
||
return;
|
||
}
|
||
// Connect: сначала тем же портом, при неудаче — поиск connect-порта через mDNS.
|
||
QString endpoint = AdbUtils::adbConnect(ip, port);
|
||
if (endpoint.isEmpty()) {
|
||
if (const QString mep = AdbUtils::mdnsFindConnect(ip); !mep.isEmpty()) {
|
||
const int c = mep.lastIndexOf(':');
|
||
endpoint = AdbUtils::adbConnect(mep.left(c), mep.mid(c + 1).toInt());
|
||
}
|
||
}
|
||
if (endpoint.isEmpty()) {
|
||
res->msg = "Спарено, но не удалось подключиться. Проверьте порт подключения "
|
||
"(в «Беспроводной отладке» он отличается от порта спаривания).";
|
||
return;
|
||
}
|
||
const QString androidId = AdbUtils::getAndroidId(endpoint);
|
||
if (androidId.isEmpty()) {
|
||
res->msg = "Подключено (" + endpoint + "), но не удалось прочитать android_id.";
|
||
return;
|
||
}
|
||
const int connectPort = endpoint.mid(endpoint.lastIndexOf(':') + 1).toInt();
|
||
// Код НЕ сохраняем — он одноразовый, для реконнекта не нужен.
|
||
WifiConnectionDAO::upsert(androidId, ip, connectPort);
|
||
res->ok = true;
|
||
res->msg = "Подключено: " + endpoint + ". Устройство появится в списке.";
|
||
});
|
||
|
||
QPointer<WifiConnectDialog> guard(this);
|
||
QPointer<QProgressDialog> progressGuard(progress);
|
||
connect(worker, &QThread::finished, qApp, [worker, res, guard, progressGuard]() {
|
||
if (progressGuard) {
|
||
progressGuard->reset();
|
||
progressGuard->deleteLater();
|
||
}
|
||
if (guard) {
|
||
guard->setStatus(res->msg);
|
||
guard->m_btn->setEnabled(true);
|
||
if (res->ok) {
|
||
guard->m_code->clear(); // код одноразовый — очистим для следующего ввода
|
||
}
|
||
}
|
||
delete res;
|
||
worker->deleteLater();
|
||
});
|
||
worker->start();
|
||
}
|