refactor: UI and wireless connection logic

This commit is contained in:
uncor3
2026-02-10 21:11:02 +00:00
parent da8b390bc2
commit cf0ba91684
7 changed files with 212 additions and 162 deletions
+1 -9
View File
@@ -57,16 +57,8 @@ AppDownloadBaseDialog::AppDownloadBaseDialog(const QString &appName,
: QDialog(parent), m_appName(appName), m_downloadProcess(nullptr),
m_progressTimer(nullptr), m_bundleId(bundleId)
{
// Common UI: progress bar and action button
m_layout = new QVBoxLayout(this);
m_layout->setSpacing(20);
m_layout->setContentsMargins(30, 30, 30, 30);
QLabel *nameLabel = new QLabel(appName);
nameLabel->setStyleSheet("font-size: 20px; font-weight: bold;");
m_layout->addWidget(nameLabel);
m_actionButton = nullptr; // Derived classes set this
m_layout->setContentsMargins(20, 20, 20, 20);
}
void AppDownloadBaseDialog::startDownloadProcess(const QString &bundleId,
+39 -18
View File
@@ -18,7 +18,7 @@
*/
#include "appdownloaddialog.h"
#include "Backdrop.h"
#include "BackDrop.h"
#include "iDescriptor-ui.h"
#include "iDescriptor.h"
#include "libipatool-go.h"
@@ -43,17 +43,41 @@ AppDownloadDialog::AppDownloadDialog(const QString &appName,
setWindowTitle("Download " + appName + " IPA");
setModal(true);
setFixedWidth(500);
setContentsMargins(0, 0, 0, 0);
m_loadingWidget = new ZLoadingWidget(this);
m_loadingWidget = new ZLoadingWidget(true, this);
layout()->addWidget(m_loadingWidget);
QVBoxLayout *contentLayout = new QVBoxLayout(this);
QVBoxLayout *contentLayout = new QVBoxLayout();
contentLayout->setContentsMargins(0, 0, 0, 0);
m_bgLabel = new QLabel();
// FIMXE: causes infinite scaling for some reason, need to investigate
// m_bgLabel->setScaledContents(true);
// m_bgLabel->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored);
// contentLayout->addWidget(m_bgLabel);
// m_bgLabel = new QLabel();
// m_bgLabel->setScaledContents(true);
// m_bgLabel->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored);
// contentLayout->addWidget(m_bgLabel);
QHBoxLayout *cardLayout = new QHBoxLayout();
cardLayout->setContentsMargins(20, 20, 20, 20);
contentLayout->addLayout(cardLayout);
m_appIcon = new QLabel();
m_appIcon->setFixedSize(64, 64);
cardLayout->addWidget(m_appIcon);
cardLayout->addSpacing(5);
QVBoxLayout *textLayout = new QVBoxLayout();
QLabel *nameLabel = new QLabel(appName);
nameLabel->setStyleSheet("font-size: 18px; font-weight: bold;");
nameLabel->setWordWrap(true);
textLayout->addWidget(nameLabel);
textLayout->addSpacing(5);
QLabel *descLabel = new QLabel(description);
descLabel->setWordWrap(true);
descLabel->setStyleSheet("font-size: 14px; color: #666;");
textLayout->addWidget(descLabel);
cardLayout->addLayout(textLayout);
QPointer<AppDownloadDialog> safeThis = this;
fetchAppIconFromApple(
@@ -61,20 +85,17 @@ AppDownloadDialog::AppDownloadDialog(const QString &appName,
[safeThis](const QPixmap &icon, const QJsonObject &appInfo) {
if (auto dialog = safeThis.data()) {
if (!icon.isNull()) {
QPixmap blurred = BackDrop::blurPixmap(icon, 30);
dialog->m_bgLabel->setPixmap(blurred.scaled(
dialog->size(), Qt::KeepAspectRatioByExpanding,
Qt::SmoothTransformation));
dialog->m_appIcon->setPixmap(icon.scaled(
64, 64, Qt::KeepAspectRatio, Qt::SmoothTransformation));
// QPixmap blurred = BackDrop::blurPixmap(icon, 30);
// dialog->m_bgLabel->setPixmap(blurred.scaled(
// dialog->size(), Qt::KeepAspectRatioByExpanding,
// Qt::SmoothTransformation));
}
dialog->m_loadingWidget->stop(true);
}
});
QLabel *descLabel = new QLabel(description);
descLabel->setWordWrap(true);
descLabel->setStyleSheet("font-size: 14px; color: #666;");
contentLayout->insertWidget(1, descLabel);
// Directory selection UI
QHBoxLayout *dirLayout = new QHBoxLayout();
QLabel *dirTextLabel = new QLabel("Save to:");
@@ -102,7 +123,7 @@ AppDownloadDialog::AppDownloadDialog(const QString &appName,
});
dirLayout->addWidget(m_dirButton);
contentLayout->insertLayout(2, dirLayout);
contentLayout->addLayout(dirLayout);
QHBoxLayout *buttonLayout = new QHBoxLayout();
+8 -6
View File
@@ -35,12 +35,12 @@ public:
const QString &description,
QWidget *parent = nullptr);
protected:
void resizeEvent(QResizeEvent *event) override
{
QWidget::resizeEvent(event);
m_bgLabel->setFixedSize(event->size());
}
// protected:
// void resizeEvent(QResizeEvent *event) override
// {
// QWidget::resizeEvent(event);
// m_bgLabel->setFixedSize(event->size());
// }
private slots:
void onDownloadClicked();
@@ -50,7 +50,9 @@ private:
QPushButton *m_dirButton;
ZLabel *m_dirLabel;
QString m_bundleId;
// FIXME: remove this if not needed
QLabel *m_bgLabel;
QLabel *m_appIcon;
ZLoadingWidget *m_loadingWidget;
};
+14 -5
View File
@@ -373,6 +373,11 @@ init_idescriptor_device(const QString &udid,
qDebug() << "Initializing iDescriptor device with UDID: " << udid
<< (isWireless ? "over wireless" : "over USB");
if (isWireless) {
qDebug() << "Wireless args" << "IP:" << wirelessArgs.ip
<< "for mac address" << udid;
}
iDescriptorInitDeviceResult result = {};
UsbmuxdConnectionHandle *usbmuxd_conn = nullptr;
@@ -550,12 +555,16 @@ init_idescriptor_device(const QString &udid,
result.heartbeatThread = heartbeatThread;
// TODO cache pairing file path
result.deviceInfo.isWireless = isWireless;
result.deviceInfo.ipAddress = wirelessArgs.ip.toStdString();
fullDeviceInfo(infoXml, afc_client, result.diagRelay.get(), result);
::QObject::connect(heartbeatThread, &HeartbeatThread::heartbeatFailed,
AppContext::sharedInstance(),
&AppContext::heartbeatFailed);
::QObject::connect(heartbeatThread, &HeartbeatThread::heartbeatThreadExited,
AppContext::sharedInstance(), &AppContext::removeDevice);
if (isWireless) {
::QObject::connect(heartbeatThread, &HeartbeatThread::heartbeatFailed,
AppContext::sharedInstance(),
&AppContext::heartbeatFailed);
::QObject::connect(
heartbeatThread, &HeartbeatThread::heartbeatThreadExited,
AppContext::sharedInstance(), &AppContext::removeDevice);
}
cleanup:
// Cleanup on error
// FIXME: implement proper cleanup
+16 -38
View File
@@ -360,10 +360,7 @@ MainWindow::MainWindow(QWidget *parent)
// Handle device connection
switch (event) {
case DeviceMonitorThread::IDEVICE_DEVICE_ADD: {
/* this should never happen iDescriptor does not
support network devices but for some reason even
though we are only listening for USB devices, we
still get network devices on macOS*/
/* never gets fired on any platform */
if (conn_type == DeviceMonitorThread::CONNECTION_NETWORK) {
return;
}
@@ -388,11 +385,8 @@ MainWindow::MainWindow(QWidget *parent)
}
case DeviceMonitorThread::IDEVICE_DEVICE_PAIRED: {
/* never gets fired on any platform */
if (conn_type == DeviceMonitorThread::CONNECTION_NETWORK) {
qDebug() << "Network devices are not supported but a "
"network device was "
"received in event listener. Please report "
"this issue.";
return;
}
qDebug() << "Device paired: " << udid;
@@ -417,8 +411,14 @@ MainWindow::MainWindow(QWidget *parent)
QTimer::singleShot(std::chrono::seconds(1), this,
[this]() { m_deviceMonitor->start(); });
// ═══════════════════════════════════════════════════════════════════════
// Upgrade to wireless when a "WIRED" device is removed
// ═══════════════════════════════════════════════════════════════════════
connect(AppContext::sharedInstance(), &AppContext::deviceRemoved, this,
[](const std::string &udid, const std::string &wifiMacAddress) {
[](const std::string &udid, const std::string &wifiMacAddress,
const std::string &ipAddress, bool wasWireless) {
if (wasWireless)
return;
qDebug() << "Upgrading device to wireless connection for UDID"
<< QString::fromStdString(udid);
QMetaObject::invokeMethod(
@@ -428,26 +428,14 @@ MainWindow::MainWindow(QWidget *parent)
Q_ARG(DeviceMonitorThread::IdeviceConnectionType,
DeviceMonitorThread::CONNECTION_NETWORK),
Q_ARG(AddType, AddType::UpgradeToWireless),
Q_ARG(QString, QString::fromStdString(wifiMacAddress)));
Q_ARG(QString, QString::fromStdString(wifiMacAddress)),
Q_ARG(QString, QString::fromStdString(ipAddress)));
});
connect(NetworkDeviceManager::sharedInstance(),
&NetworkDeviceManager::deviceAdded, this,
[this](const NetworkDevice &device) {
// return; // FIXME: disable for now
const iDescriptorDevice *idevice =
AppContext::sharedInstance()->getDeviceByMacAddress(
device.macAddress);
if (idevice) {
qDebug() << "Network device matched to connected device:"
<< QString::fromStdString(
idevice->deviceInfo.deviceName)
<< "MAC:" << device.macAddress;
// You can now use 'idevice' as needed
}
// FIXME: both macAddress and udid can be used to get pairing
// file
if (AppContext::sharedInstance()->getDeviceByMacAddress(
device.macAddress)) {
qDebug() << "Prefering wired connection on device MAC:"
@@ -463,9 +451,8 @@ MainWindow::MainWindow(QWidget *parent)
Q_ARG(DeviceMonitorThread::IdeviceConnectionType,
DeviceMonitorThread::CONNECTION_NETWORK),
Q_ARG(AddType, AddType::Wireless),
Q_ARG(QString, device.macAddress));
// Handle network device addition if needed
Q_ARG(QString, device.macAddress),
Q_ARG(QString, device.address));
});
connect(AppContext::sharedInstance(), &AppContext::deviceHeartbeatFailed,
@@ -482,15 +469,6 @@ MainWindow::MainWindow(QWidget *parent)
// toast->setPosition(ToastPosition::BOTTOM_MIDDLE);
// toast->show();
});
// NetworkDevicesWidget *m_networkDevicesWidget = new
// NetworkDevicesWidget();
// m_networkDevicesWidget->setAttribute(Qt::WA_DeleteOnClose);
// m_networkDevicesWidget->setWindowFlag(Qt::Window);
// m_networkDevicesWidget->resize(500, 600);
// // connect(m_networkDevicesWidget, &QObject::destroyed, this,
// // [this]() { m_networkDevicesWidget = nullptr; });
// m_networkDevicesWidget->show();
}
void MainWindow::createMenus()
@@ -518,9 +496,9 @@ void MainWindow::updateNoDevicesConnected()
return m_mainStackedWidget->setCurrentIndex(0); // Show Welcome page
}
int deviceCount = AppContext::sharedInstance()->getConnectedDeviceCount();
// m_connectedDeviceCountLabel->setText(
// "iDescriptor: " + QString::number(deviceCount) +
// (deviceCount == 1 ? " device" : " devices") + " connected");
m_connectedDeviceCountLabel->setText(
"iDescriptor: " + QString::number(deviceCount) +
(deviceCount == 1 ? " device" : " devices") + " connected");
m_mainStackedWidget->setCurrentIndex(1); // Show device list page
}
+116 -85
View File
@@ -33,6 +33,90 @@
#include <QPalette>
#include <QPushButton>
NetworkDeviceCard::NetworkDeviceCard(const NetworkDevice &device,
QWidget *parent)
: QWidget(parent)
{
QVBoxLayout *cardLayout = new QVBoxLayout(this);
cardLayout->setContentsMargins(12, 10, 12, 10);
cardLayout->setSpacing(4);
// Device name (primary)
QLabel *nameLabel = new QLabel(device.name);
nameLabel->setWordWrap(true);
QFont nameFont = nameLabel->font();
nameFont.setPointSize(13);
nameFont.setWeight(QFont::Medium);
nameLabel->setFont(nameFont);
QPalette namePalette = nameLabel->palette();
namePalette.setColor(QPalette::WindowText,
palette().color(QPalette::WindowText));
nameLabel->setPalette(namePalette);
// Device info container
QWidget *infoContainer = new QWidget();
QHBoxLayout *infoLayout = new QHBoxLayout(infoContainer);
infoLayout->setContentsMargins(0, 0, 0, 0);
infoLayout->setSpacing(12);
// Address info
QLabel *addressLabel = new QLabel(QString("IP: %1").arg(device.address));
QFont addressFont = addressLabel->font();
addressFont.setPointSize(11);
addressLabel->setFont(addressFont);
QPalette addressPalette = addressLabel->palette();
QColor secondaryColor = palette().color(QPalette::WindowText);
secondaryColor.setAlpha(180);
addressPalette.setColor(QPalette::WindowText, secondaryColor);
addressLabel->setPalette(addressPalette);
// Port info
QLabel *portLabel = new QLabel(QString("Port: %1").arg(device.port));
portLabel->setFont(addressFont);
portLabel->setPalette(addressPalette);
infoLayout->addWidget(addressLabel);
infoLayout->addWidget(portLabel);
infoLayout->addStretch();
m_connectButton = new QPushButton("Connect");
m_connectButton->setDefault(true);
connect(m_connectButton, &QPushButton::clicked, this, [this, device]() {
m_connectButton->setText("Connecting...");
m_connectButton->setEnabled(false);
AppContext::sharedInstance()->tryToConnectToNetworkDevice(
device.macAddress);
});
infoLayout->addWidget(m_connectButton);
infoLayout->addSpacing(5);
// Status indicator
QLabel *statusIndicator = new QLabel("");
QFont statusFont = statusIndicator->font();
statusFont.setPointSize(12);
statusIndicator->setFont(statusFont);
QPalette statusPalette = statusIndicator->palette();
statusPalette.setColor(QPalette::WindowText,
QColor(52, 199, 89)); // iOS green
statusIndicator->setPalette(statusPalette);
infoLayout->addWidget(statusIndicator);
cardLayout->addWidget(nameLabel);
cardLayout->addWidget(infoContainer);
}
void NetworkDeviceCard::failed()
{
m_connectButton->setText("Failed to connect");
m_connectButton->setEnabled(false);
QTimer::singleShot(2000, this, [this]() {
m_connectButton->setText("Connect");
m_connectButton->setEnabled(true);
});
}
NetworkDevicesToConnectWidget::NetworkDevicesToConnectWidget(QWidget *parent)
: QWidget(parent)
{
@@ -57,6 +141,12 @@ NetworkDevicesToConnectWidget::NetworkDevicesToConnectWidget(QWidget *parent)
// Initial device list update
updateDeviceList();
connect(AppContext::sharedInstance(),
&AppContext::noPairingFileForWirelessDevice, this,
&NetworkDevicesToConnectWidget::onNoPairingFileForWirelessDevice);
connect(AppContext::sharedInstance(), &AppContext::initFailed, this,
&NetworkDevicesToConnectWidget::onDeviceInitFailed);
}
NetworkDevicesToConnectWidget::~NetworkDevicesToConnectWidget()
@@ -126,90 +216,18 @@ void NetworkDevicesToConnectWidget::createDeviceCard(
const NetworkDevice &device)
{
// Main card frame
QWidget *card = new QWidget();
NetworkDeviceCard *card = new NetworkDeviceCard(device);
QVBoxLayout *cardLayout = new QVBoxLayout(card);
cardLayout->setContentsMargins(12, 10, 12, 10);
cardLayout->setSpacing(4);
// Device name (primary)
QLabel *nameLabel = new QLabel(device.name);
nameLabel->setWordWrap(true);
QFont nameFont = nameLabel->font();
nameFont.setPointSize(13);
nameFont.setWeight(QFont::Medium);
nameLabel->setFont(nameFont);
QPalette namePalette = nameLabel->palette();
namePalette.setColor(QPalette::WindowText,
palette().color(QPalette::WindowText));
nameLabel->setPalette(namePalette);
// Device info container
QWidget *infoContainer = new QWidget();
QHBoxLayout *infoLayout = new QHBoxLayout(infoContainer);
infoLayout->setContentsMargins(0, 0, 0, 0);
infoLayout->setSpacing(12);
// Address info
QLabel *addressLabel = new QLabel(QString("IP: %1").arg(device.address));
QFont addressFont = addressLabel->font();
addressFont.setPointSize(11);
addressLabel->setFont(addressFont);
QPalette addressPalette = addressLabel->palette();
QColor secondaryColor = palette().color(QPalette::WindowText);
secondaryColor.setAlpha(180);
addressPalette.setColor(QPalette::WindowText, secondaryColor);
addressLabel->setPalette(addressPalette);
// Port info
QLabel *portLabel = new QLabel(QString("Port: %1").arg(device.port));
portLabel->setFont(addressFont);
portLabel->setPalette(addressPalette);
infoLayout->addWidget(addressLabel);
infoLayout->addWidget(portLabel);
infoLayout->addStretch();
QPushButton *connectButton = new QPushButton("Connect");
connectButton->setDefault(true);
connect(connectButton, &QPushButton::clicked, this,
[this, device, connectButton]() {
connectButton->setText("Connecting...");
connectButton->setEnabled(false);
AppContext::sharedInstance()->tryToConnectToNetworkDevice(
device.macAddress);
});
infoLayout->addWidget(connectButton);
infoLayout->addSpacing(5);
// Status indicator
QLabel *statusIndicator = new QLabel("");
QFont statusFont = statusIndicator->font();
statusFont.setPointSize(12);
statusIndicator->setFont(statusFont);
QPalette statusPalette = statusIndicator->palette();
statusPalette.setColor(QPalette::WindowText,
QColor(52, 199, 89)); // iOS green
statusIndicator->setPalette(statusPalette);
infoLayout->addWidget(statusIndicator);
cardLayout->addWidget(nameLabel);
cardLayout->addWidget(infoContainer);
// Store the device info as property for later removal
card->setProperty("deviceName", device.name);
card->setProperty("deviceAddress", device.address);
// Insert before the stretch
m_deviceLayout->insertWidget(m_deviceLayout->count() - 1, card);
m_deviceCards.append(card);
m_deviceCards[device.macAddress] = card;
}
void NetworkDevicesToConnectWidget::clearDeviceCards()
{
for (QWidget *card : m_deviceCards) {
card->deleteLater();
if (card) {
card->deleteLater();
}
}
m_deviceCards.clear();
}
@@ -244,16 +262,13 @@ void NetworkDevicesToConnectWidget::onWirelessDeviceAdded(
}
void NetworkDevicesToConnectWidget::onWirelessDeviceRemoved(
const QString &deviceName)
const QString &macAddress)
{
// Find and remove the corresponding card
for (int i = 0; i < m_deviceCards.count(); ++i) {
QWidget *card = m_deviceCards[i];
if (card->property("deviceName").toString() == deviceName) {
m_deviceCards.removeAt(i);
card->deleteLater();
break;
}
NetworkDeviceCard *card = m_deviceCards[macAddress];
m_deviceCards.remove(macAddress);
if (card) {
card->deleteLater();
}
// Update status
@@ -264,4 +279,20 @@ void NetworkDevicesToConnectWidget::onWirelessDeviceRemoved(
m_statusLabel->setText(
QString("Found %1 network device(s)").arg(deviceCount));
}
}
void NetworkDevicesToConnectWidget::onNoPairingFileForWirelessDevice(
const QString &macAddress)
{
// m_deviceCards.
}
// udid or mac address
void NetworkDevicesToConnectWidget::onDeviceInitFailed(const QString &udid)
{
NetworkDeviceCard *deviceCard = m_deviceCards[udid];
if (deviceCard) {
qDebug() << "Calling failed() on device card for" << udid;
deviceCard->failed();
}
}
+18 -1
View File
@@ -28,10 +28,25 @@
#include <QGroupBox>
#include <QLabel>
#include <QPushButton>
#include <QScrollArea>
#include <QVBoxLayout>
#include <QWidget>
class NetworkDeviceCard : public QWidget
{
Q_OBJECT
public:
explicit NetworkDeviceCard(const NetworkDevice &device,
QWidget *parent = nullptr);
private:
QPushButton *m_connectButton = nullptr;
public:
void failed();
};
class NetworkDevicesToConnectWidget : public QWidget
{
Q_OBJECT
@@ -43,6 +58,8 @@ public:
private slots:
void onWirelessDeviceAdded(const NetworkDevice &device);
void onWirelessDeviceRemoved(const QString &deviceName);
void onNoPairingFileForWirelessDevice(const QString &macAddress);
void onDeviceInitFailed(const QString &udid);
private:
void setupUI();
@@ -62,7 +79,7 @@ private:
DnssdService *m_networkProvider = nullptr;
#endif
QList<QWidget *> m_deviceCards;
QMap<QString, NetworkDeviceCard *> m_deviceCards;
};
#endif // NETWORKDEVICESTOCONNECTWIDGET_H