mirror of
https://github.com/iDescriptor/iDescriptor.git
synced 2026-06-21 19:35:49 +08:00
add tool base widget, fix minor bugs, rename some widgets
This commit is contained in:
@@ -17,7 +17,7 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "airplaywindow.h"
|
||||
#include "airplaywidget.h"
|
||||
#include <QApplication>
|
||||
#include <QCheckBox>
|
||||
#include <QCloseEvent>
|
||||
@@ -137,8 +137,8 @@ AirPlaySettings AirPlaySettingsDialog::getSettings() const
|
||||
return settings;
|
||||
}
|
||||
|
||||
AirPlayWindow::AirPlayWindow(QWidget *parent)
|
||||
: QMainWindow(parent), m_stackedWidget(nullptr), m_tutorialWidget(nullptr),
|
||||
AirPlayWidget::AirPlayWidget(QWidget *parent)
|
||||
: Tool(parent), m_stackedWidget(nullptr), m_tutorialWidget(nullptr),
|
||||
m_streamingWidget(nullptr), m_loadingIndicator(nullptr),
|
||||
m_loadingLabel(nullptr), m_tutorialPlayer(nullptr),
|
||||
m_tutorialVideoWidget(nullptr), m_videoLabel(nullptr),
|
||||
@@ -167,14 +167,14 @@ AirPlayWindow::AirPlayWindow(QWidget *parent)
|
||||
|
||||
DiagnoseDialog *diagnoseDialog = new DiagnoseDialog();
|
||||
diagnoseDialog->show();
|
||||
QTimer::singleShot(0, this, &AirPlayWindow::close);
|
||||
QTimer::singleShot(0, this, &AirPlayWidget::close);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
QTimer::singleShot(500, this, &AirPlayWindow::startAirPlayServer);
|
||||
QTimer::singleShot(500, this, &AirPlayWidget::startAirPlayServer);
|
||||
}
|
||||
|
||||
AirPlayWindow::~AirPlayWindow()
|
||||
AirPlayWidget::~AirPlayWidget()
|
||||
{
|
||||
stopAirPlayServer();
|
||||
#ifdef Q_OS_LINUX
|
||||
@@ -182,13 +182,11 @@ AirPlayWindow::~AirPlayWindow()
|
||||
#endif
|
||||
}
|
||||
|
||||
void AirPlayWindow::setupUI()
|
||||
void AirPlayWidget::setupUI()
|
||||
{
|
||||
setWindowTitle("AirPlay Receiver - iDescriptor");
|
||||
setWindowTitle("AirPlay - iDescriptor");
|
||||
|
||||
// Create stacked widget
|
||||
m_stackedWidget = new QStackedWidget(this);
|
||||
setCentralWidget(m_stackedWidget);
|
||||
|
||||
m_tutorialWidget = new QWidget();
|
||||
m_tutorialLayout = new QVBoxLayout(m_tutorialWidget);
|
||||
@@ -216,14 +214,14 @@ void AirPlayWindow::setupUI()
|
||||
m_settingsButton = new QPushButton("Settings");
|
||||
m_settingsButton->setVisible(false);
|
||||
connect(m_settingsButton, &QPushButton::clicked, this,
|
||||
&AirPlayWindow::showSettingsDialog);
|
||||
&AirPlayWidget::showSettingsDialog);
|
||||
QHBoxLayout *settingsLayout = new QHBoxLayout();
|
||||
settingsLayout->addStretch();
|
||||
settingsLayout->addWidget(m_settingsButton);
|
||||
settingsLayout->addStretch();
|
||||
m_tutorialLayout->addLayout(settingsLayout);
|
||||
|
||||
QTimer::singleShot(100, this, &AirPlayWindow::setupTutorialVideo);
|
||||
QTimer::singleShot(100, this, &AirPlayWidget::setupTutorialVideo);
|
||||
|
||||
m_streamingWidget = new QWidget();
|
||||
QVBoxLayout *streamingLayout = new QVBoxLayout(m_streamingWidget);
|
||||
@@ -250,13 +248,14 @@ void AirPlayWindow::setupUI()
|
||||
|
||||
// Start with tutorial widget
|
||||
m_stackedWidget->setCurrentWidget(m_tutorialWidget);
|
||||
layout()->addWidget(m_stackedWidget);
|
||||
|
||||
#ifdef __linux__
|
||||
m_v4l2_enabled = false; // Disable V4L2 by default
|
||||
#endif
|
||||
}
|
||||
|
||||
void AirPlayWindow::setupTutorialVideo()
|
||||
void AirPlayWidget::setupTutorialVideo()
|
||||
{
|
||||
m_tutorialPlayer = new QMediaPlayer(this);
|
||||
m_tutorialVideoWidget = new QVideoWidget();
|
||||
@@ -289,7 +288,7 @@ void AirPlayWindow::setupTutorialVideo()
|
||||
m_tutorialLayout->addWidget(m_tutorialVideoWidget, 1);
|
||||
}
|
||||
|
||||
void AirPlayWindow::showTutorialView()
|
||||
void AirPlayWidget::showTutorialView()
|
||||
{
|
||||
m_stackedWidget->setCurrentWidget(m_tutorialWidget);
|
||||
if (m_tutorialPlayer) {
|
||||
@@ -298,7 +297,7 @@ void AirPlayWindow::showTutorialView()
|
||||
}
|
||||
}
|
||||
|
||||
void AirPlayWindow::showStreamingView()
|
||||
void AirPlayWidget::showStreamingView()
|
||||
{
|
||||
m_loadingIndicator->stop();
|
||||
m_stackedWidget->setCurrentWidget(m_streamingWidget);
|
||||
@@ -307,7 +306,7 @@ void AirPlayWindow::showStreamingView()
|
||||
}
|
||||
}
|
||||
|
||||
void AirPlayWindow::showSettingsDialog()
|
||||
void AirPlayWidget::showSettingsDialog()
|
||||
{
|
||||
AirPlaySettingsDialog dialog(this);
|
||||
if (dialog.exec() == QDialog::Accepted) {
|
||||
@@ -316,26 +315,26 @@ void AirPlayWindow::showSettingsDialog()
|
||||
// Save settings
|
||||
SettingsManager::sharedInstance()->setAirplayFps(newSettings.fps);
|
||||
SettingsManager::sharedInstance()->setAirplayNoHold(newSettings.noHold);
|
||||
|
||||
|
||||
QMessageBox::information(this, "Settings Saved",
|
||||
"AirPlay will be restarted to apply the new "
|
||||
"settings.");
|
||||
ToolboxWidget::sharedInstance()->restartAirPlayWindow();
|
||||
ToolboxWidget::sharedInstance()->restartAirPlayWidget();
|
||||
}
|
||||
}
|
||||
|
||||
void AirPlayWindow::startAirPlayServer()
|
||||
void AirPlayWidget::startAirPlayServer()
|
||||
{
|
||||
if (m_serverRunning)
|
||||
return;
|
||||
|
||||
m_serverThread = new AirPlayServerThread(this);
|
||||
connect(m_serverThread, &AirPlayServerThread::statusChanged, this,
|
||||
&AirPlayWindow::onServerStatusChanged);
|
||||
&AirPlayWidget::onServerStatusChanged);
|
||||
connect(m_serverThread, &AirPlayServerThread::videoFrameReady, this,
|
||||
&AirPlayWindow::updateVideoFrame);
|
||||
&AirPlayWidget::updateVideoFrame);
|
||||
connect(m_serverThread, &AirPlayServerThread::clientConnectionChanged, this,
|
||||
&AirPlayWindow::onClientConnectionChanged);
|
||||
&AirPlayWidget::onClientConnectionChanged);
|
||||
connect(m_serverThread, &AirPlayServerThread::errorOccurred, this,
|
||||
[this](const QString &message) {
|
||||
QMessageBox::critical(this, "AirPlay Server Error", message);
|
||||
@@ -347,7 +346,7 @@ void AirPlayWindow::startAirPlayServer()
|
||||
m_serverThread->start();
|
||||
}
|
||||
|
||||
void AirPlayWindow::stopAirPlayServer()
|
||||
void AirPlayWidget::stopAirPlayServer()
|
||||
{
|
||||
if (m_serverThread) {
|
||||
m_serverThread->quit();
|
||||
@@ -357,7 +356,7 @@ void AirPlayWindow::stopAirPlayServer()
|
||||
m_serverRunning = false;
|
||||
}
|
||||
|
||||
void AirPlayWindow::updateVideoFrame(QByteArray frameData, int width,
|
||||
void AirPlayWidget::updateVideoFrame(QByteArray frameData, int width,
|
||||
int height)
|
||||
{
|
||||
if (frameData.size() != width * height * 3) {
|
||||
@@ -386,7 +385,7 @@ void AirPlayWindow::updateVideoFrame(QByteArray frameData, int width,
|
||||
m_videoLabel->setPixmap(scaledPixmap);
|
||||
}
|
||||
|
||||
void AirPlayWindow::onServerStatusChanged(bool running)
|
||||
void AirPlayWidget::onServerStatusChanged(bool running)
|
||||
{
|
||||
m_serverRunning = running;
|
||||
|
||||
@@ -420,7 +419,7 @@ void AirPlayWindow::onServerStatusChanged(bool running)
|
||||
}
|
||||
}
|
||||
|
||||
void AirPlayWindow::onClientConnectionChanged(bool connected)
|
||||
void AirPlayWidget::onClientConnectionChanged(bool connected)
|
||||
{
|
||||
m_clientConnected = connected;
|
||||
|
||||
@@ -439,7 +438,7 @@ void AirPlayWindow::onClientConnectionChanged(bool connected)
|
||||
}
|
||||
#ifdef __linux__
|
||||
|
||||
void AirPlayWindow::onV4L2CheckboxToggled(bool enabled)
|
||||
void AirPlayWidget::onV4L2CheckboxToggled(bool enabled)
|
||||
{
|
||||
if (enabled) {
|
||||
// Check if V4L2 loopback exists
|
||||
@@ -566,7 +565,7 @@ void AirPlayServerThread::run()
|
||||
|
||||
#ifdef __linux__
|
||||
// V4L2 Implementation
|
||||
void AirPlayWindow::initV4L2(int width, int height, const char *device)
|
||||
void AirPlayWidget::initV4L2(int width, int height, const char *device)
|
||||
{
|
||||
closeV4L2(); // Close previous device if any
|
||||
|
||||
@@ -598,7 +597,7 @@ void AirPlayWindow::initV4L2(int width, int height, const char *device)
|
||||
qDebug("V4L2 device %s initialized to %dx%d", device, width, height);
|
||||
}
|
||||
|
||||
void AirPlayWindow::closeV4L2()
|
||||
void AirPlayWidget::closeV4L2()
|
||||
{
|
||||
if (m_v4l2_fd >= 0) {
|
||||
::close(m_v4l2_fd);
|
||||
@@ -606,7 +605,7 @@ void AirPlayWindow::closeV4L2()
|
||||
}
|
||||
}
|
||||
|
||||
void AirPlayWindow::writeFrameToV4L2(uint8_t *data, int width, int height)
|
||||
void AirPlayWidget::writeFrameToV4L2(uint8_t *data, int width, int height)
|
||||
{
|
||||
// Check if V4L2 device needs to be initialized or re-initialized
|
||||
if (m_v4l2_fd < 0 || m_v4l2_width != width || m_v4l2_height != height) {
|
||||
@@ -625,7 +624,7 @@ void AirPlayWindow::writeFrameToV4L2(uint8_t *data, int width, int height)
|
||||
}
|
||||
}
|
||||
|
||||
bool AirPlayWindow::checkV4L2LoopbackExists()
|
||||
bool AirPlayWidget::checkV4L2LoopbackExists()
|
||||
{
|
||||
try {
|
||||
QFileInfo videoDevice("/dev/video0");
|
||||
@@ -636,7 +635,7 @@ bool AirPlayWindow::checkV4L2LoopbackExists()
|
||||
}
|
||||
}
|
||||
|
||||
bool AirPlayWindow::createV4L2Loopback()
|
||||
bool AirPlayWidget::createV4L2Loopback()
|
||||
{
|
||||
try {
|
||||
QProcess process;
|
||||
@@ -680,7 +679,7 @@ bool AirPlayWindow::createV4L2Loopback()
|
||||
}
|
||||
}
|
||||
|
||||
void AirPlayWindow::setupV4L2Checkbox()
|
||||
void AirPlayWidget::setupV4L2Checkbox()
|
||||
{
|
||||
if (!SettingsManager::sharedInstance()->showV4L2())
|
||||
return;
|
||||
@@ -692,7 +691,7 @@ void AirPlayWindow::setupV4L2Checkbox()
|
||||
m_v4l2Checkbox->setChecked(false);
|
||||
|
||||
connect(m_v4l2Checkbox, &QCheckBox::toggled, this,
|
||||
&AirPlayWindow::onV4L2CheckboxToggled);
|
||||
&AirPlayWidget::onV4L2CheckboxToggled);
|
||||
|
||||
} catch (...) {
|
||||
qWarning("Exception occurred while setting up V4L2 checkbox");
|
||||
@@ -17,9 +17,10 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef AIRPLAYWINDOW_H
|
||||
#define AIRPLAYWINDOW_H
|
||||
#ifndef AIRPLAYWIDGET_H
|
||||
#define AIRPLAYWIDGET_H
|
||||
|
||||
#include "iDescriptor-ui.h"
|
||||
#include "qprocessindicator.h"
|
||||
#include <QCheckBox>
|
||||
#include <QCloseEvent>
|
||||
@@ -93,13 +94,13 @@ private:
|
||||
AirPlaySettings m_settings;
|
||||
};
|
||||
|
||||
class AirPlayWindow : public QMainWindow
|
||||
class AirPlayWidget : public Tool
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit AirPlayWindow(QWidget *parent = nullptr);
|
||||
~AirPlayWindow();
|
||||
explicit AirPlayWidget(QWidget *parent = nullptr);
|
||||
~AirPlayWidget();
|
||||
|
||||
private slots:
|
||||
void updateVideoFrame(QByteArray frameData, int width, int height);
|
||||
@@ -154,4 +155,4 @@ private:
|
||||
AirPlaySettings m_settings;
|
||||
};
|
||||
|
||||
#endif // AIRPLAYWINDOW_H
|
||||
#endif // AIRPLAYWIDGET_H
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* 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 "tool.h"
|
||||
|
||||
Tool::Tool(QWidget *parent) : QWidget(parent)
|
||||
{
|
||||
#ifdef __APPLE__
|
||||
setupToolFrame(this);
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
#ifndef TOOL_H
|
||||
#define TOOL_H
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
#ifdef __APPLE__
|
||||
#include "../platform/macos/macos.h"
|
||||
#endif
|
||||
|
||||
class Tool : public QWidget
|
||||
{
|
||||
public:
|
||||
explicit Tool(QWidget *parent = nullptr);
|
||||
};
|
||||
|
||||
#endif // TOOL_H
|
||||
@@ -27,7 +27,7 @@
|
||||
#include <QTimer>
|
||||
|
||||
CableInfoWidget::CableInfoWidget(iDescriptorDevice *device, QWidget *parent)
|
||||
: QWidget(parent), m_device(device), m_response(nullptr)
|
||||
: Tool(parent), m_device(device), m_response(nullptr)
|
||||
{
|
||||
setupUI();
|
||||
connect(AppContext::sharedInstance(), &AppContext::deviceRemoved, this,
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#ifndef CABLEINFOWIDGET_H
|
||||
#define CABLEINFOWIDGET_H
|
||||
|
||||
#include "iDescriptor-ui.h"
|
||||
#include "iDescriptor.h"
|
||||
#include "zloadingwidget.h"
|
||||
#include <QGridLayout>
|
||||
@@ -31,7 +32,7 @@
|
||||
#include <QVBoxLayout>
|
||||
#include <QWidget>
|
||||
|
||||
class CableInfoWidget : public QWidget
|
||||
class CableInfoWidget : public Tool
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
|
||||
@@ -51,10 +51,12 @@
|
||||
|
||||
DevDiskImagesWidget::DevDiskImagesWidget(iDescriptorDevice *device,
|
||||
QWidget *parent)
|
||||
: QWidget{parent},
|
||||
: Tool(parent),
|
||||
m_currentDeviceUdid(
|
||||
device != nullptr ? QString::fromStdString(device->udid) : QString())
|
||||
{
|
||||
setMinimumSize(400, 400);
|
||||
resize(800, 600);
|
||||
setupUi();
|
||||
connect(DevDiskManager::sharedInstance(), &DevDiskManager::imageListFetched,
|
||||
this, &DevDiskImagesWidget::onImageListFetched);
|
||||
@@ -204,14 +206,27 @@ void DevDiskImagesWidget::displayImages()
|
||||
|
||||
qDebug() << "Total images:" << allImages.size();
|
||||
|
||||
int itemIndex = 0;
|
||||
|
||||
// Create UI items
|
||||
auto createVersionItem = [&](const ImageInfo &info) {
|
||||
bool isCompatible =
|
||||
(info.compatibility == ImageCompatibility::Compatible ||
|
||||
info.compatibility == ImageCompatibility::MaybeCompatible);
|
||||
auto *itemWidget = new QWidget();
|
||||
itemWidget->setObjectName("itemWidget");
|
||||
auto *itemLayout = new QHBoxLayout(itemWidget);
|
||||
|
||||
// TODO: maybe create a custom widget for this, if we ever need this
|
||||
// elsewhere ?
|
||||
QColor baseColor = QApplication::palette().color(QPalette::Window);
|
||||
QColor bgColor =
|
||||
itemIndex % 2 == 0 ? baseColor.lighter(110) : baseColor;
|
||||
itemWidget->setStyleSheet(
|
||||
QString("QWidget#itemWidget { background-color: %1; }")
|
||||
.arg(bgColor.name()));
|
||||
itemIndex++;
|
||||
|
||||
auto *versionLabel = new QLabel(info.version);
|
||||
if (isCompatible) {
|
||||
if (info.compatibility == ImageCompatibility::Compatible) {
|
||||
@@ -229,20 +244,20 @@ void DevDiskImagesWidget::displayImages()
|
||||
if (hasConnectedDevice) {
|
||||
if (isCompatible) {
|
||||
if (info.isMounted) {
|
||||
auto *mountedLabel = new QLabel("✓ Mounted");
|
||||
auto *mountedLabel = new QLabel("Mounted");
|
||||
mountedLabel->setStyleSheet(
|
||||
"QLabel { color: #1565C0; font-weight: bold; }");
|
||||
itemLayout->addWidget(mountedLabel);
|
||||
} else if (info.compatibility ==
|
||||
ImageCompatibility::MaybeCompatible) {
|
||||
auto *maybeLabel = new QLabel("⚠ Maybe compatible");
|
||||
auto *maybeLabel = new QLabel("Maybe compatible");
|
||||
maybeLabel->setStyleSheet("QLabel { color: #F57C00; "
|
||||
"margin-left: 10px; font-weight: "
|
||||
"bold; }");
|
||||
itemLayout->addWidget(maybeLabel);
|
||||
}
|
||||
} else {
|
||||
auto *incompatLabel = new QLabel("⚠ Not compatible");
|
||||
auto *incompatLabel = new QLabel("Not compatible");
|
||||
incompatLabel->setStyleSheet(
|
||||
"QLabel { color: #D32F2F; margin-left: 10px; font-weight: "
|
||||
"bold; }");
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#ifndef DEVDISKIMAGESWIDGET_H
|
||||
#define DEVDISKIMAGESWIDGET_H
|
||||
|
||||
#include "iDescriptor-ui.h"
|
||||
#include "iDescriptor.h"
|
||||
#include "qprocessindicator.h"
|
||||
#include <QComboBox>
|
||||
@@ -35,7 +36,7 @@
|
||||
#include <QWidget>
|
||||
#include <string>
|
||||
|
||||
class DevDiskImagesWidget : public QWidget
|
||||
class DevDiskImagesWidget : public Tool
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
|
||||
#ifdef __APPLE__
|
||||
#include "diskusagebar.h"
|
||||
#include "platform/macos.h"
|
||||
#include "platform/macos/macos.h"
|
||||
|
||||
#include <QEnterEvent>
|
||||
#include <QHBoxLayout>
|
||||
|
||||
@@ -36,8 +36,10 @@
|
||||
#include <QWheelEvent>
|
||||
#include <QWidget>
|
||||
|
||||
#include "./base/tool.h"
|
||||
|
||||
#ifdef __APPLE__
|
||||
#include "./platform/macos.h"
|
||||
#include "./platform/macos/macos.h"
|
||||
#endif
|
||||
|
||||
#define COLOR_GREEN QColor(0, 180, 0) // Green
|
||||
|
||||
+1
-1
@@ -37,7 +37,7 @@ public:
|
||||
|
||||
protected:
|
||||
void mousePressEvent(QMouseEvent *event) override;
|
||||
void enterEvent(QEnterEvent *event);
|
||||
void enterEvent(QEnterEvent *event) override;
|
||||
void leaveEvent(QEvent *event) override;
|
||||
|
||||
private slots:
|
||||
|
||||
+13
-5
@@ -435,11 +435,19 @@ MainWindow::MainWindow(QWidget *parent)
|
||||
connect(NetworkDeviceManager::sharedInstance(),
|
||||
&NetworkDeviceManager::deviceAdded, this,
|
||||
[this](const NetworkDevice &device) {
|
||||
// return; // FIXME: disable for now
|
||||
if (AppContext::sharedInstance()->getDeviceByMacAddress(
|
||||
device.macAddress)) {
|
||||
qDebug() << "Prefering wired connection on device MAC:"
|
||||
<< device.macAddress;
|
||||
if (auto existingDevice =
|
||||
AppContext::sharedInstance()->getDeviceByMacAddress(
|
||||
device.macAddress)) {
|
||||
if (existingDevice->deviceInfo.isWireless) {
|
||||
qDebug() << "Ignoring wireless device with MAC:"
|
||||
<< device.macAddress
|
||||
<< "as it's already initialized";
|
||||
|
||||
} else {
|
||||
qDebug() << "Prefering wired connection on device MAC:"
|
||||
<< device.macAddress;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
qDebug() << "Trying to add network device with MAC:"
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
*/
|
||||
|
||||
#include "networkdeviceswidget.h"
|
||||
|
||||
#ifdef __linux__
|
||||
#include "core/services/avahi/avahi_service.h"
|
||||
#else
|
||||
@@ -31,11 +30,12 @@
|
||||
#include <QLabel>
|
||||
#include <QPalette>
|
||||
|
||||
NetworkDevicesWidget::NetworkDevicesWidget(QWidget *parent) : QWidget(parent)
|
||||
NetworkDevicesWidget::NetworkDevicesWidget(QWidget *parent) : Tool(parent)
|
||||
{
|
||||
setWindowTitle("Network Devices - iDescriptor");
|
||||
resize(500, 600);
|
||||
setMinimumSize(400, 300);
|
||||
setupUI();
|
||||
|
||||
#ifdef __linux__
|
||||
m_networkProvider = new AvahiService(this);
|
||||
connect(m_networkProvider, &AvahiService::deviceAdded, this,
|
||||
@@ -55,6 +55,7 @@ NetworkDevicesWidget::NetworkDevicesWidget(QWidget *parent) : QWidget(parent)
|
||||
|
||||
// Initial device list update
|
||||
updateDeviceList();
|
||||
setMaximumHeight(sizeHint().height());
|
||||
}
|
||||
|
||||
NetworkDevicesWidget::~NetworkDevicesWidget()
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#include "core/services/dnssd/dnssd_service.h"
|
||||
#endif
|
||||
|
||||
#include "iDescriptor-ui.h"
|
||||
#include <QEvent>
|
||||
#include <QGroupBox>
|
||||
#include <QLabel>
|
||||
@@ -33,7 +34,7 @@
|
||||
#include <QVBoxLayout>
|
||||
#include <QWidget>
|
||||
|
||||
class NetworkDevicesWidget : public QWidget
|
||||
class NetworkDevicesWidget : public Tool
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <QMainWindow>
|
||||
#include <QPoint>
|
||||
#include <QString>
|
||||
@@ -33,4 +34,6 @@ void setupMacOSWindow(QMainWindow *window);
|
||||
|
||||
void showPopoverForBarWidget(QWidget *widget, const UsageInfo &info);
|
||||
|
||||
void hidePopoverForBarWidget();
|
||||
void hidePopoverForBarWidget();
|
||||
|
||||
void setupToolFrame(QWidget *parent);
|
||||
@@ -191,3 +191,100 @@ void showPopoverForBarWidget(QWidget *widget, const UsageInfo &info)
|
||||
s_popover = [popover retain];
|
||||
s_viewController = [viewController retain];
|
||||
}
|
||||
|
||||
// taken from
|
||||
// https://github.com/tauri-apps/tao/blob/3c2b4447aa53151ae96d30a60928d1d71e9bb5fc/src/platform_impl/macos/view.rs#L1154
|
||||
void setTrafficLightInset(NSPoint position, NSWindow *window)
|
||||
{
|
||||
CGFloat x = position.x;
|
||||
CGFloat y = position.y;
|
||||
|
||||
NSButton *closeButton = [window standardWindowButton:NSWindowCloseButton];
|
||||
NSButton *miniaturizeButton =
|
||||
[window standardWindowButton:NSWindowMiniaturizeButton];
|
||||
NSButton *zoomButton = [window standardWindowButton:NSWindowZoomButton];
|
||||
|
||||
NSView *titleBarContainer = closeButton.superview.superview;
|
||||
|
||||
NSRect closeRect = closeButton.frame;
|
||||
CGFloat titleBarFrameHeight = closeRect.size.height + y;
|
||||
NSRect titleBarRect = titleBarContainer.frame;
|
||||
titleBarRect.size.height = titleBarFrameHeight;
|
||||
titleBarRect.origin.y = window.frame.size.height - titleBarFrameHeight;
|
||||
[titleBarContainer setFrame:titleBarRect];
|
||||
|
||||
CGFloat spaceBetween = NSMinX(miniaturizeButton.frame) - NSMinX(closeRect);
|
||||
NSArray<NSButton *> *buttons =
|
||||
@[ closeButton, miniaturizeButton, zoomButton ];
|
||||
|
||||
for (NSUInteger i = 0; i < buttons.count; i++) {
|
||||
NSButton *button = buttons[i];
|
||||
NSRect rect = button.frame;
|
||||
rect.origin.x = x + (i * spaceBetween);
|
||||
[button setFrameOrigin:rect.origin];
|
||||
}
|
||||
}
|
||||
|
||||
void setupToolFrame(QWidget *toolFrame)
|
||||
{
|
||||
if (!toolFrame) {
|
||||
qWarning() << "setupToolFrame: toolFrame is null";
|
||||
return;
|
||||
}
|
||||
|
||||
NSView *nativeView = reinterpret_cast<NSView *>(toolFrame->winId());
|
||||
if (!nativeView) {
|
||||
qWarning() << "setupToolFrame: native view is null";
|
||||
return;
|
||||
}
|
||||
|
||||
NSWindow *window = [nativeView window];
|
||||
if (!window) {
|
||||
qWarning() << "setupToolFrame: native window is null";
|
||||
return;
|
||||
}
|
||||
|
||||
// Doesn't work, need to figure out a better way, we need to remove
|
||||
// fullscreen button NSWindowStyleMask mask = [window styleMask]; mask &=
|
||||
// ~NSWindowStyleMaskClosable; mask &= ~NSWindowStyleMaskMiniaturizable;
|
||||
// mask &= ~NSWindowStyleMaskFullScreen;
|
||||
// [window setStyleMask:mask];
|
||||
|
||||
NSRect windowFrame = [[window contentView] frame];
|
||||
|
||||
// NSEdgeInsets insets = NSEdgeInsetsMake(20, 15, 0, 0);
|
||||
// // macOS 12.0+ uses a single inset point; adjust as needed for your
|
||||
// target if (@available(macOS 12.0, *)) {
|
||||
// [window setTrafficLightInset:NSMakePoint(15, 20)];
|
||||
// } else {
|
||||
// [window setTrafficLightInsets:insets];
|
||||
// }
|
||||
|
||||
// Works but resizing messes up the styles
|
||||
// dispatch_async(dispatch_get_main_queue(), ^{
|
||||
// setTrafficLightInset(NSMakePoint(20, 25), window);
|
||||
// // x = horizontal inset from left, y = extra height added to title bar
|
||||
// setTrafficLightInset(NSMakePoint(35.0, 44.0), window);
|
||||
// });
|
||||
|
||||
NSToolbar *toolbar =
|
||||
[[NSToolbar alloc] initWithIdentifier:@"HiddenInsetToolbar"];
|
||||
toolbar.showsBaselineSeparator =
|
||||
NO; // equivalent to HideToolbarSeparator: true
|
||||
[window setToolbar:toolbar];
|
||||
[window setBackgroundColor:[NSColor colorWithWhite:0.95 alpha:1.0]];
|
||||
// [toolbar setVisible:NO];
|
||||
// todo : is it ok ?
|
||||
[toolbar release];
|
||||
// TODO: theming
|
||||
[window setBackgroundColor:[NSColor colorWithWhite:0.95 alpha:1.0]];
|
||||
|
||||
// NSButton *closeBtn = [window standardWindowButton:NSWindowCloseButton];
|
||||
// if (closeBtn) {
|
||||
// qDebug() << "Hiding close button";
|
||||
// [closeBtn setHidden:YES]; }
|
||||
// // NSButton *miniBtn = [window
|
||||
// standardWindowButton:NSWindowMiniaturizeButton]; if (miniBtn) {
|
||||
// qDebug() << "Hiding minimize button";
|
||||
// [miniBtn setHidden:YES]// ; }
|
||||
}
|
||||
@@ -46,7 +46,7 @@ public:
|
||||
ball_rotate,
|
||||
};
|
||||
|
||||
void paintEvent(QPaintEvent *e);
|
||||
void paintEvent(QPaintEvent *e) override;
|
||||
|
||||
void start();
|
||||
void stop();
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
|
||||
QueryMobileGestaltWidget::QueryMobileGestaltWidget(iDescriptorDevice *device,
|
||||
QWidget *parent)
|
||||
: QWidget(parent), m_device(device)
|
||||
: Tool(parent), m_device(device)
|
||||
{
|
||||
// FIXME: not tested on iOS 17,18 but it's deprecated on iOS 26
|
||||
// i am assuming it won't work
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#ifndef QUERYMOBILEGESTALTWIDGET_H
|
||||
#define QUERYMOBILEGESTALTWIDGET_H
|
||||
|
||||
#include "iDescriptor-ui.h"
|
||||
#include "iDescriptor.h"
|
||||
#include <QCheckBox>
|
||||
#include <QComboBox>
|
||||
@@ -36,7 +37,7 @@
|
||||
#include <QVariant>
|
||||
#include <QWidget>
|
||||
|
||||
class QueryMobileGestaltWidget : public QWidget
|
||||
class QueryMobileGestaltWidget : public Tool
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
|
||||
@@ -58,6 +58,7 @@ void SettingsWidget::setupUI()
|
||||
auto *scrollArea = new QScrollArea();
|
||||
auto *scrollWidget = new QWidget();
|
||||
auto *scrollLayout = new QVBoxLayout(scrollWidget);
|
||||
scrollLayout->setSpacing(35);
|
||||
scrollLayout->setContentsMargins(10, 10, 10, 10);
|
||||
|
||||
// === GENERAL SETTINGS ===
|
||||
|
||||
+15
-28
@@ -18,7 +18,7 @@
|
||||
*/
|
||||
|
||||
#include "toolboxwidget.h"
|
||||
#include "airplaywindow.h"
|
||||
#include "airplaywidget.h"
|
||||
#include "appcontext.h"
|
||||
#include "cableinfowidget.h"
|
||||
#include "devdiskimageswidget.h"
|
||||
@@ -411,17 +411,17 @@ void ToolboxWidget::onToolboxClicked(iDescriptorTool tool, bool requiresDevice)
|
||||
qDebug() << "idevice exists:" << (device != nullptr) << m_uuid.c_str();
|
||||
switch (tool) {
|
||||
case iDescriptorTool::Airplayer: {
|
||||
if (!m_airplayWindow) {
|
||||
m_airplayWindow = new AirPlayWindow();
|
||||
connect(m_airplayWindow, &QObject::destroyed, this,
|
||||
[this]() { m_airplayWindow = nullptr; });
|
||||
m_airplayWindow->setAttribute(Qt::WA_DeleteOnClose);
|
||||
m_airplayWindow->setWindowFlag(Qt::Window);
|
||||
m_airplayWindow->resize(400, 300);
|
||||
m_airplayWindow->show();
|
||||
if (!m_airplayWidget) {
|
||||
m_airplayWidget = new AirPlayWidget();
|
||||
connect(m_airplayWidget, &QObject::destroyed, this,
|
||||
[this]() { m_airplayWidget = nullptr; });
|
||||
m_airplayWidget->setAttribute(Qt::WA_DeleteOnClose);
|
||||
m_airplayWidget->setWindowFlag(Qt::Window);
|
||||
m_airplayWidget->resize(400, 300);
|
||||
m_airplayWidget->show();
|
||||
} else {
|
||||
m_airplayWindow->raise();
|
||||
m_airplayWindow->activateWindow();
|
||||
m_airplayWidget->raise();
|
||||
m_airplayWidget->activateWindow();
|
||||
}
|
||||
} break;
|
||||
|
||||
@@ -462,11 +462,8 @@ void ToolboxWidget::onToolboxClicked(iDescriptorTool tool, bool requiresDevice)
|
||||
devDiskImageHelper->start();
|
||||
} break;
|
||||
case iDescriptorTool::VirtualLocation: {
|
||||
// Handle virtual location functionality
|
||||
VirtualLocation *virtualLocation = new VirtualLocation(device);
|
||||
virtualLocation->setAttribute(Qt::WA_DeleteOnClose);
|
||||
virtualLocation->setWindowFlag(Qt::Window);
|
||||
virtualLocation->resize(800, 600);
|
||||
virtualLocation->show();
|
||||
} break;
|
||||
case iDescriptorTool::Restart: {
|
||||
@@ -476,20 +473,15 @@ void ToolboxWidget::onToolboxClicked(iDescriptorTool tool, bool requiresDevice)
|
||||
shutdownDevice(device);
|
||||
} break;
|
||||
case iDescriptorTool::QueryMobileGestalt: {
|
||||
// Handle querying MobileGestalt
|
||||
QueryMobileGestaltWidget *queryMobileGestaltWidget =
|
||||
new QueryMobileGestaltWidget(device);
|
||||
queryMobileGestaltWidget->setAttribute(Qt::WA_DeleteOnClose);
|
||||
queryMobileGestaltWidget->setWindowFlag(Qt::Window);
|
||||
queryMobileGestaltWidget->resize(800, 600);
|
||||
queryMobileGestaltWidget->show();
|
||||
} break;
|
||||
case iDescriptorTool::DeveloperDiskImages: {
|
||||
if (!m_devDiskImagesWidget) {
|
||||
m_devDiskImagesWidget = new DevDiskImagesWidget(device);
|
||||
m_devDiskImagesWidget->setAttribute(Qt::WA_DeleteOnClose);
|
||||
m_devDiskImagesWidget->setWindowFlag(Qt::Window);
|
||||
m_devDiskImagesWidget->resize(800, 600);
|
||||
connect(m_devDiskImagesWidget, &QObject::destroyed, this,
|
||||
[this]() { m_devDiskImagesWidget = nullptr; });
|
||||
m_devDiskImagesWidget->show();
|
||||
@@ -504,8 +496,6 @@ void ToolboxWidget::onToolboxClicked(iDescriptorTool tool, bool requiresDevice)
|
||||
connect(m_wirelessGalleryImportWidget, &QObject::destroyed, this,
|
||||
[this]() { m_wirelessGalleryImportWidget = nullptr; });
|
||||
m_wirelessGalleryImportWidget->setAttribute(Qt::WA_DeleteOnClose);
|
||||
m_wirelessGalleryImportWidget->setWindowFlag(Qt::Window);
|
||||
// m_wirelessGalleryImportWidget->resize(800, 600);
|
||||
m_wirelessGalleryImportWidget->show();
|
||||
} else {
|
||||
m_wirelessGalleryImportWidget->raise();
|
||||
@@ -533,7 +523,6 @@ void ToolboxWidget::onToolboxClicked(iDescriptorTool tool, bool requiresDevice)
|
||||
case iDescriptorTool::CableInfoWidget: {
|
||||
CableInfoWidget *cableInfoWidget = new CableInfoWidget(device);
|
||||
cableInfoWidget->setAttribute(Qt::WA_DeleteOnClose);
|
||||
cableInfoWidget->setWindowFlag(Qt::Window);
|
||||
cableInfoWidget->resize(600, 400);
|
||||
cableInfoWidget->show();
|
||||
} break;
|
||||
@@ -541,8 +530,6 @@ void ToolboxWidget::onToolboxClicked(iDescriptorTool tool, bool requiresDevice)
|
||||
if (!m_networkDevicesWidget) {
|
||||
m_networkDevicesWidget = new NetworkDevicesWidget();
|
||||
m_networkDevicesWidget->setAttribute(Qt::WA_DeleteOnClose);
|
||||
m_networkDevicesWidget->setWindowFlag(Qt::Window);
|
||||
m_networkDevicesWidget->resize(500, 600);
|
||||
connect(m_networkDevicesWidget, &QObject::destroyed, this,
|
||||
[this]() { m_networkDevicesWidget = nullptr; });
|
||||
m_networkDevicesWidget->show();
|
||||
@@ -647,15 +634,15 @@ void ToolboxWidget::_enterRecoveryMode(iDescriptorDevice *device)
|
||||
// }
|
||||
}
|
||||
|
||||
void ToolboxWidget::restartAirPlayWindow()
|
||||
void ToolboxWidget::restartAirPlayWidget()
|
||||
{
|
||||
if (!m_airplayWindow) {
|
||||
if (!m_airplayWidget) {
|
||||
onToolboxClicked(iDescriptorTool::Airplayer, false);
|
||||
return;
|
||||
}
|
||||
|
||||
connect(
|
||||
m_airplayWindow, &QObject::destroyed, this,
|
||||
m_airplayWidget, &QObject::destroyed, this,
|
||||
[this]() {
|
||||
// give some time for cleanup
|
||||
QTimer::singleShot(100, this, [this]() {
|
||||
@@ -664,5 +651,5 @@ void ToolboxWidget::restartAirPlayWindow()
|
||||
},
|
||||
Qt::SingleShotConnection);
|
||||
|
||||
m_airplayWindow->close();
|
||||
m_airplayWidget->close();
|
||||
}
|
||||
+3
-3
@@ -20,7 +20,7 @@
|
||||
#ifndef TOOLBOXWIDGET_H
|
||||
#define TOOLBOXWIDGET_H
|
||||
|
||||
#include "airplaywindow.h"
|
||||
#include "airplaywidget.h"
|
||||
#include "devdiskimageswidget.h"
|
||||
#include "devicesidebarwidget.h"
|
||||
#include "iDescriptor-ui.h"
|
||||
@@ -48,7 +48,7 @@ public:
|
||||
static void shutdownDevice(iDescriptorDevice *device);
|
||||
static void _enterRecoveryMode(iDescriptorDevice *device);
|
||||
static ToolboxWidget *sharedInstance();
|
||||
void restartAirPlayWindow();
|
||||
void restartAirPlayWidget();
|
||||
private slots:
|
||||
void onDeviceSelectionChanged();
|
||||
void onToolboxClicked(iDescriptorTool tool, bool requiresDevice);
|
||||
@@ -71,7 +71,7 @@ private:
|
||||
std::string m_uuid;
|
||||
DevDiskImagesWidget *m_devDiskImagesWidget = nullptr;
|
||||
NetworkDevicesWidget *m_networkDevicesWidget = nullptr;
|
||||
AirPlayWindow *m_airplayWindow = nullptr;
|
||||
AirPlayWidget *m_airplayWidget = nullptr;
|
||||
#ifndef __APPLE__
|
||||
iFuseWidget *m_ifuseWidget = nullptr;
|
||||
#endif
|
||||
|
||||
@@ -42,11 +42,15 @@
|
||||
#include <QUrl>
|
||||
#include <QVBoxLayout>
|
||||
#include <QWidget>
|
||||
|
||||
// FIXME: on macOS setupToolFrame in Tool widget does nothing
|
||||
// probably because we are using a QQuickWidget
|
||||
VirtualLocation::VirtualLocation(iDescriptorDevice *device, QWidget *parent)
|
||||
: QWidget{parent}, m_device(device)
|
||||
: Tool(parent), m_device(device)
|
||||
{
|
||||
setWindowTitle("Virtual Location - iDescriptor");
|
||||
setMinimumSize(600, 400);
|
||||
resize(800, 600);
|
||||
|
||||
// Create the main layout
|
||||
QHBoxLayout *mainLayout = new QHBoxLayout(this);
|
||||
mainLayout->setContentsMargins(10, 10, 10, 10);
|
||||
@@ -414,7 +418,7 @@ void VirtualLocation::onApplyClicked()
|
||||
if (err->code == ServiceNotFoundErrorCode) {
|
||||
auto res = QMessageBox::question(
|
||||
this, "Enable Developer Mode?",
|
||||
"Location Simulation service not found. Enable Developer "
|
||||
"Location Simulation service is not found. Enable Developer "
|
||||
"Mode on the device?",
|
||||
QMessageBox::Yes | QMessageBox::No);
|
||||
if (res == QMessageBox::Yes) {
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#define VIRTUAL_LOCATION_H
|
||||
|
||||
#include "devdiskimagehelper.h"
|
||||
#include "iDescriptor-ui.h"
|
||||
#include "iDescriptor.h"
|
||||
#include <QGroupBox>
|
||||
#include <QLineEdit>
|
||||
@@ -30,7 +31,7 @@
|
||||
#include <QVBoxLayout>
|
||||
#include <QWidget>
|
||||
|
||||
class VirtualLocation : public QWidget
|
||||
class VirtualLocation : public Tool
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
#include <QTimer>
|
||||
|
||||
WirelessGalleryImportWidget::WirelessGalleryImportWidget(QWidget *parent)
|
||||
: QWidget(parent), m_scrollArea(nullptr), m_scrollContent(nullptr),
|
||||
: Tool(parent), m_scrollArea(nullptr), m_scrollContent(nullptr),
|
||||
m_fileListLayout(nullptr), m_browseButton(nullptr),
|
||||
m_importButton(nullptr), m_statusLabel(nullptr)
|
||||
{
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#ifndef WIRELESSGALLERYIMPORTWIDGET_H
|
||||
#define WIRELESSGALLERYIMPORTWIDGET_H
|
||||
|
||||
#include "iDescriptor-ui.h"
|
||||
#include "qprocessindicator.h"
|
||||
#include <QHBoxLayout>
|
||||
#include <QLabel>
|
||||
@@ -32,7 +33,7 @@
|
||||
#include <QVideoWidget>
|
||||
#include <QWidget>
|
||||
|
||||
class WirelessGalleryImportWidget : public QWidget
|
||||
class WirelessGalleryImportWidget : public Tool
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
|
||||
Reference in New Issue
Block a user