mirror of
https://github.com/iDescriptor/iDescriptor.git
synced 2026-06-21 19:35:49 +08:00
refactor(ui): add initial QML setup
This commit is contained in:
+11
-12
@@ -95,10 +95,6 @@ if (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
|
||||
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreadedDLL")
|
||||
endif()
|
||||
|
||||
set(CMAKE_AUTOMOC ON)
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
set(CXXQT_QTCOMPONENTS Core Gui Qml QuickControls2 QuickTest Widgets Test)
|
||||
if(NOT BUILD_WASM)
|
||||
set(CXXQT_QTCOMPONENTS ${CXXQT_QTCOMPONENTS})
|
||||
@@ -138,7 +134,7 @@ endif()
|
||||
cxx_qt_import_crate(
|
||||
MANIFEST_PATH src/rust/Cargo.toml
|
||||
CRATES idescriptor_rust_codebase
|
||||
LOCKED
|
||||
# LOCKED
|
||||
QT_MODULES Qt::Core Qt::Gui Qt::Qml Qt::QuickControls2
|
||||
)
|
||||
|
||||
@@ -188,13 +184,16 @@ else()
|
||||
endif()
|
||||
|
||||
file(GLOB PROJECT_SOURCES
|
||||
src/*.h
|
||||
src/*.cpp
|
||||
src/core/helpers/*.cpp
|
||||
src/core/services/*.cpp
|
||||
src/base/*.cpp
|
||||
src/base/*.h
|
||||
# src/*.h
|
||||
# src/*.cpp
|
||||
# src/core/helpers/*.cpp
|
||||
# src/core/services/*.cpp
|
||||
# src/base/*.cpp
|
||||
# src/base/*.h
|
||||
src/main.cpp
|
||||
src/constants.h
|
||||
resources.qrc
|
||||
resources.ui.qrc
|
||||
)
|
||||
|
||||
|
||||
@@ -283,6 +282,7 @@ target_link_libraries(iDescriptor PRIVATE
|
||||
Qt6::Location
|
||||
Qt6::Positioning
|
||||
Qt6::QuickWidgets
|
||||
Qt6::Qml
|
||||
Qt6::QuickControls2
|
||||
PkgConfig::SSH
|
||||
${SSH_LIBRARY}
|
||||
@@ -312,7 +312,6 @@ if(ENABLE_RECOVERY_DEVICE_SUPPORT)
|
||||
endif()
|
||||
|
||||
target_include_directories(iDescriptor PRIVATE
|
||||
# Put idevice-rs includes FIRST
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/lib
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/lib/zupdater/src
|
||||
)
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
<RCC>
|
||||
<qresource prefix="/">
|
||||
<file>src/qml/Main.qml</file>
|
||||
<file>src/qml/Index.qml</file>
|
||||
<file>src/qml/Tabs.qml</file>
|
||||
<file>src/qml/HowToConnect.qml</file>
|
||||
<file>src/qml/Welcome.qml</file>
|
||||
<file>src/qml/TabButton.qml</file>
|
||||
<file>src/qml/Device.qml</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
@@ -0,0 +1,18 @@
|
||||
#ifndef CONSTANTS_H
|
||||
#define CONSTANTS_H
|
||||
|
||||
#include "iDescriptor.h"
|
||||
#include <QObject>
|
||||
|
||||
class Constants : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
Q_PROPERTY(QString REPO_URL READ REPO_URL CONSTANT)
|
||||
public:
|
||||
explicit Constants(QObject *parent = nullptr) : QObject(parent) {}
|
||||
|
||||
QString REPO_URL() const { return QStringLiteral(IDESCRIPTOR_REPO_URL); }
|
||||
};
|
||||
|
||||
#endif // CONSTANTS_H
|
||||
+11
-11
@@ -47,7 +47,7 @@ using u_int64_t = uint64_t;
|
||||
"© 2026 The iDescriptor Project contributors. See AUTHORS for details."
|
||||
#define RECOVERY_CLIENT_CONNECTION_TRIES 3
|
||||
#define APPLE_VENDOR_ID 0x05ac
|
||||
#define REPO_URL "https://github.com/iDescriptor/iDescriptor"
|
||||
#define IDESCRIPTOR_REPO_URL "https://github.com/iDescriptor/iDescriptor"
|
||||
#define SPONSORS_JSON_URL \
|
||||
"https://raw.githubusercontent.com/iDescriptor/iDescriptor/refs/heads/" \
|
||||
"main/sponsors.json"
|
||||
@@ -86,13 +86,13 @@ using u_int64_t = uint64_t;
|
||||
#endif
|
||||
|
||||
// rust codebase
|
||||
#include "idescriptor_rust_codebase/src/afc2_services.cxxqt.h"
|
||||
#include "idescriptor_rust_codebase/src/afc_services.cxxqt.h"
|
||||
#include "idescriptor_rust_codebase/src/hause_arrest.cxxqt.h"
|
||||
#include "idescriptor_rust_codebase/src/io_manager.cxxqt.h"
|
||||
#include "idescriptor_rust_codebase/src/lib.cxxqt.h"
|
||||
#include "idescriptor_rust_codebase/src/screenshot.cxxqt.h"
|
||||
#include "idescriptor_rust_codebase/src/service_manager.cxxqt.h"
|
||||
// #include "idescriptor_rust_codebase/src/afc2_services.cxxqt.h"
|
||||
// #include "idescriptor_rust_codebase/src/afc_services.cxxqt.h"
|
||||
// #include "idescriptor_rust_codebase/src/hause_arrest.cxxqt.h"
|
||||
// #include "idescriptor_rust_codebase/src/io_manager.cxxqt.h"
|
||||
// #include "idescriptor_rust_codebase/src/lib.cxxqt.h"
|
||||
// #include "idescriptor_rust_codebase/src/screenshot.cxxqt.h"
|
||||
// #include "idescriptor_rust_codebase/src/service_manager.cxxqt.h"
|
||||
|
||||
namespace iDescriptor
|
||||
{
|
||||
@@ -233,9 +233,9 @@ struct iDescriptorDevice {
|
||||
iDescriptor::IdeviceConnectionType conn_type;
|
||||
DeviceInfo deviceInfo;
|
||||
unsigned int ios_version;
|
||||
CXX::ServiceManager *service_manager;
|
||||
CXX::AfcBackend *afc_backend;
|
||||
CXX::Afc2Backend *afc2_backend;
|
||||
QObject *service_manager;
|
||||
QObject *afc_backend;
|
||||
QObject *afc2_backend;
|
||||
};
|
||||
|
||||
void fullDeviceInfo(const pugi::xml_document &doc, DeviceInfo &d);
|
||||
|
||||
+58
-27
@@ -17,8 +17,8 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "constants.h"
|
||||
#include "iDescriptor.h"
|
||||
#include "mainwindow.h"
|
||||
#include "settingsmanager.h"
|
||||
#include <QApplication>
|
||||
#include <QDebug>
|
||||
@@ -32,43 +32,55 @@
|
||||
#include "platform/windows/win_common.h"
|
||||
#endif
|
||||
|
||||
#include <QQmlApplicationEngine>
|
||||
#include <QQmlContext>
|
||||
#include <QQuickWindow>
|
||||
#include <QtGui/QGuiApplication>
|
||||
#include <QtQml/QQmlApplicationEngine>
|
||||
#define FLUENTUI_BUILD_STATIC_LIB 1
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
#ifdef WIN32
|
||||
// ::SetUnhandledExceptionFilter(MyUnhandledExceptionFilter);
|
||||
qputenv("QT_QPA_PLATFORM", "windows:darkmode=2");
|
||||
#endif
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
|
||||
qputenv("QT_QUICK_CONTROLS_STYLE", "Basic");
|
||||
#else
|
||||
qputenv("QT_QUICK_CONTROLS_STYLE", "Default");
|
||||
#endif
|
||||
#ifdef Q_OS_LINUX
|
||||
// fix bug UOSv20 v-sync does not work
|
||||
qputenv("QSG_RENDER_LOOP", "basic");
|
||||
#endif
|
||||
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
|
||||
QQuickWindow::setGraphicsApi(QSGRendererInterface::OpenGL);
|
||||
#endif
|
||||
#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
|
||||
QApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
|
||||
QApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0))
|
||||
QApplication::setHighDpiScaleFactorRoundingPolicy(
|
||||
Qt::HighDpiScaleFactorRoundingPolicy::PassThrough);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
QApplication a(argc, argv);
|
||||
QCoreApplication::setOrganizationName("iDescriptor");
|
||||
QCoreApplication::setApplicationName("iDescriptor");
|
||||
QCoreApplication::setApplicationVersion(APP_VERSION);
|
||||
if (a.arguments().contains("--reset-settings")) {
|
||||
SettingsManager::sharedInstance()->clear();
|
||||
// SettingsManager::sharedInstance()->clear();
|
||||
QMessageBox::information(nullptr, "Settings Reset",
|
||||
"All application settings have been reset to "
|
||||
"their default values.");
|
||||
}
|
||||
QQmlApplicationEngine engine;
|
||||
|
||||
#ifdef WIN32
|
||||
|
||||
bool enableMica = !a.arguments().contains("--disable-mica") &&
|
||||
!SettingsManager::sharedInstance()->disableMica();
|
||||
if (!enableMica) {
|
||||
SettingsManager::sharedInstance()->setDisableMica(true);
|
||||
qDebug() << "Mica effect disabled";
|
||||
}
|
||||
|
||||
QApplication::setEffectEnabled(Qt::UI_AnimateCombo, false);
|
||||
|
||||
QOperatingSystemVersion osVersion = QOperatingSystemVersion::current();
|
||||
if (enableMica && osVersion >= QOperatingSystemVersion::Windows11) {
|
||||
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);
|
||||
}
|
||||
} else {
|
||||
qDebug() << "Not applying WinUI stylesheet.";
|
||||
}
|
||||
|
||||
QString appPath = QCoreApplication::applicationDirPath();
|
||||
QString gstPluginPath =
|
||||
QDir::toNativeSeparators(appPath + "/gstreamer-1.0");
|
||||
@@ -103,7 +115,26 @@ int main(int argc, char *argv[])
|
||||
setenv("GST_PLUGIN_SYSTEM_PATH", gstPluginPath.toUtf8().constData(), 1);
|
||||
setenv("GST_PLUGIN_SCANNER", gstPluginScannerPath.toUtf8().constData(), 1);
|
||||
#endif
|
||||
MainWindow *w = MainWindow::sharedInstance();
|
||||
w->show();
|
||||
|
||||
const QUrl url(QStringLiteral("qrc:/src/qml/Main.qml"));
|
||||
QObject::connect(
|
||||
&engine, &QQmlApplicationEngine::objectCreated, &a,
|
||||
[url](QObject *obj, const QUrl &objUrl) {
|
||||
if (!obj && url == objUrl) {
|
||||
QCoreApplication::exit(-1);
|
||||
}
|
||||
},
|
||||
Qt::QueuedConnection);
|
||||
|
||||
// FIXME: for some reason we have to set this
|
||||
// dont let this end up in final build
|
||||
#ifdef WIN32
|
||||
engine.addImportPath("C:/Qt/6.8.3/mingw_64/qml");
|
||||
#endif
|
||||
Constants constants;
|
||||
|
||||
engine.rootContext()->setContextProperty("CONSTANTS", &constants);
|
||||
engine.load(url);
|
||||
|
||||
return a.exec();
|
||||
}
|
||||
|
||||
@@ -71,44 +71,44 @@ void enableMica(HWND hwnd)
|
||||
{
|
||||
if (!hwnd)
|
||||
return;
|
||||
SettingsManager *sm = SettingsManager::sharedInstance();
|
||||
WIN_BACKDROP type = sm->winBackdropType();
|
||||
MARGINS margins = {-1};
|
||||
DwmExtendFrameIntoClientArea(hwnd, &margins);
|
||||
// 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);
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
// 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));
|
||||
}
|
||||
// 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));
|
||||
// }
|
||||
}
|
||||
|
||||
void setupWinWindow(QWidget *window)
|
||||
{
|
||||
QOperatingSystemVersion osVersion = QOperatingSystemVersion::current();
|
||||
if (osVersion < QOperatingSystemVersion::Windows11 ||
|
||||
SettingsManager::sharedInstance()->disableMica())
|
||||
return;
|
||||
window->setAttribute(Qt::WA_TranslucentBackground);
|
||||
HWND hwnd = reinterpret_cast<HWND>(window->winId());
|
||||
enableMica(hwnd);
|
||||
// QOperatingSystemVersion osVersion = QOperatingSystemVersion::current();
|
||||
// if (osVersion < QOperatingSystemVersion::Windows11 ||
|
||||
// SettingsManager::sharedInstance()->disableMica())
|
||||
// return;
|
||||
// window->setAttribute(Qt::WA_TranslucentBackground);
|
||||
// HWND hwnd = reinterpret_cast<HWND>(window->winId());
|
||||
// enableMica(hwnd);
|
||||
|
||||
/*
|
||||
normally we had plans to enable acrylic on win 10 but since it's
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
import QtQuick 2.15
|
||||
import QtQuick.Controls 2.15
|
||||
import QtQuick.Layouts 1.15
|
||||
import "."
|
||||
import com.kdab.cxx_qt.demo 1.0
|
||||
|
||||
Item {
|
||||
id: root
|
||||
property ListModel devices: ListModel {}
|
||||
|
||||
property bool showWelcomePage : true
|
||||
readonly property Core core: Core {}
|
||||
|
||||
Component.onCompleted: {
|
||||
root.core.init()
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: root.core
|
||||
|
||||
function onDevice_event(eventType, udid, info) {
|
||||
console.log("Device event:", eventType, udid, info)
|
||||
root.showWelcomePage = false;
|
||||
if (eventType === 1) {
|
||||
// Use append to add items to the ListModel
|
||||
devices.append({ udid: udid, info: info })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Repeater {
|
||||
model: devices
|
||||
delegate: Label {
|
||||
text: model.info
|
||||
font.pixelSize: 16
|
||||
padding: 10
|
||||
Layout.fillWidth: true
|
||||
//MouseArea {
|
||||
// anchors.fill: parent
|
||||
// onClicked: {
|
||||
// root.currentIndex = index + 1
|
||||
// root.showWelcomePage = false
|
||||
// }
|
||||
//}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Welcome {
|
||||
id: welcomePage
|
||||
visible : showWelcomePage
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,207 @@
|
||||
import QtQuick 2.15
|
||||
import QtQuick.Controls 2.15
|
||||
import QtQuick.Layouts 1.15
|
||||
|
||||
Dialog {
|
||||
id: dlg
|
||||
modal: true
|
||||
focus: true
|
||||
closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutside
|
||||
|
||||
width: 560
|
||||
height: 560
|
||||
|
||||
property int currentIndex: 0
|
||||
property bool loading: true
|
||||
|
||||
onOpened: {
|
||||
loading = true
|
||||
currentIndex = 0
|
||||
loadTimer.restart()
|
||||
}
|
||||
|
||||
Timer {
|
||||
id: loadTimer
|
||||
interval: 500
|
||||
repeat: false
|
||||
onTriggered: dlg.loading = false
|
||||
}
|
||||
|
||||
function updateNav() {
|
||||
prevBtn.enabled = dlg.currentIndex > 0
|
||||
nextBtn.enabled = dlg.currentIndex < (stack.count - 1)
|
||||
}
|
||||
|
||||
onCurrentIndexChanged: updateNav()
|
||||
Component.onCompleted: updateNav()
|
||||
|
||||
background: Rectangle {
|
||||
radius: 10
|
||||
color: palette.window
|
||||
border.color: Qt.rgba(0, 0, 0, 0.12)
|
||||
border.width: 1
|
||||
}
|
||||
|
||||
contentItem: Item {
|
||||
anchors.fill: parent
|
||||
|
||||
ColumnLayout {
|
||||
anchors.fill: parent
|
||||
anchors.margins: 16
|
||||
spacing: 12
|
||||
|
||||
Item {
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
|
||||
StackLayout {
|
||||
id: stack
|
||||
anchors.fill: parent
|
||||
currentIndex: dlg.currentIndex
|
||||
|
||||
// Page 1
|
||||
Item {
|
||||
ColumnLayout {
|
||||
anchors.fill: parent
|
||||
spacing: 10
|
||||
|
||||
Item { Layout.fillHeight: true }
|
||||
|
||||
Text {
|
||||
Layout.fillWidth: true
|
||||
text: "Connect your device"
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
wrapMode: Text.WordWrap
|
||||
font.pixelSize: 16
|
||||
font.bold: true
|
||||
color: palette.text
|
||||
}
|
||||
|
||||
Image {
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
source: "qrc:/resources/connect.png"
|
||||
fillMode: Image.PreserveAspectFit
|
||||
smooth: true
|
||||
mipmap: true
|
||||
Layout.preferredWidth: 200
|
||||
Layout.preferredHeight: 200
|
||||
}
|
||||
|
||||
Item { Layout.fillHeight: true }
|
||||
}
|
||||
}
|
||||
|
||||
// Page 2
|
||||
Item {
|
||||
ColumnLayout {
|
||||
anchors.fill: parent
|
||||
spacing: 10
|
||||
|
||||
Item { Layout.fillHeight: true }
|
||||
|
||||
Text {
|
||||
Layout.fillWidth: true
|
||||
text: "Accept the pairing dialog"
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
wrapMode: Text.WordWrap
|
||||
font.pixelSize: 16
|
||||
font.bold: true
|
||||
color: palette.text
|
||||
}
|
||||
|
||||
Image {
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
source: "qrc:/resources/trust.png"
|
||||
fillMode: Image.PreserveAspectFit
|
||||
smooth: true
|
||||
mipmap: true
|
||||
Layout.preferredWidth: 200
|
||||
Layout.preferredHeight: 200
|
||||
}
|
||||
|
||||
Item { Layout.fillHeight: true }
|
||||
}
|
||||
}
|
||||
|
||||
// Page 3
|
||||
Item {
|
||||
ColumnLayout {
|
||||
anchors.fill: parent
|
||||
spacing: 10
|
||||
|
||||
Item { Layout.fillHeight: true }
|
||||
|
||||
Text {
|
||||
Layout.fillWidth: true
|
||||
text: {
|
||||
if (Qt.platform.os === "windows")
|
||||
return "You can now unplug the device. iDescriptor will connect to it automatically (requires iOS 15 or later and the Bonjour service)."
|
||||
if (Qt.platform.os === "linux")
|
||||
return "You can now unplug the device. iDescriptor will connect to it automatically (requires iOS 15 or later and the Avahi daemon)."
|
||||
return "You can now unplug the device. iDescriptor will connect to it automatically (requires iOS 15 or later)."
|
||||
}
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
wrapMode: Text.WordWrap
|
||||
font.pixelSize: 16
|
||||
font.bold: true
|
||||
color: palette.text
|
||||
}
|
||||
|
||||
Image {
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
source: "qrc:/resources/ios-version.png"
|
||||
fillMode: Image.PreserveAspectFit
|
||||
smooth: true
|
||||
mipmap: true
|
||||
Layout.preferredWidth: 200
|
||||
Layout.preferredHeight: 200
|
||||
}
|
||||
|
||||
Item { Layout.fillHeight: true }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
visible: dlg.loading
|
||||
color: Qt.rgba(0, 0, 0, 0.06)
|
||||
|
||||
BusyIndicator {
|
||||
anchors.centerIn: parent
|
||||
running: dlg.loading
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
Layout.fillWidth: true
|
||||
spacing: 10
|
||||
|
||||
Item { Layout.fillWidth: true }
|
||||
|
||||
Button {
|
||||
id: prevBtn
|
||||
text: "Previous"
|
||||
icon.source: "qrc:/resources/icons/MaterialSymbolsArrowLeftAlt.png"
|
||||
Layout.preferredWidth: 48
|
||||
onClicked: {
|
||||
if (dlg.currentIndex > 0) dlg.currentIndex -= 1
|
||||
}
|
||||
}
|
||||
|
||||
Button {
|
||||
id: nextBtn
|
||||
text: "Next"
|
||||
icon.source: "qrc:/resources/icons/MaterialSymbolsArrowRightAlt.png"
|
||||
Layout.preferredWidth: 48
|
||||
onClicked: {
|
||||
if (dlg.currentIndex < stack.count - 1) dlg.currentIndex += 1
|
||||
}
|
||||
}
|
||||
|
||||
Item { Layout.fillWidth: true }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
import QtQuick 2.15
|
||||
import QtQuick.Controls 2.15
|
||||
import FluentUI 1.0
|
||||
import QtQuick.Layouts 1.15
|
||||
import "."
|
||||
|
||||
FluWindow {
|
||||
|
||||
id:window
|
||||
title: "iDescriptor"
|
||||
width: 1000
|
||||
height: 668
|
||||
minimumWidth: 668
|
||||
minimumHeight: 320
|
||||
launchMode: FluWindowType.SingleTask
|
||||
fitsAppBarWindows: true
|
||||
property int currentIndex: 0
|
||||
|
||||
appBar: FluAppBar {
|
||||
height: 28
|
||||
showDark: true
|
||||
z: 7
|
||||
|
||||
RowLayout{
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: parent.top
|
||||
anchors.topMargin: 10
|
||||
spacing: 0
|
||||
TabButton {
|
||||
text: qsTr("iDevice")
|
||||
onClicked: currentIndex = 0
|
||||
active: currentIndex == 0
|
||||
}
|
||||
|
||||
TabButton {
|
||||
text: qsTr("Apps")
|
||||
onClicked: currentIndex = 1
|
||||
active: currentIndex == 1
|
||||
}
|
||||
TabButton {
|
||||
text: qsTr("Toolbox")
|
||||
onClicked: currentIndex = 2
|
||||
active: currentIndex == 2
|
||||
}
|
||||
TabButton {
|
||||
text: qsTr("Jailbroken")
|
||||
onClicked: currentIndex = 3
|
||||
active: currentIndex == 3
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Tabs {
|
||||
currentIndex: window.currentIndex
|
||||
anchors.fill: parent
|
||||
anchors.topMargin: appBar.height
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
import QtQuick 2.15
|
||||
import QtQuick.Window 2.15
|
||||
// import QtQuick.Controls 2.15
|
||||
import QtQuick.Layouts 1.15
|
||||
import FluentUI 1.0
|
||||
|
||||
FluLauncher {
|
||||
id: app
|
||||
// Connections{
|
||||
// target: FluTheme
|
||||
// function onDarkModeChanged(){
|
||||
// SettingsHelper.saveDarkMode(FluTheme.darkMode)
|
||||
// }
|
||||
// }
|
||||
// Connections{
|
||||
// target: FluApp
|
||||
// function onUseSystemAppBarChanged(){
|
||||
// SettingsHelper.saveUseSystemAppBar(FluApp.useSystemAppBar)
|
||||
// }
|
||||
// }
|
||||
// Connections{
|
||||
// target: TranslateHelper
|
||||
// function onCurrentChanged(){
|
||||
// SettingsHelper.saveLanguage(TranslateHelper.current)
|
||||
// }
|
||||
// }
|
||||
Component.onCompleted: {
|
||||
// Network.openLog = false
|
||||
// Network.setInterceptor(function(param){
|
||||
// param.addHeader("Token","000000000000000000000")
|
||||
// })
|
||||
FluApp.init(app,Qt.locale())
|
||||
// FluApp.windowIcon = "qrc:/example/res/image/favicon.ico"
|
||||
// FluApp.useSystemAppBar = SettingsHelper.getUseSystemAppBar()
|
||||
FluApp.useSystemAppBar = false
|
||||
// FluTheme.darkMode = SettingsHelper.getDarkMode()
|
||||
FluTheme.darkMode = false
|
||||
FluTheme.animationEnabled = true
|
||||
FluRouter.routes = {
|
||||
"/":"qrc:/src/qml/Index.qml",
|
||||
}
|
||||
var args = Qt.application.arguments
|
||||
if(args.length>=2 && args[1].startsWith("-crashed=")){
|
||||
FluRouter.navigate("/crash",{crashFilePath:args[1].replace("-crashed=","")})
|
||||
}else{
|
||||
FluRouter.navigate("/")
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
import QtQuick 2.15
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
|
||||
Button {
|
||||
id: btn
|
||||
property bool active: false
|
||||
|
||||
contentItem : Text {
|
||||
text : btn.text
|
||||
color : btn.active ? "#888888" : "red"
|
||||
font.pixelSize: 22
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
}
|
||||
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
background: Rectangle {
|
||||
color : "transparent"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
import QtQuick 2.15
|
||||
import QtQuick.Controls 2.15
|
||||
import QtQuick.Layouts 1.15
|
||||
import "."
|
||||
import com.kdab.cxx_qt.demo 1.0
|
||||
|
||||
Item {
|
||||
id: root
|
||||
anchors.fill: parent
|
||||
property int currentIndex : 0
|
||||
|
||||
|
||||
Device {
|
||||
id : device
|
||||
visible : currentIndex == 0
|
||||
opacity: root.currentIndex === 0 ? 1 : 0
|
||||
property real slideY: root.currentIndex === 0 ? 0 : 20
|
||||
transform: Translate { y: device.slideY }
|
||||
|
||||
Behavior on opacity {
|
||||
NumberAnimation { duration: 167; easing.type: Easing.OutCubic }
|
||||
}
|
||||
Behavior on slideY {
|
||||
NumberAnimation { duration: 167; easing.type: Easing.OutCubic }
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,163 @@
|
||||
import QtQuick 2.15
|
||||
import QtQuick.Controls 2.15
|
||||
import QtQuick.Layouts 1.15
|
||||
|
||||
Item {
|
||||
id: root
|
||||
anchors.fill: parent
|
||||
|
||||
// FIXME: theming
|
||||
property color linkColor: "#3b82f6"
|
||||
|
||||
|
||||
ColumnLayout {
|
||||
id: mainLayout
|
||||
anchors.fill: parent
|
||||
spacing: 0
|
||||
|
||||
Item { Layout.preferredHeight: 10 }
|
||||
|
||||
Item { Layout.fillHeight: true }
|
||||
|
||||
Text {
|
||||
id: title
|
||||
Layout.fillWidth: true
|
||||
text: "Welcome to iDescriptor"
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
font.pixelSize: 28
|
||||
font.weight: Font.DemiBold
|
||||
wrapMode: Text.WordWrap
|
||||
color: palette.text
|
||||
}
|
||||
|
||||
Item { Layout.preferredHeight: 6 }
|
||||
|
||||
Text {
|
||||
id: subtitle
|
||||
Layout.fillWidth: true
|
||||
text: "Open-Source & Free"
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
font.pixelSize: 10
|
||||
font.weight: Font.Normal
|
||||
wrapMode: Text.WordWrap
|
||||
color: palette.text
|
||||
}
|
||||
|
||||
Item { Layout.preferredHeight: 12 }
|
||||
|
||||
RowLayout {
|
||||
id: imageAndWirelessDevicesLayout
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
spacing: 75
|
||||
|
||||
Image {
|
||||
id: connectImage
|
||||
source: "qrc:/resources/connect.png"
|
||||
fillMode: Image.PreserveAspectFit
|
||||
mipmap: true
|
||||
smooth: true
|
||||
|
||||
sourceSize.width: 0
|
||||
sourceSize.height: 0
|
||||
Layout.preferredWidth: implicitWidth
|
||||
Layout.preferredHeight: implicitHeight
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
id: explorerWithInstructionLayout
|
||||
spacing: 12
|
||||
|
||||
// FIXME: implement
|
||||
Rectangle {
|
||||
Layout.preferredWidth: 360
|
||||
Layout.preferredHeight: 180
|
||||
radius: 8
|
||||
color: "#1e40af" // blue
|
||||
border.color: "#0b2a7a"
|
||||
border.width: 1
|
||||
|
||||
Text {
|
||||
anchors.centerIn: parent
|
||||
text: "NetworkDevicesToConnectWidget"
|
||||
color: "white"
|
||||
font.pixelSize: 14
|
||||
font.weight: Font.DemiBold
|
||||
}
|
||||
}
|
||||
|
||||
Text {
|
||||
id: howToConnectLink
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
text: "How to connect a wireless device?"
|
||||
color: root.linkColor
|
||||
font.pixelSize: 12
|
||||
font.weight: Font.DemiBold
|
||||
wrapMode: Text.NoWrap
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onClicked: root.howToConnectRequested()
|
||||
}
|
||||
}
|
||||
|
||||
Item { Layout.preferredHeight: 20 }
|
||||
}
|
||||
}
|
||||
|
||||
Item { Layout.preferredHeight: 10 }
|
||||
|
||||
Text {
|
||||
id: instruction
|
||||
Layout.fillWidth: true
|
||||
text: "Connect an iDevice to get started"
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
font.pixelSize: 14
|
||||
wrapMode: Text.WordWrap
|
||||
color: palette.text
|
||||
}
|
||||
|
||||
Item { Layout.preferredHeight: 10 }
|
||||
|
||||
Text {
|
||||
id: githubLink
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
text: "Found an issue? Report it on GitHub"
|
||||
color: root.linkColor
|
||||
font.pixelSize: 12
|
||||
font.weight: Font.DemiBold
|
||||
wrapMode: Text.NoWrap
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onClicked: Qt.openUrlExternally(CONSTANTS.REPO_URL)
|
||||
}
|
||||
}
|
||||
|
||||
Item { Layout.preferredHeight: 10 }
|
||||
|
||||
// FIXME: implement
|
||||
Rectangle {
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
visible: Qt.platform.os !== "osx"
|
||||
Layout.preferredWidth: 520
|
||||
Layout.preferredHeight: 90
|
||||
radius: 8
|
||||
color: "#b91c1c" // red
|
||||
border.color: "#7f1d1d"
|
||||
border.width: 1
|
||||
|
||||
Text {
|
||||
anchors.centerIn: parent
|
||||
text: "DiagnoseWidget"
|
||||
color: "white"
|
||||
font.pixelSize: 14
|
||||
font.weight: Font.DemiBold
|
||||
}
|
||||
}
|
||||
|
||||
// bottom stretch
|
||||
Item { Layout.fillHeight: true }
|
||||
}
|
||||
}
|
||||
+8
-11
@@ -1,13 +1,10 @@
|
||||
use cxx_qt_build::CxxQtBuilder;
|
||||
use cxx_qt_build::{CxxQtBuilder, QmlModule};
|
||||
|
||||
fn main() {
|
||||
CxxQtBuilder::new()
|
||||
.file("src/lib.rs")
|
||||
.file("src/afc_services.rs")
|
||||
.file("src/afc2_services.rs")
|
||||
.file("src/service_manager.rs")
|
||||
.file("src/screenshot.rs")
|
||||
.file("src/hause_arrest.rs")
|
||||
.file("src/io_manager.rs")
|
||||
.build();
|
||||
}
|
||||
CxxQtBuilder::new_qml_module(
|
||||
QmlModule::new("com.kdab.cxx_qt.demo").qml_file("../qml/Tabs.qml"),
|
||||
)
|
||||
.qt_module("Qml")
|
||||
.files(["src/lib.rs","src/afc_services.rs","src/afc2_services.rs","src/service_manager.rs","src/screenshot.rs","src/hause_arrest.rs","src/io_manager.rs"])
|
||||
.build();
|
||||
}
|
||||
+2
-2
@@ -79,9 +79,8 @@ where
|
||||
rx.recv().expect("Tokio runtime worker panicked")
|
||||
}
|
||||
|
||||
#[cxx_qt::bridge(namespace = "CXX")]
|
||||
#[cxx_qt::bridge]
|
||||
mod qobject {
|
||||
#[namespace = ""]
|
||||
unsafe extern "C++" {
|
||||
include!("cxx-qt-lib/qstring.h");
|
||||
include!("cxx-qt-lib/qlist.h");
|
||||
@@ -93,6 +92,7 @@ mod qobject {
|
||||
|
||||
extern "RustQt" {
|
||||
#[qobject]
|
||||
#[qml_element]
|
||||
type Core = super::RCore;
|
||||
|
||||
#[qinvokable]
|
||||
|
||||
Reference in New Issue
Block a user