diff --git a/CMakeLists.txt b/CMakeLists.txt index a473410..43e4bc1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -22,17 +22,18 @@ if(WIN32) set(PKG_CONFIG_EXECUTABLE "C:/msys64/mingw64/bin/pkg-config.exe") list(APPEND CMAKE_PREFIX_PATH "C:/lxqt") set(CUSTOM_LIB_PATH "C:/msys64/mingw64/lib") - set(CUSTOM_BIN_PATH "C:/msys64/mingw64/bin") set(CUSTOM_INCLUDE_PATH "C:/msys64/mingw64/include") set(CUSTOM_PKGCONFIG_PATH "C:/msys64/mingw64/lib/pkgconfig") - # Use Windows path separator for environment variables set(ENV{PKG_CONFIG_PATH} "${CUSTOM_PKGCONFIG_PATH};$ENV{PKG_CONFIG_PATH}") -else() +elseif(APPLE) set(CUSTOM_LIB_PATH "/usr/local/lib") set(CUSTOM_INCLUDE_PATH "/usr/local/include") set(CUSTOM_PKGCONFIG_PATH "/usr/local/lib/pkgconfig") - # Use Unix path separator for environment variables set(ENV{PKG_CONFIG_PATH} "${CUSTOM_PKGCONFIG_PATH}:$ENV{PKG_CONFIG_PATH}") +else () + set(CUSTOM_LIB_PATH "/usr/local/lib") + set(CUSTOM_PKGCONFIG_PATH "/usr/local/lib/pkgconfig") + set(ENV{PKG_CONFIG_PATH} "$ENV{PKG_CONFIG_PATH}:${CUSTOM_PKGCONFIG_PATH}") endif() include_directories(${CUSTOM_INCLUDE_PATH}) @@ -80,24 +81,34 @@ if(WIN32) message(STATUS "Found Qt bin directory: ${QT_BIN_PATH}") endif() +# Define library search behavior based on platform +if(LINUX) + # On Linux (AUR builds), let CMake search default system paths first. + # The custom path /usr/local/lib will be checked if it's in the default search paths. + set(CUSTOM_FIND_LIB_ARGS "") +else() + # On other platforms, only search the custom path for our specific libraries. + set(CUSTOM_FIND_LIB_ARGS + PATHS ${CUSTOM_LIB_PATH} + NO_DEFAULT_PATH + ) +endif() + find_library(IMOBILEDEVICE_LIBRARY NAMES imobiledevice-1.0 - PATHS ${CUSTOM_LIB_PATH} - NO_DEFAULT_PATH + ${CUSTOM_FIND_LIB_ARGS} REQUIRED ) find_library(IMOBILEDEVICE_GLUE_LIBRARY NAMES imobiledevice-glue-1.0 - PATHS ${CUSTOM_LIB_PATH} - NO_DEFAULT_PATH + ${CUSTOM_FIND_LIB_ARGS} REQUIRED ) find_library(TATSU_LIBRARY NAMES tatsu - PATHS ${CUSTOM_LIB_PATH} - NO_DEFAULT_PATH + ${CUSTOM_FIND_LIB_ARGS} REQUIRED ) @@ -120,8 +131,7 @@ endif() find_library(USBMUXD_LIBRARY NAMES usbmuxd-2.0 - PATHS ${CUSTOM_LIB_PATH} - NO_DEFAULT_PATH + ${CUSTOM_FIND_LIB_ARGS} REQUIRED ) @@ -130,17 +140,8 @@ if(WIN32) find_library(SSL_LIBRARY NAMES ssl PATHS C:/msys64/mingw64/lib REQUIRED) find_library(CRYPTO_LIBRARY NAMES crypto PATHS C:/msys64/mingw64/lib REQUIRED) else() - find_library(SSL_LIBRARY - NAMES ssl - PATHS /usr/local/lib /usr/lib /usr/lib/x86_64-linux-gnu - REQUIRED - ) - - find_library(CRYPTO_LIBRARY - NAMES crypto - PATHS /usr/local/lib /usr/lib /usr/lib/x86_64-linux-gnu - REQUIRED - ) + find_library(SSL_LIBRARY NAMES ssl REQUIRED) + find_library(CRYPTO_LIBRARY NAMES crypto REQUIRED) endif() # Add libssh for SSH connections @@ -322,10 +323,29 @@ set_target_properties(iDescriptor PROPERTIES MACOSX_BUNDLE TRUE WIN32_EXECUTABLE TRUE # Control library search order - system libs first, then /usr/local/lib - INSTALL_RPATH "/usr/local/lib:/usr/lib/x86_64-linux-gnu:/usr/lib:$ORIGIN" - # INSTALL_RPATH "/usr/local/lib:/usr/lib/" + INSTALL_RPATH "/usr/lib/x86_64-linux-gnu:/usr/lib:/usr/local/lib:$ORIGIN" BUILD_WITH_INSTALL_RPATH TRUE ) +if (UNIX AND NOT APPLE) +# Add install rules for the project +include(GNUInstallDirs) + +# Install the main executable +install(TARGETS iDescriptor + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} +) + +# Install the .desktop file +install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/iDescriptor.desktop + DESTINATION ${CMAKE_INSTALL_DATADIR}/applications +) + +# Install the application icon +install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/resources/icons/app-icon/icon.png + RENAME iDescriptor.png + DESTINATION ${CMAKE_INSTALL_DATADIR}/icons/hicolor/256x256/apps +) +endif() include(GNUInstallDirs) diff --git a/resources.qrc b/resources.qrc index 21645c9..5d6e357 100644 --- a/resources.qrc +++ b/resources.qrc @@ -31,6 +31,9 @@ resources/icons/MaterialSymbolsAndroidWifi3BarPlus.png resources/icons/IconParkTwotoneMoreTwo.png resources/icons/BxBxsTerminal.png + resources/icons/ClarityEyeHideLine.png + resources/icons/ClarityEyeLine.png + resources/icons/MaterialSymbolsLightImageOutlineSharp.png qml/MapView.qml resources/iphone.png resources/ios-wallpapers/iphone-ios4.png diff --git a/resources/icons/ClarityEyeHideLine.png b/resources/icons/ClarityEyeHideLine.png new file mode 100644 index 0000000..f3b8280 Binary files /dev/null and b/resources/icons/ClarityEyeHideLine.png differ diff --git a/resources/icons/ClarityEyeLine.png b/resources/icons/ClarityEyeLine.png new file mode 100644 index 0000000..a60e450 Binary files /dev/null and b/resources/icons/ClarityEyeLine.png differ diff --git a/resources/icons/MaterialSymbolsLightImageOutlineSharp.png b/resources/icons/MaterialSymbolsLightImageOutlineSharp.png new file mode 100644 index 0000000..8efacb8 Binary files /dev/null and b/resources/icons/MaterialSymbolsLightImageOutlineSharp.png differ diff --git a/src/core/services/init_device.cpp b/src/core/services/init_device.cpp index 3076d06..7bdc40f 100644 --- a/src/core/services/init_device.cpp +++ b/src/core/services/init_device.cpp @@ -104,7 +104,7 @@ void parseOldDevice(PlistNavigator &ioreg, DeviceInfo &d) int healthPercent = (designCapacity != 0) ? (maxCapacity * 100) / designCapacity : 0; healthPercent = std::min(healthPercent, 100); - d.batteryInfo.health = QString::number(healthPercent) + "%"; + d.batteryInfo.health = QString::number(qBound(0, healthPercent, 100)) + "%"; d.batteryInfo.cycleCount = cycleCount; d.batteryInfo.serialNumber = !batterySerialNumber.empty() ? batterySerialNumber @@ -322,7 +322,9 @@ DeviceInfo fullDeviceInfo(const pugi::xml_document &doc, // seems to be to the most accurate way to get health d.batteryInfo.health = - QString::number((maxCapacity * 100) / designCapacity) + "%"; + QString::number( + qBound(0, (maxCapacity * 100) / designCapacity, 100)) + + "%"; d.batteryInfo.cycleCount = cycleCount; d.batteryInfo.serialNumber = !batterySerialNumber.empty() ? batterySerialNumber diff --git a/src/deviceinfowidget.cpp b/src/deviceinfowidget.cpp index 0e6f37f..243cb3e 100644 --- a/src/deviceinfowidget.cpp +++ b/src/deviceinfowidget.cpp @@ -24,6 +24,7 @@ #include "iDescriptor-ui.h" #include "iDescriptor.h" #include "infolabel.h" +#include "privateinfolabel.h" #include "toolboxwidget.h" #include #include @@ -283,6 +284,24 @@ DeviceInfoWidget::DeviceInfoWidget(iDescriptorDevice *device, QWidget *parent) createValueLabel(QString::fromStdString( device->deviceInfo.productionDevice ? "Yes" : "No"))}); + // Serial Number with privacy + if (!device->deviceInfo.serialNumber.empty()) { + infoItems.append( + {"Serial Number:", + new PrivateInfoLabel( + QString::fromStdString(device->deviceInfo.serialNumber), + this)}); + } + + // IMEI with privacy (Mobile Equipment Identifier) + if (!device->deviceInfo.mobileEquipmentIdentifier.empty()) { + infoItems.append( + {"IMEI:", new PrivateInfoLabel( + QString::fromStdString( + device->deviceInfo.mobileEquipmentIdentifier), + this)}); + } + // Distribute items into the grid int numRows = (infoItems.size() + 1) / 2; for (int i = 0; i < numRows; ++i) { diff --git a/src/infolabel.cpp b/src/infolabel.cpp index 76f72bb..4c604b2 100644 --- a/src/infolabel.cpp +++ b/src/infolabel.cpp @@ -75,3 +75,5 @@ void InfoLabel::restoreOriginalText() setStyleSheet("QLabel:hover { background-color: rgba(255, 255, 255, 0.1); " "border-radius: 2px; }"); } + +void InfoLabel::setOriginalText(const QString &text) { m_originalText = text; } diff --git a/src/infolabel.h b/src/infolabel.h index 01bc7fe..6a6d723 100644 --- a/src/infolabel.h +++ b/src/infolabel.h @@ -31,6 +31,9 @@ public: explicit InfoLabel(const QString &text = QString(), QWidget *parent = nullptr); + // Allow updating the original text (useful for PrivateInfoLabel) + void setOriginalText(const QString &text); + protected: void mousePressEvent(QMouseEvent *event) override; void enterEvent(QEnterEvent *event); diff --git a/src/privateinfolabel.cpp b/src/privateinfolabel.cpp new file mode 100644 index 0000000..6c7c9bc --- /dev/null +++ b/src/privateinfolabel.cpp @@ -0,0 +1,68 @@ +/* + * iDescriptor: A free and open-source idevice management tool. + * + * Copyright (C) 2025 Uncore + * + * 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 . + */ + +#include "privateinfolabel.h" + +PrivateInfoLabel::PrivateInfoLabel(const QString &fullText, QWidget *parent) + : QWidget(parent), m_fullText(fullText), m_isVisible(false) +{ + m_maskedText = getMaskedText(fullText); + + QHBoxLayout *layout = new QHBoxLayout(this); + layout->setContentsMargins(0, 0, 0, 0); + layout->setSpacing(5); + + m_textLabel = new InfoLabel(m_maskedText, this); + layout->addWidget(m_textLabel); + + m_toggleButton = new ZIconWidget( + QIcon(":/resources/icons/ClarityEyeHideLine.png"), "Show", this); + m_toggleButton->setIconSize(QSize(20, 20)); + connect(m_toggleButton, &ZIconWidget::clicked, this, + &PrivateInfoLabel::toggleVisibility); + layout->addWidget(m_toggleButton); + + layout->addStretch(); +} + +QString PrivateInfoLabel::getMaskedText(const QString &text) +{ + if (text.length() <= 4) { + return QString("*").repeated(text.length()); + } + // Show first 4 characters, hide the rest + return text.left(4) + QString("*").repeated(text.length() - 4); +} + +void PrivateInfoLabel::toggleVisibility() +{ + m_isVisible = !m_isVisible; + if (m_isVisible) { + m_textLabel->setText(m_fullText); + m_textLabel->setOriginalText(m_fullText); + m_toggleButton->setIcon(QIcon(":/resources/icons/ClarityEyeLine.png")); + m_toggleButton->setToolTip("Hide"); + } else { + m_textLabel->setText(m_maskedText); + m_textLabel->setOriginalText(m_fullText); + m_toggleButton->setIcon( + QIcon(":/resources/icons/ClarityEyeHideLine.png")); + m_toggleButton->setToolTip("Show"); + } +} diff --git a/src/privateinfolabel.h b/src/privateinfolabel.h new file mode 100644 index 0000000..3ef5f92 --- /dev/null +++ b/src/privateinfolabel.h @@ -0,0 +1,49 @@ +/* + * iDescriptor: A free and open-source idevice management tool. + * + * Copyright (C) 2025 Uncore + * + * 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 . + */ + +#ifndef PRIVATEINFOLABEL_H +#define PRIVATEINFOLABEL_H + +#include "iDescriptor-ui.h" +#include "infolabel.h" +#include +#include + +class PrivateInfoLabel : public QWidget +{ + Q_OBJECT + +public: + explicit PrivateInfoLabel(const QString &fullText, + QWidget *parent = nullptr); + +private slots: + void toggleVisibility(); + +private: + QString m_fullText; + QString m_maskedText; + bool m_isVisible; + InfoLabel *m_textLabel; + ZIconWidget *m_toggleButton; + + QString getMaskedText(const QString &text); +}; + +#endif // PRIVATEINFOLABEL_H