diff --git a/resources.qrc b/resources.qrc
index 0471523..5b98687 100644
--- a/resources.qrc
+++ b/resources.qrc
@@ -12,5 +12,28 @@
qml/MapView.qml
resources/dump.js
resources/iphone.png
+ resources/ios-wallpapers/iphone-ios4.png
+ resources/ios-wallpapers/iphone-ios5.png
+ resources/ios-wallpapers/iphone-ios6.png
+ resources/ios-wallpapers/iphone-ios7.png
+ resources/ios-wallpapers/iphone-ios8.png
+ resources/ios-wallpapers/iphone-ios9.png
+ resources/ios-wallpapers/iphone-ios10.png
+ resources/ios-wallpapers/iphone-ios11.png
+ resources/ios-wallpapers/iphone-ios12.png
+ resources/ios-wallpapers/iphone-ios13.png
+ resources/ios-wallpapers/iphone-ios14.png
+ resources/ios-wallpapers/iphone-ios15.png
+ resources/ios-wallpapers/iphone-ios16.png
+ resources/ios-wallpapers/iphone-ios17.png
+ resources/ios-wallpapers/iphone-ios18.png
+ resources/ios-wallpapers/iphone-ios26.png
+ resources/iphone-mockups/iphone-3.png
+ resources/iphone-mockups/iphone-4.png
+ resources/iphone-mockups/iphone-5.png
+ resources/iphone-mockups/iphone-6.png
+ resources/iphone-mockups/iphone-x.png
+ resources/iphone-mockups/iphone-15.png
+ resources/iphone-mockups/iphone-16.png
\ No newline at end of file
diff --git a/resources/ios-wallpapers/iphone-ios10.png b/resources/ios-wallpapers/iphone-ios10.png
new file mode 100644
index 0000000..b221f16
Binary files /dev/null and b/resources/ios-wallpapers/iphone-ios10.png differ
diff --git a/resources/ios-wallpapers/iphone-ios11.png b/resources/ios-wallpapers/iphone-ios11.png
new file mode 100644
index 0000000..d8781c5
Binary files /dev/null and b/resources/ios-wallpapers/iphone-ios11.png differ
diff --git a/resources/ios-wallpapers/iphone-ios12.png b/resources/ios-wallpapers/iphone-ios12.png
new file mode 100644
index 0000000..7fc1379
Binary files /dev/null and b/resources/ios-wallpapers/iphone-ios12.png differ
diff --git a/resources/ios-wallpapers/iphone-ios5.png b/resources/ios-wallpapers/iphone-ios5.png
new file mode 100644
index 0000000..ca429fa
Binary files /dev/null and b/resources/ios-wallpapers/iphone-ios5.png differ
diff --git a/resources/iphone-mockups/iphone-15.png b/resources/iphone-mockups/iphone-15.png
new file mode 100755
index 0000000..92e5680
Binary files /dev/null and b/resources/iphone-mockups/iphone-15.png differ
diff --git a/resources/iphone-mockups/iphone-16.png b/resources/iphone-mockups/iphone-16.png
new file mode 100755
index 0000000..2445a57
Binary files /dev/null and b/resources/iphone-mockups/iphone-16.png differ
diff --git a/resources/iphone-mockups/iphone-3.png b/resources/iphone-mockups/iphone-3.png
new file mode 100755
index 0000000..a788d2e
Binary files /dev/null and b/resources/iphone-mockups/iphone-3.png differ
diff --git a/resources/iphone-mockups/iphone-4.png b/resources/iphone-mockups/iphone-4.png
new file mode 100755
index 0000000..7344ceb
Binary files /dev/null and b/resources/iphone-mockups/iphone-4.png differ
diff --git a/resources/iphone-mockups/iphone-5.png b/resources/iphone-mockups/iphone-5.png
new file mode 100755
index 0000000..0b23128
Binary files /dev/null and b/resources/iphone-mockups/iphone-5.png differ
diff --git a/resources/iphone-mockups/iphone-6.png b/resources/iphone-mockups/iphone-6.png
new file mode 100755
index 0000000..b37bff6
Binary files /dev/null and b/resources/iphone-mockups/iphone-6.png differ
diff --git a/resources/iphone-mockups/iphone-x.png b/resources/iphone-mockups/iphone-x.png
new file mode 100755
index 0000000..f0cd464
Binary files /dev/null and b/resources/iphone-mockups/iphone-x.png differ
diff --git a/src/deviceimagewidget.cpp b/src/deviceimagewidget.cpp
new file mode 100644
index 0000000..3de8fc4
--- /dev/null
+++ b/src/deviceimagewidget.cpp
@@ -0,0 +1,297 @@
+#include "deviceimagewidget.h"
+#include
+#include
+#include
+#include
+#include
+#include
+
+DeviceImageWidget::DeviceImageWidget(iDescriptorDevice *device, QWidget *parent)
+ : QWidget(parent), m_device(device)
+{
+ QVBoxLayout *layout = new QVBoxLayout(this);
+ layout->setContentsMargins(0, 0, 0, 0);
+
+ m_imageLabel = new ResponsiveQLabel(this);
+ m_imageLabel->setMinimumWidth(200);
+ m_imageLabel->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
+ m_imageLabel->setStyleSheet("background: transparent; border: none;");
+
+ layout->addWidget(m_imageLabel);
+
+ setupDeviceImage();
+ m_timeUpdateTimer = new QTimer(this);
+ connect(m_timeUpdateTimer, &QTimer::timeout, this,
+ &DeviceImageWidget::updateTime);
+ m_timeUpdateTimer->start(60000); // Update every minute
+
+ updateTime();
+}
+
+DeviceImageWidget::~DeviceImageWidget()
+{
+ if (m_timeUpdateTimer) {
+ m_timeUpdateTimer->stop();
+ }
+}
+
+void DeviceImageWidget::setupDeviceImage()
+{
+ m_mockupPath = getDeviceMockupPath();
+ m_wallpaperPath = getWallpaperPath();
+
+ qDebug() << "Using mockup:" << m_mockupPath;
+ qDebug() << "Using wallpaper:" << m_wallpaperPath;
+}
+
+QString DeviceImageWidget::getDeviceMockupPath() const
+{
+ QString displayName =
+ QString::fromStdString(m_device->deviceInfo.productType);
+ QString mockupName = getMockupNameFromDisplayName(displayName);
+
+ return QString(":/resources/iphone-mockups/iphone-%1.png").arg(mockupName);
+}
+
+QString DeviceImageWidget::getWallpaperPath() const
+{
+ int iosVersion = getIosVersionFromDevice();
+
+ // Map iOS version to available wallpapers
+ QString wallpaperVersion;
+ if (iosVersion >= 18) {
+ wallpaperVersion = "ios18";
+ } else if (iosVersion >= 17) {
+ wallpaperVersion = "ios17";
+ } else if (iosVersion >= 16) {
+ wallpaperVersion = "ios16";
+ } else if (iosVersion >= 15) {
+ wallpaperVersion = "ios15";
+ } else if (iosVersion >= 14) {
+ wallpaperVersion = "ios14";
+ } else if (iosVersion >= 13) {
+ wallpaperVersion = "ios13";
+ } else if (iosVersion >= 12) {
+ wallpaperVersion = "ios12";
+ } else if (iosVersion >= 11) {
+ wallpaperVersion = "ios11";
+ } else if (iosVersion >= 10) {
+ wallpaperVersion = "ios10";
+ } else if (iosVersion >= 9) {
+ wallpaperVersion = "ios9";
+ } else if (iosVersion >= 8) {
+ wallpaperVersion = "ios8";
+ } else if (iosVersion >= 7) {
+ wallpaperVersion = "ios7";
+ } else if (iosVersion >= 6) {
+ wallpaperVersion = "ios6";
+ } else if (iosVersion >= 5) {
+ wallpaperVersion = "ios5";
+ } else if (iosVersion >= 4) {
+ wallpaperVersion = "ios4";
+ } else {
+ // Unknown version, use ios26 as fallback
+ wallpaperVersion = "ios26";
+ }
+
+ return QString(":/resources/ios-wallpapers/iphone-%1.png")
+ .arg(wallpaperVersion);
+}
+
+QString DeviceImageWidget::getMockupNameFromDisplayName(
+ const QString &displayName) const
+{
+ // Map device names to mockup files
+ if (displayName.contains("iPhone 16", Qt::CaseInsensitive)) {
+ return "16";
+ } else if (displayName.contains("iPhone 15", Qt::CaseInsensitive)) {
+ return "15";
+ } else if (displayName.contains("iPhone X", Qt::CaseInsensitive) ||
+ displayName.contains("iPhone 11", Qt::CaseInsensitive) ||
+ displayName.contains("iPhone 12", Qt::CaseInsensitive) ||
+ displayName.contains("iPhone 13", Qt::CaseInsensitive) ||
+ displayName.contains("iPhone 14", Qt::CaseInsensitive)) {
+ return "x";
+ } else if (displayName.contains("iPhone 6", Qt::CaseInsensitive) ||
+ displayName.contains("iPhone 7", Qt::CaseInsensitive) ||
+ displayName.contains("iPhone 8", Qt::CaseInsensitive)) {
+ return "6";
+ } else if (displayName.contains("iPhone 5", Qt::CaseInsensitive) ||
+ displayName.contains("iPhone SE", Qt::CaseInsensitive)) {
+ return "5";
+ } else if (displayName.contains("iPhone 4", Qt::CaseInsensitive)) {
+ return "4";
+ } else if (displayName.contains("iPhone 3", Qt::CaseInsensitive)) {
+ return "3";
+ } else {
+ // Unknown device, use iPhone X as default
+ return "x";
+ }
+}
+
+int DeviceImageWidget::getIosVersionFromDevice() const
+{
+ unsigned int version = idevice_get_device_version(m_device->device);
+
+ if (version > 0) {
+ int majorVersion = (version >> 16) & 0xFF;
+ return majorVersion;
+ }
+
+ // Fallback: parse from productVersion string
+ QString versionString =
+ QString::fromStdString(m_device->deviceInfo.productVersion);
+ QStringList parts = versionString.split('.');
+ if (!parts.isEmpty()) {
+ bool ok;
+ int majorVersion = parts.first().toInt(&ok);
+ if (ok) {
+ return majorVersion;
+ }
+ }
+
+ // If all else fails, return unknown version (will use ios26 wallpaper)
+ return 0;
+}
+
+/*
+ this method is only here to calculate the screen area
+ so that wallpaper perfectly fits to the screen size
+ it's costy so if you want to add a new mock run
+ through this method qDebug the result and add it to createCompositeImage
+ example : screenRect = QRect(152, 79, 195, 296);
+*/
+QRect DeviceImageWidget::findScreenArea(const QPixmap &mockup) const
+{
+ QImage image = mockup.toImage().convertToFormat(QImage::Format_ARGB32);
+ if (image.isNull()) {
+ return QRect();
+ }
+
+ int width = image.width();
+ int height = image.height();
+ int centerX = width / 2;
+ int centerY = height / 2;
+
+ if (qAlpha(image.pixel(centerX, centerY)) != 0) {
+ qWarning() << "Cannot find screen area: center pixel is not "
+ "transparent. Falling back to default.";
+ return QRect(width * 0.1, height * 0.1, width * 0.8, height * 0.8);
+ }
+
+ int left = centerX;
+ int right = centerX;
+ int top = centerY;
+ int bottom = centerY;
+
+ // Scan left from center
+ while (left > 0 && qAlpha(image.pixel(left, centerY)) == 0) {
+ left--;
+ }
+
+ // Scan right from center
+ while (right < width - 1 && qAlpha(image.pixel(right, centerY)) == 0) {
+ right++;
+ }
+
+ // Scan up from center
+ while (top > 0 && qAlpha(image.pixel(centerX, top)) == 0) {
+ top--;
+ }
+
+ // Scan down from center
+ while (bottom < height - 1 && qAlpha(image.pixel(centerX, bottom)) == 0) {
+ bottom++;
+ }
+
+ // Add a small margin to avoid drawing over the bezel anti-aliasing
+ int margin = 2;
+
+ return QRect(left + 1 + margin, top + 1 + margin,
+ right - left - 2 - (margin * 2),
+ bottom - top - 2 - (margin * 2));
+}
+
+QPixmap DeviceImageWidget::createCompositeImage() const
+{
+ QPixmap mockup(m_mockupPath);
+ QPixmap wallpaper(m_wallpaperPath);
+
+ if (mockup.isNull()) {
+ qWarning() << "Failed to load mockup:" << m_mockupPath;
+ return QPixmap(":/resources/iphone.png"); // Fallback
+ }
+
+ if (wallpaper.isNull()) {
+ qWarning() << "Failed to load wallpaper:" << m_wallpaperPath;
+ return mockup; // Return just the mockup
+ }
+
+ // Start with the mockup as the base layer
+ QPixmap composite = mockup.copy();
+ QPainter painter(&composite);
+ painter.setRenderHint(QPainter::Antialiasing);
+ painter.setRenderHint(QPainter::SmoothPixmapTransform);
+
+ // Use pre-calculated screen areas for optimal performance
+ QRect screenRect;
+ QString mockupName = getMockupNameFromDisplayName(
+ QString::fromStdString(m_device->deviceInfo.productType));
+
+ if (mockupName == "3") {
+ screenRect = QRect(152, 79, 195, 296);
+ } else if (mockupName == "4") {
+ screenRect = QRect(421, 188, 366, 534);
+ } else if (mockupName == "5") {
+ screenRect = QRect(34, 113, 290, 523);
+ } else if (mockupName == "6") {
+ screenRect = QRect(75, 355, 1265, 2256);
+ } else if (mockupName == "x") {
+ screenRect = QRect(252, 436, 2375, 4989);
+ } else if (mockupName == "15") {
+ screenRect = QRect(22, 56, 323, 674);
+ } else if (mockupName == "16") {
+ screenRect = QRect(24, 61, 319, 668);
+ } else {
+ // Fallback for unknown devices
+ screenRect = QRect(mockup.width() * 0.12, mockup.height() * 0.08,
+ mockup.width() * 0.76, mockup.height() * 0.84);
+ }
+
+ // Draw wallpaper BEHIND the mockup (into the screen area)
+ QPixmap scaledWallpaper = wallpaper.scaled(
+ screenRect.size(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
+ painter.drawPixmap(screenRect, scaledWallpaper);
+
+ // Draw current time in the center of the screen
+ QString currentTime = QDateTime::currentDateTime().toString("hh:mm");
+
+ // Setup text rendering with better font sizing
+ QFont timeFont;
+ timeFont.setFamily("SF Pro Display, Helvetica, Arial");
+
+ // Scale font size based on screen dimensions
+ int fontSize = screenRect.width() / 5;
+ timeFont.setPointSize(fontSize);
+ timeFont.setWeight(QFont::Light);
+
+ painter.setFont(timeFont);
+
+ // Draw text shadow for better readability
+ painter.setPen(QColor(0, 0, 0, 150));
+ painter.drawText(screenRect.adjusted(2, 2, 2, 2), Qt::AlignCenter,
+ currentTime);
+
+ // Draw main text - perfectly centered in the screen area
+ painter.setPen(QColor(255, 255, 255, 255));
+ painter.drawText(screenRect, Qt::AlignCenter, currentTime);
+
+ painter.end();
+ return composite;
+}
+
+void DeviceImageWidget::updateTime()
+{
+ QPixmap composite = createCompositeImage();
+ m_imageLabel->setPixmap(composite);
+}
\ No newline at end of file
diff --git a/src/deviceimagewidget.h b/src/deviceimagewidget.h
new file mode 100644
index 0000000..a1bc10b
--- /dev/null
+++ b/src/deviceimagewidget.h
@@ -0,0 +1,38 @@
+#ifndef DEVICEIMAGEWIDGET_H
+#define DEVICEIMAGEWIDGET_H
+
+#include "iDescriptor.h"
+#include "responsiveqlabel.h"
+#include
+#include
+
+class DeviceImageWidget : public QWidget
+{
+ Q_OBJECT
+
+public:
+ explicit DeviceImageWidget(iDescriptorDevice *device,
+ QWidget *parent = nullptr);
+ ~DeviceImageWidget();
+
+private slots:
+ void updateTime();
+
+private:
+ void setupDeviceImage();
+ QString getDeviceMockupPath() const;
+ QString getWallpaperPath() const;
+ QString getMockupNameFromDisplayName(const QString &displayName) const;
+ int getIosVersionFromDevice() const;
+ QPixmap createCompositeImage() const;
+ QRect findScreenArea(const QPixmap &mockup) const;
+
+ iDescriptorDevice *m_device;
+ ResponsiveQLabel *m_imageLabel;
+ QTimer *m_timeUpdateTimer;
+
+ QString m_mockupPath;
+ QString m_wallpaperPath;
+};
+
+#endif // DEVICEIMAGEWIDGET_H
\ No newline at end of file
diff --git a/src/deviceinfowidget.cpp b/src/deviceinfowidget.cpp
index 7d3dec0..731724e 100644
--- a/src/deviceinfowidget.cpp
+++ b/src/deviceinfowidget.cpp
@@ -35,16 +35,13 @@ DeviceInfoWidget::DeviceInfoWidget(iDescriptorDevice *device, QWidget *parent)
// Left side container for image and actions
QWidget *leftContainer = new QWidget();
+ // leftContainer->setStyleSheet("margin-left: 100px");
QVBoxLayout *leftLayout = new QVBoxLayout(leftContainer);
leftLayout->setContentsMargins(0, 0, 0, 0);
leftLayout->setSpacing(1);
- // Create responsive image label
- m_deviceImageLabel = new ResponsiveQLabel(this);
- m_deviceImageLabel->setPixmap(QPixmap(":/resources/iphone.png"));
- m_deviceImageLabel->setMinimumWidth(200);
- m_deviceImageLabel->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
- m_deviceImageLabel->setStyleSheet("background: transparent; border: none;");
+ // Create responsive device image widget
+ m_deviceImageWidget = new DeviceImageWidget(device, this);
// Actions group box
QWidget *actionsWidget = new QWidget();
@@ -80,7 +77,7 @@ DeviceInfoWidget::DeviceInfoWidget(iDescriptorDevice *device, QWidget *parent)
actionsLayout->addWidget(recoveryBtn);
leftLayout->addStretch();
- leftLayout->addWidget(m_deviceImageLabel);
+ leftLayout->addWidget(m_deviceImageWidget);
leftLayout->addWidget(actionsWidget, 0, Qt::AlignCenter);
leftLayout->addStretch();
@@ -329,29 +326,6 @@ void DeviceInfoWidget::onBatteryMoreClicked()
msgBox.exec();
}
-QPixmap DeviceInfoWidget::getDeviceIcon(const std::string &productType)
-{
- // Create a simple colored icon based on device type
- QPixmap icon(16, 16);
- icon.fill(Qt::transparent);
-
- QPainter painter(&icon);
- painter.setRenderHint(QPainter::Antialiasing);
-
- if (productType.find("iPhone") != std::string::npos) {
- painter.setBrush(QColor(0, 122, 255)); // iOS blue
- painter.drawEllipse(2, 2, 12, 12);
- } else if (productType.find("iPad") != std::string::npos) {
- painter.setBrush(QColor(255, 149, 0)); // Orange
- painter.drawRect(2, 2, 12, 12);
- } else {
- painter.setBrush(QColor(128, 128, 128)); // Gray for unknown
- painter.drawEllipse(2, 2, 12, 12);
- }
-
- return icon;
-}
-
void DeviceInfoWidget::updateBatteryInfo()
{
qDebug() << "Updating battery info...";
diff --git a/src/deviceinfowidget.h b/src/deviceinfowidget.h
index 2ef0538..5ab83df 100644
--- a/src/deviceinfowidget.h
+++ b/src/deviceinfowidget.h
@@ -1,8 +1,8 @@
#ifndef DEVICEINFOWIDGET_H
#define DEVICEINFOWIDGET_H
#include "batterywidget.h"
+#include "deviceimagewidget.h"
#include "iDescriptor.h"
-#include "responsiveqlabel.h"
#include
#include
#include
@@ -18,7 +18,6 @@ private slots:
void onBatteryMoreClicked();
private:
- QPixmap getDeviceIcon(const std::string &productType);
iDescriptorDevice *m_device;
QTimer *m_updateTimer;
void updateBatteryInfo();
@@ -28,7 +27,7 @@ private:
BatteryWidget *m_batteryWidget;
QLabel *m_lightningIconLabel;
- ResponsiveQLabel *m_deviceImageLabel = nullptr;
+ DeviceImageWidget *m_deviceImageWidget;
};
#endif // DEVICEINFOWIDGET_H
diff --git a/src/toolboxwidget.h b/src/toolboxwidget.h
index 72618f4..5bf98f5 100644
--- a/src/toolboxwidget.h
+++ b/src/toolboxwidget.h
@@ -22,8 +22,6 @@ public:
static void shutdownDevice(iDescriptorDevice *device);
static void _enterRecoveryMode(iDescriptorDevice *device);
private slots:
- void onDeviceAdded();
- void onDeviceRemoved();
void onDeviceSelectionChanged();
void onToolboxClicked(iDescriptorTool tool);