-Properly scale icons
-Show changelog
-Add iconSizeBaseMultiplier
This commit is contained in:
uncor3
2025-12-08 20:02:38 +00:00
parent f0d049a2da
commit c1f38dbd18
17 changed files with 327 additions and 48 deletions
+2 -1
View File
@@ -12,7 +12,8 @@
"/usr/include/qt6/**",
"/usr/include/qt6/QtBluetooth/**",
"${workspaceFolder}/lib/zupdater/src",
"/usr/include/qt6/QtConcurrent"
"/usr/include/qt6/QtConcurrent",
"/usr/include/qt6"
],
"defines": [],
"compilerPath": "/usr/bin/gcc",
+3 -1
View File
@@ -202,6 +202,8 @@
"qimage": "cpp",
"qabstractbutton": "cpp",
"qtnetwork": "cpp",
"qtcore": "cpp"
"qtcore": "cpp",
"qbluetoothdevicediscoveryagent": "cpp",
"qbluetoothuuid": "cpp"
}
}
+2 -2
View File
@@ -1,5 +1,5 @@
cmake_minimum_required(VERSION 3.16)
project(iDescriptor VERSION 0.1.0 LANGUAGES CXX)
project(iDescriptor VERSION 0.1.2 LANGUAGES CXX)
# Feature options
option(ENABLE_RECOVERY_DEVICE_SUPPORT "Enable recovery device support (requires libirecovery)" ON)
@@ -55,7 +55,7 @@ endforeach()
list(APPEND _qt_pkg_dirs ${CUSTOM_PKGCONFIG_PATH})
find_package(PkgConfig REQUIRED)
find_package(Qt6 REQUIRED COMPONENTS Widgets Multimedia MultimediaWidgets Network QuickControls2 SerialPort Positioning Location QuickWidgets)
find_package(Qt6 REQUIRED COMPONENTS Widgets Multimedia MultimediaWidgets Network QuickControls2 SerialPort Positioning Location QuickWidgets)
# Add QTermWidget
# Prefer CMake-native qtermwidget6, fallback to pkg-config if needed
+11 -11
View File
@@ -76,20 +76,19 @@ DeviceInfoWidget::DeviceInfoWidget(iDescriptorDevice *device, QWidget *parent)
ZIconWidget *shutdownBtn = new ZIconWidget(
QIcon(":/resources/icons/IcOutlinePowerSettingsNew.png"), "Shutdown",
this);
shutdownBtn->setIconSize(QSize(20, 20));
1.0, this);
connect(shutdownBtn, &ZIconWidget::clicked, this,
[device]() { ToolboxWidget::shutdownDevice(device); });
ZIconWidget *restartBtn = new ZIconWidget(
QIcon(":/resources/icons/IcTwotoneRestartAlt.png"), "Restart", this);
restartBtn->setIconSize(QSize(20, 20));
ZIconWidget *restartBtn =
new ZIconWidget(QIcon(":/resources/icons/IcTwotoneRestartAlt.png"),
"Restart", 1.0, this);
connect(restartBtn, &ZIconWidget::clicked, this,
[device]() { ToolboxWidget::restartDevice(device); });
ZIconWidget *recoveryBtn = new ZIconWidget(
QIcon(":/resources/icons/HugeiconsWrench01.png"), "Recovery", this);
recoveryBtn->setIconSize(QSize(20, 20));
ZIconWidget *recoveryBtn =
new ZIconWidget(QIcon(":/resources/icons/HugeiconsWrench01.png"),
"Recovery", 1.0, this);
connect(recoveryBtn, &ZIconWidget::clicked, this,
[device]() { ToolboxWidget::_enterRecoveryMode(device); });
@@ -155,9 +154,10 @@ DeviceInfoWidget::DeviceInfoWidget(iDescriptorDevice *device, QWidget *parent)
chargingLayout->setSpacing(5);
// Create icon label
m_lightningIconLabel = new ZIconLabel(
QIcon(":/resources/icons/MdiLightningBolt.png"), " Charging", this);
m_lightningIconLabel->setFixedSize(QSize(20, 20));
m_lightningIconLabel =
new ZIconLabel(QIcon(":/resources/icons/MdiLightningBolt.png"),
" Charging", 1.0, this);
m_batteryWidget = new BatteryWidget(
qBound<int>(1, device->deviceInfo.batteryInfo.currentBatteryLevel, 100),
device->deviceInfo.batteryInfo.isCharging, this);
+65 -14
View File
@@ -18,6 +18,7 @@
*/
#pragma once
#include "settingsmanager.h"
#include <QAbstractButton>
#include <QApplication>
#include <QGraphicsView>
@@ -141,18 +142,35 @@ class ZIconWidget : public QAbstractButton
{
Q_OBJECT
public:
ZIconWidget(const QIcon &icon, const QString &tooltip,
QWidget *parent = nullptr)
: QAbstractButton(parent), m_icon(icon)
ZIconWidget(const QIcon &icon, const QString &tooltip = "",
qreal iconSizeMultiplier = 1.0, QWidget *parent = nullptr)
: QAbstractButton(parent), m_icon(icon),
m_iconSizeMultiplier(iconSizeMultiplier)
{
setToolTip(tooltip);
setFixedSize(32, 32);
setIconSize(QSize(24, 24));
if (tooltip != "") {
setToolTip(tooltip);
}
QFontMetrics fm(font());
double baseSize =
fm.height() * m_iconSizeMultiplier *
SettingsManager::sharedInstance()->iconSizeBaseMultiplier();
int intBaseSize = qRound(baseSize);
m_iconSize = QSize(intBaseSize, intBaseSize);
setFixedSize(intBaseSize + 10, intBaseSize + 10);
update();
setCursor(Qt::PointingHandCursor);
connect(qApp, &QApplication::paletteChanged, this,
[this]() { update(); });
}
void setIconSizeMultiplier(qreal multiplier)
{
m_iconSizeMultiplier = multiplier;
updateIconSize();
}
void setIcon(const QIcon &icon)
{
m_icon = ZIcon(icon);
@@ -176,14 +194,31 @@ protected:
}
QRect iconRect = rect();
iconRect.setSize(iconSize()); // Use iconSize() from QAbstractButton
iconRect.setSize(m_iconSize);
iconRect.moveCenter(rect().center());
m_icon.paint(&painter, iconRect, palette());
}
private:
void updateIconSize()
{
QFontMetrics fm(font());
double baseSize =
fm.height() * m_iconSizeMultiplier *
SettingsManager::sharedInstance()->iconSizeBaseMultiplier();
int intBaseSize = qRound(baseSize);
setFixedSize(intBaseSize + 10, intBaseSize + 10);
m_iconSize = QSize(intBaseSize, intBaseSize);
update();
}
private:
ZIcon m_icon;
QSize m_iconSize;
qreal m_iconSizeMultiplier;
};
// Add this new class for display-only icons
@@ -192,15 +227,16 @@ class ZIconLabel : public QLabel
Q_OBJECT
public:
ZIconLabel(const QIcon &icon, const QString &tooltip,
QWidget *parent = nullptr)
: QLabel(parent), m_icon(icon), m_iconSize(24, 24)
qreal iconSizeMultiplier = 1.0, QWidget *parent = nullptr)
: QLabel(parent), m_icon(icon), m_iconSizeMultiplier(iconSizeMultiplier)
{
setToolTip(tooltip);
// setFixedSize(32, 32);
updateIconSize();
connect(qApp, &QApplication::paletteChanged, this,
[this]() { update(); });
connect(qApp, &QApplication::fontChanged, this,
[this]() { updateIconSize(); });
}
void setIcon(const QIcon &icon)
{
m_icon = ZIcon(icon);
@@ -213,10 +249,10 @@ public:
update();
}
void setIconSize(const QSize &size)
void setIconSizeMultiplier(qreal multiplier)
{
m_iconSize = size;
update();
m_iconSizeMultiplier = multiplier;
updateIconSize();
}
protected:
@@ -234,8 +270,23 @@ protected:
}
private:
void updateIconSize()
{
QFontMetrics fm(font());
double baseSize =
fm.height() * m_iconSizeMultiplier *
SettingsManager::sharedInstance()->iconSizeBaseMultiplier();
int intBaseSize = qRound(baseSize);
setFixedSize(intBaseSize + 10, intBaseSize + 10);
m_iconSize = QSize(intBaseSize, intBaseSize);
update();
}
ZIcon m_icon;
QSize m_iconSize;
qreal m_iconSizeMultiplier;
};
enum class iDescriptorTool {
+2
View File
@@ -54,6 +54,8 @@
"https://raw.githubusercontent.com/iDescriptor/iDescriptor/refs/heads/" \
"main/DeveloperDiskImages.json"
#define DONATE_URL "https://opencollective.com/idescriptor"
// This is because afc_read_directory accepts "/var/mobile/Media" as "/"
#define POSSIBLE_ROOT "../../../../"
+1 -1
View File
@@ -25,7 +25,7 @@
iFuseDiskUnmountButton::iFuseDiskUnmountButton(const QString &path,
QWidget *parent)
: ZIconWidget{QIcon(":/resources/icons/ClarityHardDiskSolidAlerted.png"),
"Unmount iFuse at " + path, parent}
"Unmount iFuse at " + path, 1.0, parent}
{
setCursor(Qt::PointingHandCursor);
setFixedSize(24, 24);
+2 -3
View File
@@ -89,7 +89,7 @@ JailbrokenWidget::createJailbreakTool(const JailbreakToolInfo &info)
// Icon (using the theme-aware ZIcon pattern)
// ZIconLabel *iconLabel = new ZIconLabel();
ZIconLabel *iconLabel = new ZIconLabel(QIcon(), nullptr, this);
ZIconLabel *iconLabel = new ZIconLabel(QIcon(), nullptr, 1.5, this);
// iconLabel->setAlignment(Qt::AlignCenter);
// ZIcon toolIcon(QIcon(info.iconPath));
@@ -140,8 +140,7 @@ JailbrokenWidget::createJailbreakTool(const JailbreakToolInfo &info)
iconLabel->setIcon(
QIcon(":/resources/icons/IconParkTwotoneMoreTwo.png"));
}
iconLabel->setFixedSize(60, 60);
iconLabel->setIconSize(QSize(45, 45));
iconLabel->setIconSizeMultiplier(2);
return b;
}
+21 -9
View File
@@ -19,16 +19,15 @@
#include "mainwindow.h"
#include "./ui_mainwindow.h"
#include "detailwindow.h"
#include "ifusediskunmountbutton.h"
#include "ifusemanager.h"
#include "settingswidget.h"
#include "appswidget.h"
#include "devicemanagerwidget.h"
#include "iDescriptor-ui.h"
#include "iDescriptor.h"
#include "ifusediskunmountbutton.h"
#include "ifusemanager.h"
#include "jailbrokenwidget.h"
#include "releasechangelogdialog.h"
#include "settingswidget.h"
#ifdef ENABLE_RECOVERY_DEVICE_SUPPORT
#include "libirecovery.h"
#endif
@@ -55,7 +54,7 @@
void handleCallback(const idevice_event_t *event, void *userData)
{
printf("Device event received: ");
qDebug() << "Device event received";
switch (event->event) {
case IDEVICE_DEVICE_ADD: {
@@ -140,7 +139,6 @@ MainWindow::MainWindow(QWidget *parent)
const QSize minSize(900, 600);
setMinimumSize(minSize);
resize(minSize);
m_ZTabWidget = new ZTabWidget(this);
m_ZTabWidget->setAttribute(Qt::WA_ContentsMarginsRespectsSafeArea, false);
@@ -179,7 +177,6 @@ MainWindow::MainWindow(QWidget *parent)
ZIconWidget *settingsButton = new ZIconWidget(
QIcon(":/resources/icons/MingcuteSettings7Line.png"), "Settings");
settingsButton->setCursor(Qt::PointingHandCursor);
settingsButton->setFixedSize(24, 24);
connect(settingsButton, &ZIconWidget::clicked, this, [this]() {
SettingsManager::sharedInstance()->showSettingsDialog();
});
@@ -187,7 +184,6 @@ MainWindow::MainWindow(QWidget *parent)
ZIconWidget *githubButton = new ZIconWidget(
QIcon(":/resources/icons/MdiGithub.png"), "iDescriptor on GitHub");
githubButton->setCursor(Qt::PointingHandCursor);
githubButton->setFixedSize(24, 24);
connect(githubButton, &ZIconWidget::clicked, this,
[]() { QDesktopServices::openUrl(QUrl(REPO_URL)); });
@@ -325,6 +321,22 @@ MainWindow::MainWindow(QWidget *parent)
.arg(PACKAGE_MANAGER_HINT));
#endif
QString lastAppVersion = SettingsManager::sharedInstance()->appVersion();
bool shouldShowReleaseChangelog = lastAppVersion != APP_VERSION;
SettingsManager::sharedInstance()->setAppVersion(APP_VERSION);
if (shouldShowReleaseChangelog) {
connect(
m_updater, &ZUpdater::dataAvailable, this,
[this](const QJsonDocument data, bool isUpdateAvailable) {
if (!isUpdateAvailable) {
ReleaseChangelogDialog dialog(data, this);
dialog.exec();
}
},
Qt::SingleShotConnection);
}
SettingsManager::sharedInstance()->doIfEnabled(
SettingsManager::Setting::AutoCheckUpdates, [this]() {
qDebug() << "Checking for updates...";
+1 -1
View File
@@ -32,7 +32,7 @@ PrivateInfoLabel::PrivateInfoLabel(const QString &fullText, QWidget *parent)
layout->addWidget(m_textLabel);
m_toggleButton = new ZIconWidget(
QIcon(":/resources/icons/ClarityEyeHideLine.png"), "Show", this);
QIcon(":/resources/icons/ClarityEyeHideLine.png"), "Show", 1.0, this);
m_toggleButton->setIconSize(QSize(20, 20));
connect(m_toggleButton, &ZIconWidget::clicked, this,
&PrivateInfoLabel::toggleVisibility);
+115
View File
@@ -0,0 +1,115 @@
/*
* iDescriptor: A free and open-source idevice management tool.
*
* Copyright (C) 2025 Uncore <https://github.com/uncor3>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include "releasechangelogdialog.h"
#include "iDescriptor.h"
#include "settingsmanager.h"
#include <QApplication>
#include <QCheckBox>
#include <QDesktopServices>
#include <QJsonObject>
#include <QLabel>
#include <QPushButton>
#include <QUrl>
#include <QVBoxLayout>
ReleaseChangelogDialog::ReleaseChangelogDialog(QJsonDocument data,
QWidget *parent)
: QDialog(parent)
{
setupUI(data);
}
ReleaseChangelogDialog::~ReleaseChangelogDialog() {}
void ReleaseChangelogDialog::setupUI(const QJsonDocument &data)
{
setWindowTitle("iDescriptor - Release Changelog");
setModal(true);
setMinimumSize(500, 250);
resize(600, 300);
m_mainLayout = new QVBoxLayout(this);
m_mainLayout->setContentsMargins(20, 20, 20, 20);
m_mainLayout->setSpacing(15);
m_titleLabel =
new QLabel(QString("iDescriptor has been updated to v") + APP_VERSION);
m_titleLabel->setAlignment(Qt::AlignCenter);
m_titleLabel->setStyleSheet(
"font-size: 18px; font-weight: bold; margin-bottom: 10px;");
m_mainLayout->addWidget(m_titleLabel);
QString description = "Failed to load changelog data.";
QJsonArray dataArr = data.array();
if (!dataArr.isEmpty()) {
for (const QJsonValue &releaseVal : dataArr) {
QJsonObject releaseObj = releaseVal.toObject();
if (!releaseObj.isEmpty()) {
QString tagName = releaseObj.value("tag_name").toString();
if (tagName.isEmpty()) {
continue;
}
if (tagName == QString("v") + APP_VERSION) {
if (releaseObj.value("body").isUndefined())
break;
description = releaseObj.value("body").toString();
break;
}
}
}
}
m_descriptionLabel = new QLabel(description);
m_descriptionLabel->setAlignment(Qt::AlignCenter);
m_descriptionLabel->setWordWrap(true);
m_descriptionLabel->setStyleSheet("font-size: 14px; margin: 10px;");
m_mainLayout->addWidget(m_descriptionLabel);
m_mainLayout->addStretch();
QHBoxLayout *buttonsLayout = new QHBoxLayout();
m_skipButton = new QPushButton("Ok, Thanks!");
m_skipButton->setFixedHeight(40);
m_donateButton = new QPushButton("Donate");
m_donateButton->setDefault(true);
m_donateButton->setFixedHeight(40);
buttonsLayout->addWidget(m_skipButton);
buttonsLayout->addWidget(m_donateButton);
m_mainLayout->addLayout(buttonsLayout, Qt::AlignCenter);
connect(m_donateButton, &QPushButton::clicked, this,
&ReleaseChangelogDialog::onDonateClicked);
connect(m_skipButton, &QPushButton::clicked, this,
&ReleaseChangelogDialog::onSkipButtonClicked);
}
void ReleaseChangelogDialog::onDonateClicked()
{
QDesktopServices::openUrl(QUrl(DONATE_URL));
accept();
}
void ReleaseChangelogDialog::onSkipButtonClicked() { accept(); }
+33
View File
@@ -0,0 +1,33 @@
#ifndef RELEASECHANGELOG_H
#define RELEASECHANGELOG_H
#include <QDialog>
#include <QJsonArray>
#include <QLabel>
#include <QPushButton>
#include <QVBoxLayout>
class ReleaseChangelogDialog : public QDialog
{
Q_OBJECT
public:
explicit ReleaseChangelogDialog(QJsonDocument data,
QWidget *parent = nullptr);
~ReleaseChangelogDialog();
signals:
private:
void setupUI(const QJsonDocument &data);
QVBoxLayout *m_mainLayout = nullptr;
QPushButton *m_skipButton = nullptr;
QPushButton *m_donateButton = nullptr;
QLabel *m_titleLabel = nullptr;
QLabel *m_descriptionLabel = nullptr;
void onDonateClicked();
void onSkipButtonClicked();
};
#endif // RELEASECHANGELOG_H
+22
View File
@@ -368,4 +368,26 @@ void SettingsManager::clearRecentLocations()
{
m_settings->remove("recentLocations");
m_settings->sync();
}
QString SettingsManager::appVersion()
{
return m_settings->value("__APP_VERSION__", "").toString();
}
void SettingsManager::setAppVersion(const QString &version)
{
m_settings->setValue("__APP_VERSION__", version);
m_settings->sync();
}
double SettingsManager::iconSizeBaseMultiplier() const
{
return m_settings->value("iconSizeBaseMultiplier", 1.0).toDouble();
}
void SettingsManager::setIconSizeBaseMultiplier(double multiplier)
{
m_settings->setValue("iconSizeBaseMultiplier", multiplier);
m_settings->sync();
}
+6
View File
@@ -99,6 +99,12 @@ public:
void resetToDefaults();
void clear();
QString appVersion();
void setAppVersion(const QString &version);
double iconSizeBaseMultiplier() const;
void setIconSizeBaseMultiplier(double multiplier);
signals:
void favoritePlacesChanged();
void recentLocationsChanged();
+37 -2
View File
@@ -153,6 +153,29 @@ void SettingsWidget::setupUI()
scrollLayout->addWidget(jailbrokenGroup);
// === MISCELLANEOUS SETTINGS ===
auto *miscGroup = new QGroupBox("Miscellaneous");
auto *miscLayout = new QVBoxLayout(miscGroup);
auto *iconSizeBaseMultiplierLayout = new QHBoxLayout();
m_iconSizeBaseMultiplier = new QDoubleSpinBox();
m_iconSizeBaseMultiplier->setRange(1.0, 5.0);
m_iconSizeBaseMultiplier->setSingleStep(0.1);
m_iconSizeBaseMultiplier->setDecimals(1);
m_iconSizeBaseMultiplier->setSuffix("x");
m_iconSizeBaseMultiplier->setToolTip(
"Adjust the base multiplier for icon sizes. This affects how large "
"icons appear throughout the application. Requires restart to take "
"effect.");
iconSizeBaseMultiplierLayout->addWidget(
new QLabel("Icon Size Base Multiplier:"));
iconSizeBaseMultiplierLayout->addWidget(m_iconSizeBaseMultiplier);
iconSizeBaseMultiplierLayout->addStretch();
miscLayout->addLayout(iconSizeBaseMultiplierLayout);
scrollLayout->addWidget(miscGroup);
scrollLayout->addSpacing(30);
// Add a footer Author & Version & app info & app description
@@ -163,7 +186,7 @@ void SettingsWidget::setupUI()
"© 2025 See AUTHORS for details. Licensed under AGPLv3.")
.arg(APP_VERSION));
footerLabel->setAlignment(Qt::AlignCenter);
footerLabel->setStyleSheet("color: gray; font-size: 10pt;");
footerLabel->setStyleSheet("color: gray; font-size: 8pt;");
scrollLayout->addWidget(footerLabel);
// Add stretch to push everything to the top
@@ -225,6 +248,8 @@ void SettingsWidget::loadSettings()
// Disable apply button initially
m_applyButton->setEnabled(false);
m_iconSizeBaseMultiplier->setValue(sm->iconSizeBaseMultiplier());
}
void SettingsWidget::connectSignals()
@@ -245,12 +270,20 @@ void SettingsWidget::connectSignals()
connect(m_connectionTimeout, QOverload<int>::of(&QSpinBox::valueChanged),
this, &SettingsWidget::onSettingChanged);
connect(m_iconSizeBaseMultiplier,
QOverload<double>::of(&QDoubleSpinBox::valueChanged), this,
[this]() {
m_restartRequired = true;
onSettingChanged();
});
connect(m_useUnsecureBackend, &QCheckBox::toggled, this, [this]() {
// since this is unsafe if its being enabled, show a warning
if (m_useUnsecureBackend->isChecked()) {
auto reply = QMessageBox::warning(
this, "Warning",
"Enabling this will not encrypt your Apple account which is a "
"Enabling this will not encrypt your Apple account which "
"is a "
"security risk. Are you sure you want to enable this?",
QMessageBox::Yes | QMessageBox::No, QMessageBox::No);
@@ -345,6 +378,8 @@ void SettingsWidget::saveSettings()
sm->setDefaultJailbrokenRootPassword(
m_defaultJailbrokenRootPassword->text());
sm->setIconSizeBaseMultiplier(m_iconSizeBaseMultiplier->value());
m_applyButton->setEnabled(false);
}
+2
View File
@@ -66,6 +66,8 @@ private:
// Jailbroken
QLineEdit *m_defaultJailbrokenRootPassword;
QDoubleSpinBox *m_iconSizeBaseMultiplier;
// Buttons
QPushButton *m_checkUpdatesButton;
QPushButton *m_resetButton;
+2 -3
View File
@@ -220,7 +220,7 @@ ClickableWidget *ToolboxWidget::createToolbox(iDescriptorTool tool,
QVBoxLayout *layout = new QVBoxLayout(b);
ZIconLabel *icon = new ZIconLabel(QIcon(), nullptr, this);
ZIconLabel *icon = new ZIconLabel(QIcon(), nullptr, 1.5, this);
QString title;
switch (tool) {
case iDescriptorTool::Airplayer:
@@ -298,8 +298,7 @@ ClickableWidget *ToolboxWidget::createToolbox(iDescriptorTool tool,
descLabel->setWordWrap(true);
descLabel->setAlignment(Qt::AlignCenter);
descLabel->setStyleSheet("color: #666; font-size: 12px;");
icon->setFixedSize(60, 60);
icon->setIconSize(QSize(45, 45));
icon->setIconSizeMultiplier(1.90);
layout->addWidget(icon, 0, Qt::AlignCenter);
layout->addWidget(titleLabel);