refactor(ui): add WinUI stylesheet for Windows

- Introduced WinToolWidget for custom window management on Windows.
- Implemented backdrop type settings for Windows in SettingsManager.
- Enhanced SettingsWidget to allow selection of backdrop type.
- Improved status balloon and toolbox widget styles for Windows.
- Refined tab widget animations and styles for better visual feedback.
- Fixed issues with loading and error widgets in ZLoadingWidget.
- Updated welcome widget to support custom hyperlink colors.
- General code cleanup and style adjustments across multiple files.
This commit is contained in:
uncor3
2026-02-22 11:59:57 +03:00
parent bc3998cefb
commit 43d804991e
121 changed files with 3745 additions and 479 deletions
+38 -84
View File
@@ -6,7 +6,6 @@ if(WIN32)
endif()
# Feature options
option(ENABLE_RECOVERY_DEVICE_SUPPORT "Enable recovery device support (requires libirecovery)" ON)
set(PACKAGE_MANAGER_HINT "" CACHE STRING "Name of package manager(s) used to manage this build (e.g. paru, yay, pamac)")
option(PACKAGE_MANAGER_MANAGED "Build as package manager managed version (auto updates will be handled by the package manager)" OFF)
option(DEPLOY "Deploy the application (WIN32 only)" ON)
@@ -26,39 +25,27 @@ if (APPLE)
endif()
# Platform-specific paths for libraries built from source
# if(WIN32)
# include_directories("C:/msys64/mingw64/include")
# link_directories("C:/msys64/mingw64/lib")
# 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_INCLUDE_PATH "C:/msys64/mingw64/include")
# set(CUSTOM_PKGCONFIG_PATH "C:/msys64/mingw64/lib/pkgconfig")
# set(ENV{PKG_CONFIG_PATH} "${CUSTOM_PKGCONFIG_PATH};$ENV{PKG_CONFIG_PATH}")
# elseif(APPLE)
# set(CUSTOM_LIB_PATH "/usr/local/lib")
# # Remove the problematic include path that's causing conflicts
# # set(CUSTOM_INCLUDE_PATH "/usr/local/include")
# set(CUSTOM_PKGCONFIG_PATH "/usr/local/lib/pkgconfig")
# 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()
if(WIN32)
include_directories("C:/msys64/mingw64/include")
link_directories("C:/msys64/mingw64/lib")
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_INCLUDE_PATH "C:/msys64/mingw64/include")
set(CUSTOM_PKGCONFIG_PATH "C:/msys64/mingw64/lib/pkgconfig")
set(ENV{PKG_CONFIG_PATH} "${CUSTOM_PKGCONFIG_PATH};$ENV{PKG_CONFIG_PATH}")
elseif(APPLE)
set(CUSTOM_LIB_PATH "/usr/local/lib")
# Remove the problematic include path that's causing conflicts
# set(CUSTOM_INCLUDE_PATH "/usr/local/include")
set(CUSTOM_PKGCONFIG_PATH "/usr/local/lib/pkgconfig")
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()
# foreach(_ IN LISTS CMAKE_PREFIX_PATH)
# list(APPEND _qt_pkg_dirs
# "${_}/lib/pkgconfig"
# "${_}/lib64/pkgconfig"
# "${_}/lib64/qt/pkgconfig"
# "${_}/lib/qt/pkgconfig"
# )
# 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(SQLite3 REQUIRED)
@@ -110,6 +97,14 @@ add_custom_command(
COMMENT "Building idevice-rs FFI libraryy"
VERBATIM
)
elseif(WIN32)
add_custom_command(
OUTPUT ${IDEVICE_RS_LIB_PATH}
COMMAND ${CARGO_EXECUTABLE} +stable-x86_64-pc-windows-gnu build --manifest-path ${IDEVICE_RS_SOURCE_DIR}/Cargo.toml
WORKING_DIRECTORY ${IDEVICE_RS_SOURCE_DIR}
COMMENT "Building idevice-rs FFI libraryy"
VERBATIM
)
else()
add_custom_command(
OUTPUT ${IDEVICE_RS_LIB_PATH}
@@ -150,6 +145,11 @@ file(GLOB PLIST_CPP_SOURCES
add_library(idevice_cpp STATIC ${IDEVICE_CPP_SOURCES} ${PLIST_CPP_SOURCES})
add_dependencies(idevice_cpp idevice_rs_build)
if(WIN32)
# Define LIBPLIST_STATIC to prevent functions from being marked as DLL imports
target_compile_definitions(idevice_cpp PUBLIC LIBPLIST_STATIC)
endif()
target_include_directories(idevice_cpp PUBLIC
${IDEVICE_CPP_INCLUDE_DIR}
${PLIST_CPP_INCLUDE_DIR}
@@ -201,21 +201,6 @@ pkg_check_modules(AVCODEC REQUIRED IMPORTED_TARGET libavcodec)
pkg_check_modules(AVUTIL REQUIRED IMPORTED_TARGET libavutil)
pkg_check_modules(SWSCALE REQUIRED IMPORTED_TARGET libswscale)
# if(ENABLE_RECOVERY_DEVICE_SUPPORT)
# find_library(IRECOVERY_LIBRARY
# NAMES irecovery-1.0
# PATHS ${CUSTOM_LIB_PATH}
# NO_DEFAULT_PATH
# )
# if(IRECOVERY_LIBRARY)
# message(STATUS "Building with recovery device support enabled")
# else()
# message(WARNING "libirecovery not found. Recovery device support will be disabled. This is to be expected if you are installing from Arch AUR.")
# set(ENABLE_RECOVERY_DEVICE_SUPPORT OFF)
# endif()
# else()
# message(STATUS "Recovery device support disabled")
# endif()
# Add libssh for SSH connections
pkg_check_modules(SSH REQUIRED IMPORTED_TARGET libssh)
@@ -252,8 +237,10 @@ elseif (WIN32)
src/core/services/dnssd/dnssd_service.h
)
file(GLOB WINDOWS_PLATFORM_SOURCES src/platform/windows/*.cpp src/platform/windows/*.h)
file(GLOB WINDOWS_PLATFORM_SOURCES src/platform/windows/*.cpp src/platform/windows/*.h src/platform/windows/widgets/*.cpp src/platform/windows/widgets/*.h)
list(APPEND PROJECT_SOURCES ${WINDOWS_PLATFORM_SOURCES})
list(APPEND PROJECT_SOURCES
resources.win.qrc)
else()
list(APPEND PROJECT_SOURCES
src/core/services/avahi/avahi_service.cpp
@@ -261,17 +248,6 @@ else()
)
endif()
if (NOT ENABLE_RECOVERY_DEVICE_SUPPORT)
list(REMOVE_ITEM PROJECT_SOURCES
${CMAKE_CURRENT_SOURCE_DIR}/src/recoverydeviceinfowidget.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/recoverydeviceinfowidget.h
${CMAKE_CURRENT_SOURCE_DIR}/src/core/helpers/parse_recovery_mode.cpp
src/recoverydeviceinfowidget.cpp
src/recoverydeviceinfowidget.h
src/core/helpers/parse_recovery_mode.cpp
)
endif()
add_subdirectory(lib/uxplay)
add_subdirectory(lib/ipatool-go)
add_subdirectory(lib/zupdater)
@@ -323,14 +299,8 @@ target_link_libraries(iDescriptor PRIVATE
Qt6::Positioning
Qt6::QuickWidgets
Qt6::QuickControls2
# ${IMOBILEDEVICE_LIBRARY}
# ${IMOBILEDEVICE_GLUE_LIBRARY}
# ${TATSU_LIBRARY}
# ${SSL_LIBRARY}
# ${CRYPTO_LIBRARY}
PkgConfig::SSH
${SSH_LIBRARY}
# ${USBMUXD_LIBRARY}
PkgConfig::PUGIXML
# PkgConfig::USB
# PkgConfig::PLIST
@@ -350,11 +320,6 @@ target_link_libraries(iDescriptor PRIVATE
SQLite::SQLite3
)
# # Conditionally link libirecovery
# if(ENABLE_RECOVERY_DEVICE_SUPPORT)
# target_link_libraries(iDescriptor PRIVATE ${IRECOVERY_LIBRARY})
# endif()
target_include_directories(iDescriptor PRIVATE
# Put idevice-rs includes FIRST
${IDEVICE_CPP_INCLUDE_DIR}
@@ -376,7 +341,7 @@ if(APPLE)
${CORE_SERVICES_FRAMEWORK})
message(STATUS "Using macOS Bonjour framework for network service discovery")
elseif (WIN32)
target_link_libraries(iDescriptor PRIVATE PkgConfig::LIBARCHIVE)
target_link_libraries(iDescriptor PRIVATE PkgConfig::LIBARCHIVE dwmapi ntdll)
find_path(DNSSD_INCLUDE_DIR dns_sd.h HINTS ${BONJOUR_SDK}/Include )
# $<$<COMPILE_LANGUAGE:CXX> fixes winres compiler errors
target_include_directories(iDescriptor PRIVATE
@@ -406,11 +371,6 @@ target_compile_definitions(iDescriptor PRIVATE
SOURCE_DIR="${CMAKE_SOURCE_DIR}"
)
# Add compile definition for recovery device support
if(ENABLE_RECOVERY_DEVICE_SUPPORT)
target_compile_definitions(iDescriptor PRIVATE ENABLE_RECOVERY_DEVICE_SUPPORT)
endif()
if(PACKAGE_MANAGER_MANAGED)
target_compile_definitions(iDescriptor PRIVATE PACKAGE_MANAGER_MANAGED)
message(STATUS "Building as package manager managed version, updates will be handled by the package manager")
@@ -435,14 +395,8 @@ set_target_properties(iDescriptor PROPERTIES
WIN32_EXECUTABLE TRUE
BUILD_WITH_INSTALL_RPATH TRUE
)
if (UNIX AND NOT APPLE)
# Required on Linux to find libirecovery-1.0.so.5 at runtime
if (ENABLE_RECOVERY_DEVICE_SUPPORT)
set_target_properties(iDescriptor PROPERTIES
# Control library search order - system libs first, then /usr/local/lib
INSTALL_RPATH "/usr/lib/x86_64-linux-gnu:/usr/lib:/usr/local/lib:$ORIGIN"
)
endif()
# Add install rules for the project
# include(GNUInstallDirs)
+82
View File
@@ -0,0 +1,82 @@
<RCC>
<qresource prefix="/">
<file>resources/win.dark.qcss</file>
<file>resources/win.light.qcss</file>
</qresource>
<qresource prefix="/">
<file>resources/win/dark/CheckBox.png</file>
<file>resources/win/dark/CheckBoxPressed.png</file>
<file>resources/win/dark/ComboBox.png</file>
<file>resources/win/dark/ComboBoxDisabled.png</file>
<file>resources/win/dark/NextMonth.png</file>
<file>resources/win/dark/NextMonthDisabled.png</file>
<file>resources/win/dark/PrevMonth.png</file>
<file>resources/win/dark/PrevMonthDisabled.png</file>
<file>resources/win/dark/RadioButton.png</file>
<file>resources/win/dark/RadioButtonHover.png</file>
<file>resources/win/dark/RadioButtonPressed.png</file>
<file>resources/win/dark/ScrollBottom.png</file>
<file>resources/win/dark/ScrollBottomHover.png</file>
<file>resources/win/dark/ScrollBottomPressed.png</file>
<file>resources/win/dark/ScrollLeft.png</file>
<file>resources/win/dark/ScrollLeftHover.png</file>
<file>resources/win/dark/ScrollLeftPressed.png</file>
<file>resources/win/dark/ScrollRight.png</file>
<file>resources/win/dark/ScrollRightHover.png</file>
<file>resources/win/dark/ScrollRightPressed.png</file>
<file>resources/win/dark/ScrollTop.png</file>
<file>resources/win/dark/ScrollTopHover.png</file>
<file>resources/win/dark/ScrollTopPressed.png</file>
<file>resources/win/dark/SpinBoxDown.png</file>
<file>resources/win/dark/SpinBoxDownDisabled.png</file>
<file>resources/win/dark/SpinBoxUp.png</file>
<file>resources/win/dark/SpinBoxUpDisabled.png</file>
<file>resources/win/dark/ToggleSwitchDisabled.png</file>
<file>resources/win/dark/ToggleSwitchOff.png</file>
<file>resources/win/dark/ToggleSwitchOffHover.png</file>
<file>resources/win/dark/ToggleSwitchOffPressed.png</file>
<file>resources/win/dark/ToggleSwitchOn.png</file>
<file>resources/win/dark/ToggleSwitchOnHover.png</file>
<file>resources/win/dark/ToggleSwitchOnPressed.png</file>
<file>resources/win/dark/TreeViewClose.png</file>
<file>resources/win/dark/TreeViewOpen.png</file>
</qresource>
<qresource prefix="/">
<file>resources/win/light/CheckBox.png</file>
<file>resources/win/light/CheckBoxPressed.png</file>
<file>resources/win/light/ComboBox.png</file>
<file>resources/win/light/ComboBoxDisabled.png</file>
<file>resources/win/light/NextMonth.png</file>
<file>resources/win/light/NextMonthDisabled.png</file>
<file>resources/win/light/PrevMonth.png</file>
<file>resources/win/light/PrevMonthDisabled.png</file>
<file>resources/win/light/RadioButton.png</file>
<file>resources/win/light/RadioButtonHover.png</file>
<file>resources/win/light/RadioButtonPressed.png</file>
<file>resources/win/light/ScrollBottom.png</file>
<file>resources/win/light/ScrollBottomHover.png</file>
<file>resources/win/light/ScrollBottomPressed.png</file>
<file>resources/win/light/ScrollLeft.png</file>
<file>resources/win/light/ScrollLeftHover.png</file>
<file>resources/win/light/ScrollLeftPressed.png</file>
<file>resources/win/light/ScrollRight.png</file>
<file>resources/win/light/ScrollRightHover.png</file>
<file>resources/win/light/ScrollRightPressed.png</file>
<file>resources/win/light/ScrollTop.png</file>
<file>resources/win/light/ScrollTopHover.png</file>
<file>resources/win/light/ScrollTopPressed.png</file>
<file>resources/win/light/SpinBoxDown.png</file>
<file>resources/win/light/SpinBoxDownDisabled.png</file>
<file>resources/win/light/SpinBoxUp.png</file>
<file>resources/win/light/SpinBoxUpDisabled.png</file>
<file>resources/win/light/ToggleSwitchDisabled.png</file>
<file>resources/win/light/ToggleSwitchOff.png</file>
<file>resources/win/light/ToggleSwitchOffHover.png</file>
<file>resources/win/light/ToggleSwitchOffPressed.png</file>
<file>resources/win/light/ToggleSwitchOn.png</file>
<file>resources/win/light/ToggleSwitchOnHover.png</file>
<file>resources/win/light/ToggleSwitchOnPressed.png</file>
<file>resources/win/light/TreeViewClose.png</file>
<file>resources/win/light/TreeViewOpen.png</file>
</qresource>
</RCC>
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
Binary file not shown.

After

Width:  |  Height:  |  Size: 208 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 273 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 226 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 252 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 245 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 266 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 234 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 263 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 254 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 259 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 233 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 247 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 245 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 232 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 226 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 225 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 233 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 241 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 235 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 227 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 238 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 236 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 224 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 404 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 642 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 368 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 625 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 329 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 336 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 354 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 356 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 259 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 283 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 278 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 263 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 275 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 215 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 267 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 220 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 252 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 250 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 245 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 248 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 234 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 267 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 272 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 239 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 253 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 261 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 235 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 244 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 240 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 222 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 252 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 254 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 221 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 244 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 252 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 225 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 436 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 577 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 403 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 567 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 334 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 329 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 344 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 367 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 272 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 287 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 318 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 291 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 304 B

+1 -1
View File
@@ -57,7 +57,7 @@
#include "diagnosedialog.h"
#ifdef WIN32
#include "platform/windows/check_deps.h"
#include "platform/windows/win_common.h"
#endif
#include "toolboxwidget.h"
+14 -6
View File
@@ -87,18 +87,23 @@ void AppsWidget::setupUI()
QWidget *headerWidget = new QWidget();
headerWidget->setFixedHeight(60);
headerWidget->setStyleSheet("border-bottom: 1px solid #363d32;");
headerWidget->setStyleSheet(
"border-bottom: 1px solid #363d32; border-radius: 0px;");
QHBoxLayout *headerLayout = new QHBoxLayout(headerWidget);
headerLayout->setContentsMargins(20, 10, 20, 10);
// Create status label first
m_statusLabel = new QLabel("Not signed in");
m_statusLabel->setStyleSheet("margin-right: 20px;");
m_statusLabel->setStyleSheet("margin-right: 20px; border: none;");
m_loginButton = new QPushButton();
m_searchEdit = new ZLineEdit();
m_searchEdit = new QLineEdit();
#ifndef WIN32
m_searchEdit->setMaximumWidth(350);
#else
m_searchEdit->setMaximumWidth(200);
#endif
// --- Status and Login Button ---
m_manager = AppStoreManager::sharedInstance();
@@ -214,7 +219,7 @@ void AppsWidget::handleInit()
}
/*
FIXME: ipatoolinitialze still uses the secure backends
when if the user rejects it, the moment he/she tries to sign in
even if the user rejects it, the moment he/she tries to sign in
prompt(keychain or secret-service whatever the backend is) will be seen
again
*/
@@ -262,10 +267,12 @@ void AppsWidget::onAppStoreInitialized(const QJsonObject &accountInfo)
}
m_loginButton->setText(m_isLoggedIn ? "Sign Out" : "Sign In");
#ifndef WIN32
m_loginButton->setStyleSheet(
"background-color: #007AFF; color: white; border: none; "
"border-radius: "
"4px; padding: 8px 16px; font-size: 14px;");
#endif
m_searchEdit->setPlaceholderText(m_isLoggedIn ? "Search for apps..."
: "Sign in to search");
}
@@ -638,8 +645,9 @@ void AppsWidget::createAppCard(
ZLabel *installLabel = new ZLabel("Install");
installLabel->setAlignment(Qt::AlignCenter);
installLabel->setStyleSheet(
"font-size: 12px; color: #007AFF; font-weight: "
"bold; background-color: transparent;");
QString("font-size: 12px; color: %1; font-weight: "
"bold; background-color: transparent;")
.arg(COLOR_ACCENT_BLUE.name()));
installLabel->setCursor(Qt::PointingHandCursor);
installLabel->setFixedHeight(30);
+8
View File
@@ -18,8 +18,16 @@
*/
#include "tool.h"
#ifdef WIN32
#include "../platform/windows/widgets/wintoolwidget.h"
#include "../platform/windows/win_common.h"
#endif
#ifdef WIN32
Tool::Tool(QWidget *parent) : WinToolWidget(parent)
#else
Tool::Tool(QWidget *parent) : QWidget(parent)
#endif
{
#ifdef __APPLE__
setupToolFrame(this);
+9
View File
@@ -26,7 +26,16 @@
#include "../platform/macos/macos.h"
#endif
#ifdef WIN32
#include "../platform/windows/widgets/wintoolwidget.h"
#endif
#ifdef WIN32
class Tool : public WinToolWidget
#else
class Tool : public QWidget
#endif
{
public:
explicit Tool(QWidget *parent = nullptr);
+4 -4
View File
@@ -81,7 +81,7 @@ void CableInfoWidget::setupUI()
m_loadingWidget = new ZLoadingWidget(true, this);
m_loadingWidget->setupContentWidget(m_mainLayout);
QVBoxLayout *layout = new QVBoxLayout(this);
QVBoxLayout *layout = new QVBoxLayout(contentWidget());
layout->setContentsMargins(0, 0, 0, 0);
layout->addWidget(m_loadingWidget);
@@ -230,7 +230,7 @@ void CableInfoWidget::updateUI()
if (!m_cableInfo.isConnected) {
m_errorLabel->setText(
QString("%1 does not seem to be connected to any cable.")
.arg(m_device->deviceInfo.productType));
.arg(QString::fromStdString(m_device->deviceInfo.productType)));
m_loadingWidget->showError();
return;
}
@@ -243,13 +243,13 @@ void CableInfoWidget::updateUI()
"absolute guarantee of authenticity.");
if (m_cableInfo.isGenuine) {
// todo: type-c to type-c
statusText = QString("Genuine %1")
statusText = QString("Genuine %1")
.arg(m_cableInfo.isTypeC ? "USB-C to Lightning Cable"
: "Lightning Cable");
statusStyle =
"QLabel { color: #28a745; font-size: 18px; font-weight: bold; }";
} else {
statusText = "⚠️ Third-party Cable";
statusText = "Third-party Cable";
statusStyle =
"QLabel { color: #dc3545; font-size: 18px; font-weight: bold; }";
+2 -1
View File
@@ -126,6 +126,7 @@ void get_device_info_xml(const char *udid, LockdowndClientHandle *client,
if (xml_string) {
infoXml.load_string(xml_string);
free(xml_string);
// FIXME: crashes on Windows
// free(xml_string);
}
}
+9 -3
View File
@@ -26,12 +26,18 @@
#endif
#include "../../heartbeat.h"
#include <QDebug>
#ifdef _WIN32
#include "../../platform/windows/win_common.h"
#else
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sstream>
#include <string.h>
#include <sys/socket.h>
#include <unistd.h>
#endif
#include <sstream>
#include <string.h>
std::string safeGetXML(const char *key, pugi::xml_node dict)
{
@@ -453,7 +459,7 @@ void init_idescriptor_device(const iDescriptor::Uniq &uniq,
heartbeatThread->start();
while (!heartbeatThread->initialCompleted()) {
sleep(1);
// sleep(1);
}
} else {
+17 -11
View File
@@ -25,7 +25,6 @@
#include "iDescriptor.h"
#include "infolabel.h"
#include "privateinfolabel.h"
// #include "toolboxwidget.h"
#include <QApplication>
#include <QDebug>
#include <QGraphicsDropShadowEffect>
@@ -146,13 +145,14 @@ DeviceInfoWidget::DeviceInfoWidget(iDescriptorDevice *device, QWidget *parent)
m_chargingStatusLabel =
new QLabel(device->deviceInfo.batteryInfo.isCharging ? "Charging"
: "Not Charging");
m_chargingStatusLabel->setStyleSheet(
device->deviceInfo.batteryInfo.isCharging
? QString("color: %1;").arg(COLOR_GREEN.name())
: QString("color: %1;")
.arg(qApp->palette().color(QPalette::WindowText).name()));
m_chargingStatusLabel->setObjectName("ChargingStatusLabel");
m_chargingStatusLabel->setStyleSheet(mergeStyles(
m_chargingStatusLabel,
(device->deviceInfo.batteryInfo.isCharging
? QString("QLabel#ChargingStatusLabel { color: %1; }")
.arg(COLOR_GREEN.name())
: QString("QLabel#ChargingStatusLabel { color: %1; }")
.arg(qApp->palette().color(QPalette::WindowText).name()))));
// Create the layout without a parent widget
QHBoxLayout *chargingLayout = new QHBoxLayout();
chargingLayout->setContentsMargins(0, 0, 0, 0);
@@ -314,7 +314,11 @@ DeviceInfoWidget::DeviceInfoWidget(iDescriptorDevice *device, QWidget *parent)
for (int i = 0; i < numRows; ++i) {
// Left column item
QLabel *keyLabelLeft = new QLabel(infoItems[i].first);
#ifndef WIN32
keyLabelLeft->setStyleSheet("font-weight: bold;");
#else
keyLabelLeft->setStyleSheet("font-size: 15px; font-weight: 500;");
#endif
gridLayout->addWidget(keyLabelLeft, i, 0);
gridLayout->addWidget(infoItems[i].second, i, 1);
@@ -322,7 +326,11 @@ DeviceInfoWidget::DeviceInfoWidget(iDescriptorDevice *device, QWidget *parent)
int rightIndex = i + numRows;
if (rightIndex < infoItems.size()) {
QLabel *keyLabelRight = new QLabel(infoItems[rightIndex].first);
#ifndef WIN32
keyLabelRight->setStyleSheet("font-weight: bold;");
#else
keyLabelRight->setStyleSheet("font-size: 15px; font-weight: 500;");
#endif
gridLayout->addWidget(keyLabelRight, i, 2);
gridLayout->addWidget(infoItems[rightIndex].second, i, 3);
}
@@ -348,8 +356,6 @@ DeviceInfoWidget::DeviceInfoWidget(iDescriptorDevice *device, QWidget *parent)
rightSideLayout->addWidget(new DiskUsageWidget(device, this));
rightSideLayout->addStretch();
// // TODO: layout shift cause ?
// // rightSideLayout->setAlignment(Qt::AlignCenter);
mainLayout->addLayout(rightSideLayout);
mainLayout->addStretch();
@@ -420,4 +426,4 @@ void DeviceInfoWidget::updateChargingStatusIcon()
// m_chargingStatusLabel->setStyleSheet("");
// m_lightningIconLabel->hide();
// }
}
}
+76 -52
View File
@@ -39,6 +39,7 @@ DeviceSidebarItem::DeviceSidebarItem(const QString &deviceName,
setFrameStyle(QFrame::StyledPanel);
setLineWidth(1);
updateToggleButton();
setObjectName("DeviceSidebarItem");
}
void DeviceSidebarItem::setupUI()
@@ -59,7 +60,9 @@ void DeviceSidebarItem::setupUI()
QHBoxLayout *nameLayout = new QHBoxLayout();
nameLayout->setContentsMargins(0, 0, 0, 0);
m_deviceLabel = new QLabel(m_deviceName);
#ifndef WIN32
m_deviceLabel->setStyleSheet("QLabel { font-weight: bold; }");
#endif
m_deviceLabel->setWordWrap(true);
nameLayout->addWidget(m_deviceLabel);
if (m_wireless) {
@@ -78,6 +81,9 @@ void DeviceSidebarItem::setupUI()
m_toggleButton->setStyleSheet("QPushButton { "
" text-align: left; "
" padding: 2px 5px; "
#ifdef WIN32
" min-height: 0; "
#endif
" border: none; "
" color: #666; "
" font-size: 11px; "
@@ -121,6 +127,9 @@ void DeviceSidebarItem::setupUI()
QString("QPushButton { "
" background-color: rgba(255, 255, 255, 120); "
" border: 1px solid rgba(255, 255, 255, 200); "
#ifdef WIN32
" min-height: 0; "
#endif
" padding: 4px 8px; "
" text-align: center; "
" border-radius: 6px; "
@@ -159,7 +168,20 @@ void DeviceSidebarItem::setupUI()
setSelected(false);
}
void DeviceSidebarItem::setSelected(bool selected) { m_selected = selected; }
void DeviceSidebarItem::setSelected(bool selected)
{
m_selected = selected;
if (selected) {
setStyleSheet(
"QFrame#DeviceSidebarItem { background-color: rgba(255, "
"255, 255, 45); }");
} else {
setStyleSheet(
"QFrame#DeviceSidebarItem { background-color: rgba(255, "
"255, 255, 16); }");
}
}
void DeviceSidebarItem::setCollapsed(bool collapsed)
{
@@ -452,68 +474,70 @@ void DevicePendingSidebarItem::mousePressEvent(QMouseEvent *event)
}
// FIXME: better move this to a separate file
void DeviceSidebarItem::paintEvent(QPaintEvent *event)
{
Q_UNUSED(event);
// void DeviceSidebarItem::paintEvent(QPaintEvent *event)
// {
// Q_UNUSED(event);
QPainter p(this);
p.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform);
// QPainter p(this);
// p.setRenderHints(QPainter::Antialiasing |
// QPainter::SmoothPixmapTransform);
const qreal dpr = devicePixelRatioF();
const int w = width();
const int h = height();
const int sw = int(w * dpr);
const int sh = int(h * dpr);
// const qreal dpr = devicePixelRatioF();
// const int w = width();
// const int h = height();
// const int sw = int(w * dpr);
// const int sh = int(h * dpr);
constexpr int kCornerRadius = 10;
constexpr int kBlurRadius = 2;
// constexpr int kCornerRadius = 10;
// constexpr int kBlurRadius = 2;
// Cache the blurred background per size
static QPixmap cachedBg;
static QSize cachedSize;
// // Cache the blurred background per size
// static QPixmap cachedBg;
// static QSize cachedSize;
const QSize cacheSize(sw, sh);
if (cachedSize != cacheSize) {
cachedSize = cacheSize;
// const QSize cacheSize(sw, sh);
// if (cachedSize != cacheSize) {
// cachedSize = cacheSize;
QPixmap gradPm(sw, sh);
gradPm.fill(Qt::transparent);
{
QPainter gp(&gradPm);
gp.setRenderHints(QPainter::Antialiasing |
QPainter::SmoothPixmapTransform);
// QPixmap gradPm(sw, sh);
// gradPm.fill(Qt::transparent);
// {
// QPainter gp(&gradPm);
// gp.setRenderHints(QPainter::Antialiasing |
// QPainter::SmoothPixmapTransform);
QLinearGradient grad(0, 0, 1, 1);
grad.setCoordinateMode(QGradient::ObjectMode);
grad.setStops({{0.0, QColor(255, 255, 255, 255)},
{0.35, QColor(255, 255, 255, 125)},
{0.65, QColor(255, 255, 255, 125)},
{1.0, QColor(255, 255, 255, 255)}});
// QLinearGradient grad(0, 0, 1, 1);
// grad.setCoordinateMode(QGradient::ObjectMode);
// grad.setStops({{0.0, QColor(255, 255, 255, 255)},
// {0.35, QColor(255, 255, 255, 125)},
// {0.65, QColor(255, 255, 255, 125)},
// {1.0, QColor(255, 255, 255, 255)}});
gp.fillRect(QRectF(0, 0, sw, sh), grad);
}
// gp.fillRect(QRectF(0, 0, sw, sh), grad);
// }
QPixmap blurred = BackDrop::blurPixmap(gradPm, kBlurRadius);
// QPixmap blurred = BackDrop::blurPixmap(gradPm, kBlurRadius);
QPixmap mask = BackDrop::getColoredPixmap(
QBrush(Qt::white), Qt::white, 1, sw, sh, int(kCornerRadius * dpr));
// QPixmap mask = BackDrop::getColoredPixmap(
// QBrush(Qt::white), Qt::white, 1, sw, sh, int(kCornerRadius *
// dpr));
BackDrop::cutPixmap(blurred, mask, sw, sh);
// BackDrop::cutPixmap(blurred, mask, sw, sh);
blurred.setDevicePixelRatio(dpr);
cachedBg = blurred;
}
// blurred.setDevicePixelRatio(dpr);
// cachedBg = blurred;
// }
QPainterPath clipPath;
QRectF r = rect().adjusted(0.5, 0.5, -0.5, -0.5);
clipPath.addRoundedRect(r, kCornerRadius, kCornerRadius);
p.setClipPath(clipPath);
p.drawPixmap(r.toRect(), cachedBg);
// QPainterPath clipPath;
// QRectF r = rect().adjusted(0.5, 0.5, -0.5, -0.5);
// clipPath.addRoundedRect(r, kCornerRadius, kCornerRadius);
// p.setClipPath(clipPath);
// p.drawPixmap(r.toRect(), cachedBg);
p.setClipping(false);
QColor borderColor = m_selected ? COLOR_BLUE : QColor("#FFFFFF");
QPen pen(borderColor, m_selected ? 2.0 : 1.0);
p.setPen(pen);
p.setBrush(Qt::NoBrush);
p.drawRoundedRect(r, kCornerRadius, kCornerRadius);
}
// p.setClipping(false);
// QColor borderColor = m_selected ? COLOR_BLUE : QColor("#FFFFFF");
// QPen pen(borderColor, m_selected ? 2.0 : 1.0);
// p.setPen(pen);
// p.setBrush(Qt::NoBrush);
// p.drawRoundedRect(r, kCornerRadius, kCornerRadius);
// }
+2 -2
View File
@@ -45,8 +45,8 @@ public:
void setCollapsed(bool collapsed);
bool isCollapsed() const { return m_collapsed; }
protected:
void paintEvent(QPaintEvent *event) override;
// protected:
// void paintEvent(QPaintEvent *event) override;
signals:
void deviceSelected(const std::string &uuid);
void navigationRequested(const std::string &uuid, const QString &section);
+24 -7
View File
@@ -19,10 +19,11 @@
#include "diagnosewidget.h"
#ifdef WIN32
#include "platform/windows/check_deps.h"
#include "platform/windows/win_common.h"
#include <archive.h>
#include <archive_entry.h>
#endif
#include "iDescriptor-ui.h"
#include <QApplication>
#include <QCoreApplication>
#include <QCryptographicHash>
@@ -97,21 +98,37 @@ void DependencyItem::setInstalled(bool installed)
if (installed) {
if (m_name == "Avahi Daemon") {
m_statusLabel->setText("✓ Activated");
m_statusLabel->setText("Activated");
} else {
m_statusLabel->setText("✓ Installed");
m_statusLabel->setText("Installed");
}
m_statusLabel->setStyleSheet("color: green; font-weight: bold;");
#ifndef WIN32
m_statusLabel->setStyleSheet("color: green;");
#else
// FIXME: if we call this multiple times, the styles will keep stacking
// and become a mess, need a better way to handle this
m_statusLabel->setStyleSheet(mergeStyles(
m_statusLabel,
QString("QLabel { color: %1; }").arg(COLOR_GREEN.name())));
#endif
m_installButton->setVisible(false);
} else {
if (m_name == "Avahi Daemon") {
m_statusLabel->setText("Not activated");
m_statusLabel->setText("Not activated");
m_installButton->setText("Enable");
} else {
m_statusLabel->setText("Not Installed");
m_statusLabel->setText("Not Installed");
m_installButton->setText("Install");
}
m_statusLabel->setStyleSheet("color: red; font-weight: bold;");
#ifndef WIN32
m_statusLabel->setStyleSheet("color: red;");
#else
// FIXME: if we call this multiple times, the styles will keep stacking
// and become a mess, need a better way to handle this
m_statusLabel->setStyleSheet(mergeStyles(
m_statusLabel,
QString("QLabel { color: %1; }").arg(COLOR_RED.name())));
#endif
m_installButton->setVisible(true);
}
}
+9 -6
View File
@@ -143,22 +143,25 @@ void DiskUsageWidget::setupUI()
// Set colors
m_systemBar->setStyleSheet(
"QWidget#systemBar { background-color: #a1384d; border: 1px solid"
"#e64a5b; padding: 0; margin: 0; border-top-left-radius: 3px; "
"#e64a5b; padding: 0; margin: 0; border-radius:0px; "
"border-top-left-radius: 3px; "
"border-bottom-left-radius: 3px; }");
m_appsBar->setStyleSheet(
"QWidget#appsBar { background-color: #4f869f; border: 1px solid "
"#63b4da; padding: 0; margin: 0; }");
"#63b4da; border-radius:0px; padding: 0; margin: 0; }");
m_mediaBar->setStyleSheet("QWidget#mediaBar { background-color: #2ECC71; "
"border: none; padding: 0; margin: 0; }");
m_galleryBar->setStyleSheet(
"QWidget#galleryBar { background-color: #9b59b6; border: 1px solid "
"#8e44ad; padding: 0; margin: 0; }");
"#8e44ad; border-radius:0px; padding: 0; margin: 0; }");
m_othersBar->setStyleSheet(
"QWidget#othersBar { background-color: #a28729; border: 1px solid "
"#c4a32d; padding: 0; margin: 0; }");
"#c4a32d; border-radius:0px; padding: 0; margin: 0; }");
m_freeBar->setStyleSheet(
"QWidget#freeBar { background-color: #474747; border: 1px solid "
"#4f4f4f; padding: 0; margin: 0; border-top-right-radius: 3px; "
"QWidget#freeBar { background-color: rgba(255, 255, 255, 10); border: "
"1px solid "
"#4f4f4f4f; padding: 0; margin: 0; border-radius:0px; "
"border-top-right-radius: 3px; "
"border-bottom-right-radius: 3px; }");
// remove padding margin from layout
+4 -4
View File
@@ -239,12 +239,12 @@ QString HttpServer::generateJsonManifest() const
QString HttpServer::getLocalIP() const
{
foreach (const QNetworkInterface &interface,
foreach (const QNetworkInterface &netIf,
QNetworkInterface::allInterfaces()) {
if (interface.flags().testFlag(QNetworkInterface::IsUp) &&
!interface.flags().testFlag(QNetworkInterface::IsLoopBack)) {
if (netIf.flags().testFlag(QNetworkInterface::IsUp) &&
!netIf.flags().testFlag(QNetworkInterface::IsLoopBack)) {
foreach (const QNetworkAddressEntry &entry,
interface.addressEntries()) {
netIf.addressEntries()) {
if (entry.ip().protocol() == QAbstractSocket::IPv4Protocol) {
return entry.ip().toString();
}
+22
View File
@@ -40,13 +40,35 @@
#ifdef __APPLE__
#include "./platform/macos/macos.h"
#elif defined(WIN32)
#include "./platform/windows/win_common.h"
#endif
#define COLOR_GREEN QColor(0, 180, 0) // Green
#define COLOR_ORANGE QColor(255, 140, 0) // Orange
#define COLOR_RED QColor(255, 0, 0) // Red
#define COLOR_BLUE QColor("#2b5693")
#ifndef WIN32
#define COLOR_ACCENT_BLUE QColor("#0b5ed7")
#define COLOR_HYPERLINK QColor(0, 122, 255)
#else
#define COLOR_ACCENT_BLUE QColor(getWindowsAccentColor())
#define COLOR_HYPERLINK QColor("#FF7FFFD4")
#endif
inline QString mergeStyles(QWidget *widget, const QString &newStyles)
{
if (!widget) {
return newStyles;
}
QString existing = widget->styleSheet();
if (existing.isEmpty())
return newStyles;
return existing + "\n" + newStyles;
}
#define MIN_MAIN_WINDOW_SIZE QSize(900, 600)
class ResponsiveGraphicsView : public QGraphicsView
+5 -3
View File
@@ -355,7 +355,7 @@ public:
plist_get_string_val(current_node, &value);
std::string result = value ? value : "";
if (value)
free(value);
plist_mem_free(value);
return result;
}
plist_t getNode() const { return current_node; }
@@ -605,10 +605,12 @@ inline void free_directory_listing(char **entries, size_t count)
return;
for (size_t i = 0; i < count; i++) {
if (entries[i]) {
free(entries[i]);
// FIXME: crashes on Windows
// free(entries[i]);
}
}
free(entries);
// FIXME: crashes on Windows
// free(entries);
}
inline int read_file(const char *filename, uint8_t **data, size_t *length)
+1 -1
View File
@@ -30,7 +30,7 @@
#include <QStatusBar>
#include <QTimer>
#ifdef WIN32
#include "platform/windows/check_deps.h"
#include "platform/windows/win_common.h"
#endif
iFuseWidget::iFuseWidget(iDescriptorDevice *device, QWidget *parent)
+9 -24
View File
@@ -29,9 +29,7 @@ InfoLabel::InfoLabel(const QString &text, const QString &textToCopy,
m_textToCopy(!textToCopy.isEmpty() ? textToCopy : text)
{
setCursor(Qt::PointingHandCursor);
setStyleSheet("QLabel:hover { background-color: rgba(255, 255, 255, 0.1); "
"border-radius: 2px; }");
setStyleSheet(m_style);
m_restoreTimer = new QTimer(this);
m_restoreTimer->setSingleShot(true);
connect(m_restoreTimer, &QTimer::timeout, this,
@@ -49,39 +47,26 @@ void InfoLabel::mousePressEvent(QMouseEvent *event)
// prevent layout shifts
setMinimumWidth(originalWidth);
setText("Copied!");
#ifdef WIN32
setStyleSheet(QStringLiteral(
"QLabel { color: #4CAF50; font-weight: bold; font-size: 14px; }"
"QLabel:hover { background-color: rgba(255, 255, 255, 0.1); "
"border-radius: 2px; }"));
#else
setStyleSheet("QLabel { color: #4CAF50; font-weight: bold; } "
"QLabel:hover { background-color: rgba(255, 255, 255, "
"0.1); border-radius: 2px; }");
#endif
m_restoreTimer->start(1000); // Show "Copied!" for 1 second
}
QLabel::mousePressEvent(event);
}
void InfoLabel::enterEvent(QEnterEvent *event)
{
if (!m_restoreTimer->isActive()) {
setStyleSheet("QLabel:hover { background-color: rgba(255, 255, 255, "
"0.1); border-radius: 2px; }");
}
QLabel::enterEvent(event);
}
void InfoLabel::leaveEvent(QEvent *event)
{
if (!m_restoreTimer->isActive()) {
setStyleSheet("QLabel:hover { background-color: rgba(255, 255, 255, "
"0.1); border-radius: 2px; }");
}
QLabel::leaveEvent(event);
}
void InfoLabel::restoreOriginalText()
{
setText(m_originalText);
setMinimumWidth(0);
setStyleSheet("QLabel:hover { background-color: rgba(255, 255, 255, 0.1); "
"border-radius: 2px; }");
setStyleSheet(m_style);
}
void InfoLabel::setOriginalText(const QString &text) { m_originalText = text; }
+13 -2
View File
@@ -21,6 +21,7 @@
#define INFOLABEL_H
#include <QLabel>
#include <QString>
#include <QTimer>
class InfoLabel : public QLabel
@@ -37,8 +38,6 @@ public:
protected:
void mousePressEvent(QMouseEvent *event) override;
void enterEvent(QEnterEvent *event) override;
void leaveEvent(QEvent *event) override;
private slots:
void restoreOriginalText();
@@ -47,6 +46,18 @@ private:
QString m_originalText;
QString m_textToCopy;
QTimer *m_restoreTimer;
QString m_style =
#ifdef WIN32
QStringLiteral(
"QLabel:hover { background-color: rgba(255, 255, 255, 0.1); "
"border-radius: 2px; }"
"QLabel { "
"font-size: 14px;}");
#else
QStringLiteral(
"QLabel:hover { background-color: rgba(255, 255, 255, 0.1); "
"border-radius: 2px; }");
#endif
};
#endif // INFOLABEL_H
+3 -3
View File
@@ -322,7 +322,7 @@ void InstalledAppsWidget::fetchInstalledApps()
plist_get_string_val(bundle_id, &bundle_id_str);
if (bundle_id_str) {
appData["bundleId"] = QString(bundle_id_str);
free(bundle_id_str);
plist_mem_free(bundle_id_str);
}
}
@@ -337,7 +337,7 @@ void InstalledAppsWidget::fetchInstalledApps()
if (display_name_str) {
appData["displayName"] =
QString(display_name_str);
free(display_name_str);
plist_mem_free(display_name_str);
}
}
@@ -350,7 +350,7 @@ void InstalledAppsWidget::fetchInstalledApps()
plist_get_string_val(version, &version_str);
if (version_str) {
appData["version"] = QString(version_str);
free(version_str);
plist_mem_free(version_str);
}
}
+22 -9
View File
@@ -30,12 +30,20 @@
#include <QVBoxLayout>
#include <QtConcurrent/QtConcurrent>
#ifdef WIN32
#include "platform/windows/win_common.h"
#endif
LoginDialog::LoginDialog(QWidget *parent) : QDialog(parent)
{
setWindowTitle("Login to App Store - iDescriptor");
setModal(true);
setFixedWidth(400);
#ifdef WIN32
setupWinWindow(this);
#endif
QVBoxLayout *layout = new QVBoxLayout(this);
layout->setSpacing(15);
layout->setContentsMargins(20, 20, 20, 20);
@@ -47,8 +55,11 @@ LoginDialog::LoginDialog(QWidget *parent) : QDialog(parent)
m_emailEdit = new QLineEdit();
m_emailEdit->setPlaceholderText("Enter your email");
#ifndef WIN32
m_emailEdit->setStyleSheet("padding: 8px; border: 1px solid #ddd; "
"border-radius: 4px; font-size: 14px;");
#endif
layout->addWidget(m_emailEdit);
// Password
@@ -59,33 +70,35 @@ LoginDialog::LoginDialog(QWidget *parent) : QDialog(parent)
m_passwordEdit = new QLineEdit();
m_passwordEdit->setPlaceholderText("Enter your password");
m_passwordEdit->setEchoMode(QLineEdit::Password);
#ifndef WIN32
m_passwordEdit->setStyleSheet("padding: 8px; border: 1px solid #ddd; "
"border-radius: 4px; font-size: 14px;");
#endif
layout->addWidget(m_passwordEdit);
// Description
QLabel *descriptionLabel =
new QLabel("Don't worry, your credentials won't be "
"stored or shared anywhere. This App is open-source.");
QLabel *descriptionLabel = new QLabel(
"You shouldn't be using your main account here and don't worry, "
"your credentials won't be "
"stored or shared anywhere. This App is open-source.");
descriptionLabel->setStyleSheet("font-size: 10px; font-weight: thin;");
descriptionLabel->setAlignment(Qt::AlignLeft);
descriptionLabel->setWordWrap(true); // Add this line
descriptionLabel->setWordWrap(true);
layout->addWidget(descriptionLabel);
// --- Buttons and Indicator ---
// Create a container widget for the sign-in button and the indicator
QWidget *signInContainer = new QWidget(this);
m_signInStackedLayout = new QStackedLayout(signInContainer);
m_signInStackedLayout->setContentsMargins(0, 0, 0, 0);
// Create the actual "Sign In" button
m_signInButton = new QPushButton("Sign In");
#ifndef WIN32
m_signInButton->setStyleSheet(
"QPushButton { padding: 8px 16px; font-size: 14px; border-radius: 4px; "
"background-color: #007AFF; color: white; border: none; min-width: "
"80px; }"
"QPushButton:hover { background-color: #0056CC; }");
#endif
// Create the indicator
QWidget *indicatorWidget = new QWidget();
QVBoxLayout *indicatorLayout = new QVBoxLayout(indicatorWidget);
@@ -103,15 +116,15 @@ LoginDialog::LoginDialog(QWidget *parent) : QDialog(parent)
// Ensure the container has the same size as the button
signInContainer->setFixedSize(m_signInButton->sizeHint());
// Create the "Cancel" button
m_cancelButton = new QPushButton("Cancel");
// add disabled style to cancel button
#ifndef WIN32
m_cancelButton->setStyleSheet(
"QPushButton { padding: 8px 16px; font-size: 14px; border-radius: 4px; "
"background-color: #f0f0f0; color: #333; border: 1px solid #ddd; "
"min-width: 80px; }"
"QPushButton:disabled { background-color: #eee; color: #aaa; border: "
"1px solid #ddd; }");
#endif
// Layout for the buttons
QHBoxLayout *buttonLayout = new QHBoxLayout();
+12 -2
View File
@@ -23,14 +23,15 @@
#include <QApplication>
#include <QDebug>
#include <QDir>
#include <QFile>
#include <QMessageBox>
#include <QStyleFactory>
#include <QtGlobal>
#include <stdlib.h>
#ifdef WIN32
#include "platform/windows/check_deps.h"
#include "platform/windows/win_common.h"
#endif
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
@@ -45,6 +46,15 @@ int main(int argc, char *argv[])
// " "their default values.");
// }
#ifdef WIN32
QFile styleFile(detectDarkModeWindows() ? ":/resources/win.dark.qcss"
: ":/resources/win.light.qcss");
if (styleFile.open(QFile::ReadOnly | QFile::Text)) {
const QString style = QString::fromUtf8(styleFile.readAll())
.arg(COLOR_ACCENT_BLUE.name());
qDebug() << "Loaded Windows style sheet successfully.";
a.setStyleSheet(style);
}
QString appPath = QCoreApplication::applicationDirPath();
QString gstPluginPath =
QDir::toNativeSeparators(appPath + "/gstreamer-1.0");
+35 -104
View File
@@ -18,7 +18,6 @@
*/
#include "mainwindow.h"
#include "./ui_mainwindow.h"
#include "appswidget.h"
#include "devicemanagerwidget.h"
#include "iDescriptor-ui.h"
@@ -26,9 +25,6 @@
#include "ifusediskunmountbutton.h"
#include "ifusemanager.h"
#include "jailbrokenwidget.h"
// #ifdef ENABLE_RECOVERY_DEVICE_SUPPORT
// #include "libirecovery.h"
// #endif
#include "toolboxwidget.h"
#include "welcomewidget.h"
#include <QHBoxLayout>
@@ -51,112 +47,38 @@
#include <QMenu>
#include <QMenuBar>
#include <QMessageBox>
#ifdef WIN32
#include "platform/windows/check_deps.h"
#include "platform/windows/win_common.h"
#endif
using namespace IdeviceFFI;
// void handleCallback(const idevice_event_t *event, void *userData)
// {
// printf("Device event received: ");
// switch (event->event) {
// case 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*/ if (event->conn_type
// == CONNECTION_NETWORK) {
// return;
// }
// qDebug() << "Device added: " << QString::fromUtf8(event->udid);
// QMetaObject::invokeMethod(
// AppContext::sharedInstance(), "addDevice", Qt::QueuedConnection,
// Q_ARG(QString, QString::fromUtf8(event->udid)),
// Q_ARG(idevice_connection_type, event->conn_type),
// Q_ARG(AddType, AddType::Regular));
// break;
// }
// case IDEVICE_DEVICE_REMOVE: {
// QMetaObject::invokeMethod(AppContext::sharedInstance(),
// "removeDevice",
// Qt::QueuedConnection,
// Q_ARG(QString, QString(event->udid)));
// break;
// }
// case IDEVICE_DEVICE_PAIRED: {
// if (event->conn_type == 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: " << QString::fromUtf8(event->udid);
// QMetaObject::invokeMethod(
// AppContext::sharedInstance(), "addDevice", Qt::QueuedConnection,
// Q_ARG(QString, QString::fromUtf8(event->udid)),
// Q_ARG(idevice_connection_type, event->conn_type),
// Q_ARG(AddType, AddType::Pairing));
// break;
// }
// default:
// qDebug() << "Unhandled event: " << event->event;
// }
// }
// #ifdef ENABLE_RECOVERY_DEVICE_SUPPORT
// void handleCallbackRecovery(const irecv_device_event_t *event, void
// *userData)
// {
// switch (event->type) {
// case IRECV_DEVICE_ADD:
// qDebug() << "Recovery device added: ";
// QMetaObject::invokeMethod(AppContext::sharedInstance(),
// "addRecoveryDevice", Qt::QueuedConnection,
// Q_ARG(uint64_t, event->device_info->ecid));
// break;
// case IRECV_DEVICE_REMOVE:
// qDebug() << "Recovery device removed: ";
// QMetaObject::invokeMethod(AppContext::sharedInstance(),
// "removeRecoveryDevice",
// Qt::QueuedConnection, Q_ARG(uint64_t,
// event->device_info->ecid));
// break;
// default:
// printf("Unhandled recovery event: %d\n", event->type);
// }
// }
// irecv_device_event_context_t context;
// #endif
MainWindow *MainWindow::sharedInstance()
{
static MainWindow instance;
return &instance;
}
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent), ui(new Ui::MainWindow)
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent)
{
ui->setupUi(this);
setMinimumSize(MIN_MAIN_WINDOW_SIZE);
resize(MIN_MAIN_WINDOW_SIZE);
m_ZTabWidget = new ZTabWidget(this);
m_ZTabWidget->setAttribute(Qt::WA_ContentsMarginsRespectsSafeArea, false);
setContentsMargins(0, 0, 0, 0);
QWidget *centralWidget = new QWidget(this);
setCentralWidget(centralWidget);
auto mainLayout = new QVBoxLayout(centralWidget);
mainLayout->setContentsMargins(0, 0, 0, 0);
m_ZTabWidget = new ZTabWidget(this);
#ifdef __APPLE__
setupMacOSWindow(this);
setAttribute(Qt::WA_ContentsMarginsRespectsSafeArea, false);
#endif
setCentralWidget(m_ZTabWidget);
mainLayout->addWidget(m_ZTabWidget);
#ifdef WIN32
setupWinWindow(this);
#endif
m_mainStackedWidget = new QStackedWidget();
WelcomeWidget *welcomePage = new WelcomeWidget(this);
@@ -200,25 +122,35 @@ MainWindow::MainWindow(QWidget *parent)
m_connectedDeviceCountLabel->setStyleSheet(
"QLabel:hover { background-color : #13131319; }");
ui->statusbar->addWidget(m_connectedDeviceCountLabel);
QWidget *statusbar = new QWidget();
QHBoxLayout *statusLayout = new QHBoxLayout(statusbar);
statusLayout->setContentsMargins(0, 0, 0, 0);
statusbar->setObjectName("StatusBar");
statusbar->setStyleSheet(
"QWidget#StatusBar { background-color: transparent; }");
statusLayout->addWidget(m_connectedDeviceCountLabel);
// TODO: implement downloads/uploads progress stuff
StatusBalloon *statusBalloon = StatusBalloon::sharedInstance();
ui->statusbar->addWidget(statusBalloon->getButton());
statusLayout->addWidget(statusBalloon->getButton());
statusLayout->addStretch(1);
ui->statusbar->setContentsMargins(0, 0, 0, 0);
statusLayout->setContentsMargins(0, 0, 0, 0);
QLabel *appVersionLabel = new QLabel(QString("v%1").arg(APP_VERSION));
appVersionLabel->setContentsMargins(5, 0, 5, 0);
appVersionLabel->setStyleSheet(
"QLabel:hover { background-color : #13131319; }");
ui->statusbar->addPermanentWidget(appVersionLabel);
ui->statusbar->addPermanentWidget(githubButton);
ui->statusbar->addPermanentWidget(settingsButton);
#ifdef WIN32
ui->statusbar->setStyleSheet(
"QStatusBar { border-top: 1px solid #dcdcdc; }");
#endif
statusLayout->addWidget(appVersionLabel);
statusLayout->addWidget(githubButton);
statusLayout->addWidget(settingsButton);
// #ifdef WIN32
// statusLayout->setStyleSheet("QStatusBar { border-top: 1px solid
// #dcdcdc;
// }");
// #endif
mainLayout->addWidget(statusbar);
#ifdef __linux__
QList<QString> mounted_iFusePaths = iFuseManager::getMountPoints();
@@ -226,7 +158,7 @@ MainWindow::MainWindow(QWidget *parent)
for (const QString &path : mounted_iFusePaths) {
auto *p = new iFuseDiskUnmountButton(path);
ui->statusbar->addPermanentWidget(p);
statusbar->addWidget(p);
connect(p, &iFuseDiskUnmountButton::clicked, this, [this, p, path]() {
bool ok = iFuseManager::linuxUnmount(path);
if (!ok) {
@@ -235,7 +167,7 @@ MainWindow::MainWindow(QWidget *parent)
". Please try again.");
return;
}
ui->statusbar->removeWidget(p);
statusbar->removeWidget(p);
p->deleteLater();
});
}
@@ -521,7 +453,6 @@ MainWindow::~MainWindow()
// #ifdef ENABLE_RECOVERY_DEVICE_SUPPORT
// irecv_device_event_unsubscribe(context);
// #endif
delete ui;
m_deviceMonitor->requestInterruption();
// FIXME:QThread: Destroyed while thread '' is still running
// m_deviceMonitor->wait();
+9 -13
View File
@@ -22,23 +22,13 @@
#include "ZDownloader.h"
#include "ZUpdater.h"
#include "devicemanagerwidget.h"
#include "iDescriptor.h"
#include <QMainWindow>
// #ifdef ENABLE_RECOVERY_DEVICE_SUPPORT
// #include "libirecovery.h"
// #endif
#include "devicemonitor.h"
#include "iDescriptor.h"
#include "ztabwidget.h"
#include <QLabel>
#include <QMainWindow>
#include <QStackedWidget>
QT_BEGIN_NAMESPACE
namespace Ui
{
class MainWindow;
}
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
@@ -54,11 +44,17 @@ public slots:
private:
void createMenus();
Ui::MainWindow *ui;
ZTabWidget *m_ZTabWidget;
DeviceManagerWidget *m_deviceManager;
QStackedWidget *m_mainStackedWidget;
QLabel *m_connectedDeviceCountLabel;
DeviceMonitorThread *m_deviceMonitor;
QLabel *m_titleLabel;
QPushButton *m_minBtn;
QPushButton *m_maxBtn;
QPushButton *m_closeBtn;
QWidget *m_titleBar;
QWidget *m_contentArea;
QHBoxLayout *m_titleBarLayout;
};
#endif // MAINWINDOW_H
+101
View File
@@ -0,0 +1,101 @@
/*
* 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 "../../settingsmanager.h"
#include "win_common.h"
void enableAcrylic(HWND hwnd)
{
const HINSTANCE hModule = LoadLibraryA("user32.dll");
if (hModule) {
struct ACCENTPOLICY {
int nAccentState;
int nFlags;
DWORD nColor;
int nAnimationId;
};
struct WINCOMPATTRDATA {
int nAttribute;
PVOID pData;
ULONG ulDataSize;
};
typedef BOOL(WINAPI *
pSetWindowCompositionAttribute)(HWND, WINCOMPATTRDATA *);
const auto SetWindowCompositionAttribute =
(pSetWindowCompositionAttribute)GetProcAddress(
hModule, "SetWindowCompositionAttribute");
if (SetWindowCompositionAttribute) {
ACCENTPOLICY policy{};
policy.nAccentState = 4; // ACCENT_ENABLE_ACRYLICBLURBEHIND
policy.nFlags = 2;
policy.nColor = 0xD0202020;
WINCOMPATTRDATA data{};
data.nAttribute = 19;
data.pData = &policy;
data.ulDataSize = sizeof(policy);
SetWindowCompositionAttribute(hwnd, &data);
}
FreeLibrary(hModule);
}
}
#ifndef DWMWA_SYSTEMBACKDROP_TYPE
#define DWMWA_SYSTEMBACKDROP_TYPE 38
#endif
#ifndef DWMWA_MICA_EFFECT
#define DWMWA_MICA_EFFECT 1029
#endif
void enableMica(HWND hwnd)
{
if (!hwnd)
return;
SettingsManager *sm = SettingsManager::sharedInstance();
WIN_BACKDROP type = sm->winBackdropType();
MARGINS margins = {-1};
DwmExtendFrameIntoClientArea(hwnd, &margins);
DWORD build = 0;
RTL_OSVERSIONINFOW rovi = {0};
rovi.dwOSVersionInfoSize = sizeof(rovi);
using RtlGetVersionPtr = LONG(WINAPI *)(PRTL_OSVERSIONINFOW);
HMODULE ntdll = GetModuleHandleW(L"ntdll.dll");
if (ntdll) {
auto pRtlGetVersion = reinterpret_cast<RtlGetVersionPtr>(
GetProcAddress(ntdll, "RtlGetVersion"));
if (pRtlGetVersion && pRtlGetVersion(&rovi) == 0) {
build = rovi.dwBuildNumber;
}
}
if (build >= 22523) {
DwmSetWindowAttribute(hwnd, DWMWA_SYSTEMBACKDROP_TYPE, &type,
sizeof(type));
} else if (build >= 22000) {
// Undocumented old method
BOOL mica = TRUE;
DwmSetWindowAttribute(hwnd, DWMWA_MICA_EFFECT, &mica, sizeof(mica));
}
}

Some files were not shown because too many files have changed in this diff Show More