#include "mainwindow.h" #include "./ui_mainwindow.h" #include "customtabwidget.h" #include "detailwindow.h" #include "ifusediskunmountbutton.h" #include "ifusemanager.h" #include "settingswidget.h" #include "appswidget.h" #include "devicemanagerwidget.h" #include "iDescriptor-ui.h" #include "iDescriptor.h" #include "jailbrokenwidget.h" #include "libirecovery.h" #include "toolboxwidget.h" #include "welcomewidget.h" #include #include #include #include #include #include #include "appcontext.h" #include "settingsmanager.h" #include #include #include #include #include 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) { warn("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; } // return; } 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; MainWindow *MainWindow::sharedInstance() { static MainWindow instance; return &instance; } MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); const QSize minSize(900, 600); setMinimumSize(minSize); resize(minSize); // TODO // setWindowIcon(QIcon(":/resources/icons/icon.png")); // Create custom tab widget m_customTabWidget = new CustomTabWidget(this); m_customTabWidget->setAttribute(Qt::WA_ContentsMarginsRespectsSafeArea, false); setContentsMargins(0, 0, 0, 0); #ifdef __APPLE__ setupMacOSWindow(this); setAttribute(Qt::WA_ContentsMarginsRespectsSafeArea, false); #endif setCentralWidget(m_customTabWidget); // Create device manager and stacked widget for main tab m_mainStackedWidget = new QStackedWidget(); // Welcome page (shown when no devices are connected) WelcomeWidget *welcomePage = new WelcomeWidget(this); m_deviceManager = new DeviceManagerWidget(this); m_mainStackedWidget->addWidget(welcomePage); m_mainStackedWidget->addWidget(m_deviceManager); connect(m_deviceManager, &DeviceManagerWidget::updateNoDevicesConnected, this, &MainWindow::updateNoDevicesConnected); // Add tabs with icons QIcon deviceIcon(":/resources/icons/MdiLightningBolt.png"); m_customTabWidget->addTab(m_mainStackedWidget, deviceIcon, "iDevice"); m_customTabWidget->addTab(new AppsWidget(this), "Apps"); m_customTabWidget->addTab(new ToolboxWidget(this), "Toolbox"); auto *jailbrokenWidget = new JailbrokenWidget(this); m_customTabWidget->addTab(jailbrokenWidget, "Jailbroken"); m_customTabWidget->finalizeStyles(); // connect( // m_customTabWidget, &CustomTabWidget::currentChanged, this, // [this, jailbrokenWidget](int index) { // if (index == 3) { // Jailbroken tab // jailbrokenWidget->initWidget(); // } // }, // Qt::SingleShotConnection); // settings button QPushButton *settingsButton = new QPushButton(); settingsButton->setIcon( QIcon(":/resources/icons/MingcuteSettings7Line.png")); settingsButton->setToolTip("Settings"); settingsButton->setFlat(true); settingsButton->setCursor(Qt::PointingHandCursor); settingsButton->setFixedSize(24, 24); connect(settingsButton, &QPushButton::clicked, this, [this]() { SettingsManager::sharedInstance()->showSettingsDialog(); }); m_connectedDeviceCountLabel = new QLabel("iDescriptor: no devices"); m_connectedDeviceCountLabel->setContentsMargins(5, 0, 5, 0); m_connectedDeviceCountLabel->setStyleSheet( "QLabel:hover { background-color : #13131319; }"); ui->statusbar->addWidget(m_connectedDeviceCountLabel); ui->statusbar->setContentsMargins(0, 0, 0, 0); ui->statusbar->addPermanentWidget(settingsButton); #ifdef __linux__ QList mounted_iFusePaths = iFuseManager::getMountPoints(); for (const QString &path : mounted_iFusePaths) { auto *p = new iFuseDiskUnmountButton(path); ui->statusbar->addPermanentWidget(p); connect(p, &iFuseDiskUnmountButton::clicked, this, [this, p, path]() { bool ok = iFuseManager::linuxUnmount(path); if (!ok) { QMessageBox::warning(nullptr, "Unmount Failed", "Failed to unmount iFuse at " + path + ". Please try again."); return; } ui->statusbar->removeWidget(p); p->deleteLater(); }); } #endif irecv_error_t res_recovery = irecv_device_event_subscribe(&context, handleCallbackRecovery, nullptr); if (res_recovery != IRECV_E_SUCCESS) { printf("ERROR: Unable to subscribe to recovery device events.\n"); } idevice_error_t res = idevice_event_subscribe(handleCallback, nullptr); if (res != IDEVICE_E_SUCCESS) { printf("ERROR: Unable to subscribe to device events.\n"); } createMenus(); } void MainWindow::createMenus() { #ifdef Q_OS_MAC QMenu *actionsMenu = menuBar()->addMenu("&Actions"); QAction *aboutAct = new QAction("&About iDescriptor", this); connect(aboutAct, &QAction::triggered, this, [this]() { QMessageBox::about(this, "iDescriptor", "A free and open-source idevice management tool."); }); actionsMenu->addAction(aboutAct); #endif } void MainWindow::updateNoDevicesConnected() { qDebug() << "Is there no devices connected? " << AppContext::sharedInstance()->noDevicesConnected(); if (AppContext::sharedInstance()->noDevicesConnected()) { m_connectedDeviceCountLabel->setText("iDescriptor: no devices"); return m_mainStackedWidget->setCurrentIndex(0); // Show Welcome page } int deviceCount = AppContext::sharedInstance()->getConnectedDeviceCount(); m_connectedDeviceCountLabel->setText( "iDescriptor: " + QString::number(deviceCount) + (deviceCount == 1 ? " device" : " devices") + " connected"); m_mainStackedWidget->setCurrentIndex(1); // Show device list page } MainWindow::~MainWindow() { idevice_event_unsubscribe(); irecv_device_event_unsubscribe(context); delete ui; sleep(2); // Give some time for cleanup to finish }