1
0
forked from BRT/arc
arc/views/device/WifiConnectDialog.cpp
2026-06-17 19:30:24 +07:00

137 lines
5.6 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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();
}