fix bugs and styles

- Refactored jailbroken tab
- Added new icons
- Fixed files not closed in  read_afc_file_to_byte_array
- Improved memory cache for thumbnails in `PhotoModel`, increasing limit to 150MB.
- Updated UI elements in `SponsorWidget` and `ToolboxWidget` for better aesthetics and usability.
This commit is contained in:
uncor3
2025-11-07 14:31:28 +00:00
parent e3a5d576f9
commit d0fb0870d4
39 changed files with 807 additions and 479 deletions
+88 -293
View File
@@ -19,8 +19,8 @@
#include "jailbrokenwidget.h"
#include "appcontext.h"
#include "opensshterminalwidget.h"
#include "responsiveqlabel.h"
#include "sshterminalwidget.h"
#ifdef __linux__
#include "core/services/avahi/avahi_service.h"
@@ -30,6 +30,7 @@
#include "iDescriptor-ui.h"
#include "iDescriptor.h"
#include <QApplication>
#include <QButtonGroup>
#include <QDebug>
#include <QGroupBox>
@@ -41,313 +42,107 @@
#include <QVBoxLayout>
#include <QWidget>
// TODO: theming is broken
JailbrokenWidget::JailbrokenWidget(QWidget *parent) : QWidget{parent}
{
QHBoxLayout *mainLayout = new QHBoxLayout(this);
mainLayout->setContentsMargins(2, 2, 2, 2);
mainLayout->setSpacing(2);
QGridLayout *mainLayout = new QGridLayout(this);
mainLayout->setContentsMargins(10, 10, 10, 10);
mainLayout->setSpacing(10);
// Create responsive image label
ResponsiveQLabel *deviceImageLabel = new ResponsiveQLabel(this);
deviceImageLabel->setPixmap(QPixmap(":/resources/iphone.png"));
deviceImageLabel->setMinimumWidth(200);
deviceImageLabel->setSizePolicy(QSizePolicy::Ignored,
QSizePolicy::Expanding);
deviceImageLabel->setStyleSheet("background: transparent; border: none;");
// Define all the tools you want to display
QList<JailbreakToolInfo> tools;
tools.append({"Open SSH Terminal", "Connect to your device via SSH",
":/resources/icons/TablerDatabaseExport.png"});
tools.append({"More Tools Coming", "New features will be added soon",
":/resources/icons/TablerDatabaseExport.png",
false}); // Disabled placeholder
mainLayout->addWidget(deviceImageLabel, 1);
const int maxColumns = 3;
for (int i = 0; i < tools.size(); ++i) {
const auto &toolInfo = tools[i];
ClickableWidget *toolWidget = createJailbreakTool(toolInfo);
// Connect to AppContext for device events
connect(AppContext::sharedInstance(), &AppContext::deviceAdded, this,
&JailbrokenWidget::onWiredDeviceAdded);
connect(AppContext::sharedInstance(), &AppContext::deviceRemoved, this,
&JailbrokenWidget::onWiredDeviceRemoved);
int row = i / maxColumns;
int col = i % maxColumns;
mainLayout->addWidget(toolWidget, row, col);
}
#ifdef __linux__
m_wirelessProvider = new AvahiService(this);
connect(m_wirelessProvider, &AvahiService::deviceAdded, this,
&JailbrokenWidget::onWirelessDeviceAdded);
connect(m_wirelessProvider, &AvahiService::deviceRemoved, this,
&JailbrokenWidget::onWirelessDeviceRemoved);
#else
m_wirelessProvider = new DnssdService(this);
connect(m_wirelessProvider, &DnssdService::deviceAdded, this,
&JailbrokenWidget::onWirelessDeviceAdded);
connect(m_wirelessProvider, &DnssdService::deviceRemoved, this,
&JailbrokenWidget::onWirelessDeviceRemoved);
#endif
// Right side: Device selection and Terminal
QWidget *rightContainer = new QWidget();
rightContainer->setSizePolicy(QSizePolicy::Expanding,
QSizePolicy::Expanding);
rightContainer->setMinimumWidth(400);
QVBoxLayout *rightLayout = new QVBoxLayout(rightContainer);
rightLayout->setContentsMargins(15, 15, 15, 15);
rightLayout->setSpacing(10);
setupDeviceSelectionUI(rightLayout);
mainLayout->addWidget(rightContainer, 3);
// Start scanning for wireless devices
m_wirelessProvider->startBrowsing();
// Populate initial devices
updateDeviceList();
// Add a stretch to the last row and column to push everything to the
// top-left
mainLayout->setRowStretch(mainLayout->rowCount(), 1);
mainLayout->setColumnStretch(mainLayout->columnCount(), 1);
}
void JailbrokenWidget::setupDeviceSelectionUI(QVBoxLayout *layout)
ClickableWidget *
JailbrokenWidget::createJailbreakTool(const JailbreakToolInfo &info)
{
// Create scroll area for device selection
QScrollArea *scrollArea = new QScrollArea();
scrollArea->setWidgetResizable(true);
scrollArea->setMinimumHeight(200);
scrollArea->setMaximumHeight(300);
scrollArea->setObjectName("devicescrollArea");
ClickableWidget *b = new ClickableWidget();
b->setCursor(Qt::PointingHandCursor);
b->setEnabled(info.enabled);
scrollArea->setStyleSheet("QWidget#devicescrollArea {border: none;}");
QWidget *scrollContent = new QWidget();
m_deviceLayout = new QVBoxLayout(scrollContent);
m_deviceLayout->setContentsMargins(5, 5, 5, 5);
m_deviceLayout->setSpacing(10);
// Use a theme-aware stylesheet for the background and hover effect
b->setStyleSheet("ClickableWidget {"
" border-radius: 8px;"
" padding: 10px;"
"}");
// Button group for device selection
m_deviceButtonGroup = new QButtonGroup(this);
connect(m_deviceButtonGroup,
QOverload<QAbstractButton *>::of(&QButtonGroup::buttonClicked),
this, &JailbrokenWidget::onDeviceSelected);
QVBoxLayout *layout = new QVBoxLayout(b);
// Wired devices group
m_wiredDevicesGroup = new QGroupBox("Connected Devices");
m_wiredDevicesLayout = new QVBoxLayout(m_wiredDevicesGroup);
m_deviceLayout->addWidget(m_wiredDevicesGroup);
// Icon (using the theme-aware ZIcon pattern)
// ZIconLabel *iconLabel = new ZIconLabel();
ZIconLabel *iconLabel = new ZIconLabel(QIcon(), nullptr, this);
// Wireless devices group
m_wirelessDevicesGroup = new QGroupBox("Network Devices");
m_wirelessDevicesLayout = new QVBoxLayout(m_wirelessDevicesGroup);
m_deviceLayout->addWidget(m_wirelessDevicesGroup);
// iconLabel->setAlignment(Qt::AlignCenter);
// ZIcon toolIcon(QIcon(info.iconPath));
scrollArea->setWidget(scrollContent);
layout->addWidget(scrollArea);
// auto updateIcon = [b, iconLabel, toolIcon]() {
// iconLabel->setPixmap(
// toolIcon.getThemedPixmap(QSize(45, 45), b->palette()));
// };
// updateIcon();
// connect(qApp, &QApplication::paletteChanged, b, updateIcon);
// Info and connect button
m_infoLabel = new QLabel("Select a device to connect");
layout->addWidget(m_infoLabel);
// Title
QLabel *titleLabel = new QLabel(info.title);
titleLabel->setAlignment(Qt::AlignCenter);
QFont titleFont = titleLabel->font();
titleFont.setBold(true);
titleLabel->setFont(titleFont);
m_connectButton = new QPushButton("Open SSH Terminal");
m_connectButton->setEnabled(false);
connect(m_connectButton, &QPushButton::clicked, this,
&JailbrokenWidget::onOpenSSHTerminal);
layout->addWidget(m_connectButton);
// Description (using a theme-aware palette color)
QLabel *descLabel = new QLabel(info.description);
descLabel->setWordWrap(true);
descLabel->setAlignment(Qt::AlignCenter);
descLabel->setStyleSheet("font-size: 12px;");
layout->addWidget(iconLabel, 0, Qt::AlignCenter);
layout->addWidget(titleLabel);
layout->addWidget(descLabel);
// TODO: Connect the clicked signal to a slot
if (info.title == "Open SSH Terminal") {
iconLabel->setIcon(QIcon(":/resources/icons/BxBxsTerminal.png"));
connect(b, &ClickableWidget::clicked, this, [this]() {
if (m_sshTerminalWidget) {
m_sshTerminalWidget->raise();
m_sshTerminalWidget->activateWindow();
return;
}
m_sshTerminalWidget = new OpenSSHTerminalWidget();
m_sshTerminalWidget->setAttribute(Qt::WA_DeleteOnClose);
m_sshTerminalWidget->show();
m_sshTerminalWidget->raise();
m_sshTerminalWidget->activateWindow();
connect(m_sshTerminalWidget, &QObject::destroyed, this,
[this]() { m_sshTerminalWidget = nullptr; });
});
} else if (info.title == "More Tools Coming") {
iconLabel->setIcon(
QIcon(":/resources/icons/IconParkTwotoneMoreTwo.png"));
}
iconLabel->setFixedSize(60, 60);
iconLabel->setIconSize(QSize(45, 45));
return b;
}
void JailbrokenWidget::updateDeviceList()
{
// Clear existing devices
clearDeviceButtons();
// Add wired devices
QList<iDescriptorDevice *> wiredDevices =
AppContext::sharedInstance()->getAllDevices();
for (iDescriptorDevice *device : wiredDevices) {
addWiredDevice(device);
}
// Add wireless devices
QList<NetworkDevice> wirelessDevices =
m_wirelessProvider->getNetworkDevices();
for (const NetworkDevice &device : wirelessDevices) {
addWirelessDevice(device);
}
}
void JailbrokenWidget::clearDeviceButtons()
{
// Remove all buttons from button group and layouts
for (QAbstractButton *button : m_deviceButtonGroup->buttons()) {
m_deviceButtonGroup->removeButton(button);
button->deleteLater();
}
// Clear layouts
QLayoutItem *item;
while ((item = m_wiredDevicesLayout->takeAt(0)) != nullptr) {
delete item->widget();
delete item;
}
while ((item = m_wirelessDevicesLayout->takeAt(0)) != nullptr) {
delete item->widget();
delete item;
}
}
void JailbrokenWidget::addWiredDevice(iDescriptorDevice *device)
{
QString deviceName = QString::fromStdString(device->deviceInfo.deviceName);
QString udid = QString::fromStdString(device->udid);
QString displayText = QString("%1\n%2").arg(deviceName, udid);
QRadioButton *radioButton = new QRadioButton(displayText);
radioButton->setProperty("deviceType", "wired");
radioButton->setProperty("devicePointer",
QVariant::fromValue(static_cast<void *>(device)));
radioButton->setProperty("udid", udid);
m_deviceButtonGroup->addButton(radioButton);
m_wiredDevicesLayout->addWidget(radioButton);
}
void JailbrokenWidget::addWirelessDevice(const NetworkDevice &device)
{
QString displayText = QString("%1\n%2").arg(device.name, device.address);
QRadioButton *radioButton = new QRadioButton(displayText);
radioButton->setProperty("deviceType", "wireless");
radioButton->setProperty("deviceAddress", device.address);
radioButton->setProperty("deviceName", device.name);
radioButton->setProperty("devicePort", device.port);
m_deviceButtonGroup->addButton(radioButton);
m_wirelessDevicesLayout->addWidget(radioButton);
}
void JailbrokenWidget::onWiredDeviceAdded(iDescriptorDevice *device)
{
addWiredDevice(device);
}
void JailbrokenWidget::onWiredDeviceRemoved(const std::string &udid)
{
QString qudid = QString::fromStdString(udid);
// Find and remove the corresponding radio button
for (QAbstractButton *button : m_deviceButtonGroup->buttons()) {
if (button->property("deviceType").toString() == "wired" &&
button->property("udid").toString() == qudid) {
m_deviceButtonGroup->removeButton(button);
button->deleteLater();
break;
}
}
// Reset selection if this device was selected
if (m_selectedDeviceType == DeviceType::Wired && m_selectedWiredDevice &&
m_selectedWiredDevice->udid == udid) {
resetSelection();
}
}
void JailbrokenWidget::onWirelessDeviceAdded(const NetworkDevice &device)
{
addWirelessDevice(device);
}
void JailbrokenWidget::onWirelessDeviceRemoved(const QString &deviceName)
{
// Find and remove the corresponding radio button
for (QAbstractButton *button : m_deviceButtonGroup->buttons()) {
if (button->property("deviceType").toString() == "wireless" &&
button->property("deviceName").toString() == deviceName) {
m_deviceButtonGroup->removeButton(button);
button->deleteLater();
break;
}
}
// Reset selection if this device was selected
if (m_selectedDeviceType == DeviceType::Wireless &&
m_selectedNetworkDevice.name == deviceName) {
resetSelection();
}
}
void JailbrokenWidget::onDeviceSelected(QAbstractButton *button)
{
QString deviceType = button->property("deviceType").toString();
if (deviceType == "wired") {
m_selectedDeviceType = DeviceType::Wired;
m_selectedWiredDevice = static_cast<iDescriptorDevice *>(
button->property("devicePointer").value<void *>());
if (m_selectedWiredDevice->deviceInfo.jailbroken) {
m_infoLabel->setText("Jailbroken device selected");
} else {
m_infoLabel->setText(
"Device selected (detected as non-jailbroken)");
}
} else if (deviceType == "wireless") {
m_selectedDeviceType = DeviceType::Wireless;
m_selectedNetworkDevice.name =
button->property("deviceName").toString();
m_selectedNetworkDevice.address =
button->property("deviceAddress").toString();
m_selectedNetworkDevice.port = button->property("devicePort").toUInt();
m_infoLabel->setText(
"Network device selected (jailbreak status unknown)");
}
m_connectButton->setEnabled(true);
m_connectButton->setText("Open SSH Terminal");
}
void JailbrokenWidget::resetSelection()
{
m_selectedDeviceType = DeviceType::None;
m_selectedWiredDevice = nullptr;
m_selectedNetworkDevice = NetworkDevice{};
m_connectButton->setEnabled(false);
m_infoLabel->setText("Select a device to connect");
// Uncheck all radio buttons
if (m_deviceButtonGroup->checkedButton()) {
m_deviceButtonGroup->setExclusive(false);
m_deviceButtonGroup->checkedButton()->setChecked(false);
m_deviceButtonGroup->setExclusive(true);
}
}
void JailbrokenWidget::onOpenSSHTerminal()
{
if (m_selectedDeviceType == DeviceType::None) {
m_infoLabel->setText("Please select a device first");
return;
}
// Prepare connection info
ConnectionInfo connectionInfo;
if (m_selectedDeviceType == DeviceType::Wired) {
if (!m_selectedWiredDevice) {
m_infoLabel->setText("No wired device selected");
return;
}
connectionInfo.type = ConnectionType::Wired;
connectionInfo.deviceName = QString::fromStdString(
m_selectedWiredDevice->deviceInfo.deviceName);
connectionInfo.deviceUdid =
QString::fromStdString(m_selectedWiredDevice->udid);
connectionInfo.hostAddress = "127.0.0.1";
connectionInfo.port = 22;
} else if (m_selectedDeviceType == DeviceType::Wireless) {
connectionInfo.type = ConnectionType::Wireless;
connectionInfo.deviceName = m_selectedNetworkDevice.name;
connectionInfo.deviceUdid = "";
connectionInfo.hostAddress = m_selectedNetworkDevice.address;
connectionInfo.port = m_selectedNetworkDevice.port;
}
// Create and show SSH terminal widget in a new window
SSHTerminalWidget *sshTerminal = new SSHTerminalWidget(connectionInfo);
sshTerminal->setAttribute(Qt::WA_DeleteOnClose);
sshTerminal->show();
sshTerminal->raise();
sshTerminal->activateWindow();
}
JailbrokenWidget::~JailbrokenWidget() {}
JailbrokenWidget::~JailbrokenWidget() {}