mirror of
https://github.com/iDescriptor/iDescriptor.git
synced 2026-06-22 03:45:51 +08:00
add toolbox network devices & enhance UI with new icons
- Added new icons to resources.qrc for improved UI representation. - Implemented ZIconWidget for buttons in AfcExplorerWidget, replacing ClickableIconWidget. - Introduced NetworkDevicesWidget for discovering and monitoring network devices. - Updated AppInstallDialog to use QTemporaryDir for better temporary directory management. - Enhanced FileExportDialog to prompt user for opening the export directory upon completion. - Refactored styles in various widgets for consistency and improved theming support. - Cleaned up unused code and comments across multiple files.
This commit is contained in:
+64
-42
@@ -218,7 +218,8 @@ void AfcExplorerWidget::onFileListContextMenu(const QPoint &pos)
|
||||
|
||||
bool isDir = item->data(Qt::UserRole).toBool();
|
||||
if (isDir)
|
||||
return; // Only export files
|
||||
return; // TODO: Implement directory export later - Only export files
|
||||
// for now
|
||||
|
||||
QMenu menu;
|
||||
QAction *exportAction = menu.addAction("Export");
|
||||
@@ -253,7 +254,7 @@ void AfcExplorerWidget::onExportClicked()
|
||||
if (selectedItems.isEmpty())
|
||||
return;
|
||||
|
||||
// Only files (not directories)
|
||||
// Only files (not directories) - TODO: Implement directory export later
|
||||
QList<QListWidgetItem *> filesToExport;
|
||||
for (QListWidgetItem *item : selectedItems) {
|
||||
if (!item->data(Qt::UserRole).toBool())
|
||||
@@ -320,7 +321,11 @@ void AfcExplorerWidget::exportSelectedFile(QListWidgetItem *item,
|
||||
}
|
||||
}
|
||||
|
||||
// TODO : abstract to services
|
||||
/*
|
||||
FIXME : abstract to services
|
||||
even though we are using safe wrappers,
|
||||
we better move this to services
|
||||
*/
|
||||
int AfcExplorerWidget::export_file_to_path(afc_client_t afc,
|
||||
const char *device_path,
|
||||
const char *local_path)
|
||||
@@ -348,32 +353,23 @@ int AfcExplorerWidget::export_file_to_path(afc_client_t afc,
|
||||
}
|
||||
|
||||
fclose(out);
|
||||
afc_file_close(afc, handle);
|
||||
ServiceManager::safeAfcFileClose(m_device, handle);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// should be disabled if there is an error loading afc
|
||||
void AfcExplorerWidget::onImportClicked()
|
||||
{
|
||||
// TODO: check devices
|
||||
|
||||
// Select one or more files to import
|
||||
QStringList fileNames = QFileDialog::getOpenFileNames(this, "Import Files");
|
||||
if (fileNames.isEmpty())
|
||||
return;
|
||||
|
||||
// Use current breadcrumb directory as target
|
||||
QString currPath = "/";
|
||||
if (!m_history.isEmpty())
|
||||
currPath = m_history.top();
|
||||
if (!currPath.endsWith("/"))
|
||||
currPath += "/";
|
||||
|
||||
// if (!device || !client || !serviceDesc)
|
||||
// {
|
||||
// qDebug() << "Failed to connect to device or lockdown service";
|
||||
// return;
|
||||
// }
|
||||
|
||||
// Import each file
|
||||
for (const QString &localPath : fileNames) {
|
||||
QFileInfo fi(localPath);
|
||||
@@ -437,16 +433,13 @@ void AfcExplorerWidget::setupFileExplorer()
|
||||
m_explorer->setStyleSheet("border : none;");
|
||||
|
||||
// Export/Import buttons layout
|
||||
QHBoxLayout *exportLayout = new QHBoxLayout();
|
||||
m_exportBtn = new QPushButton("Export");
|
||||
m_importBtn = new QPushButton("Import");
|
||||
m_addToFavoritesBtn = new QPushButton("Add to Favorites");
|
||||
exportLayout->addWidget(m_exportBtn);
|
||||
exportLayout->addWidget(m_importBtn);
|
||||
exportLayout->addWidget(m_addToFavoritesBtn);
|
||||
exportLayout->setContentsMargins(0, 0, 0, 0);
|
||||
exportLayout->addStretch();
|
||||
explorerLayout->addLayout(exportLayout);
|
||||
m_exportBtn =
|
||||
new ZIconWidget(QIcon(":/resources/icons/PhExport.png"), "Export");
|
||||
m_importBtn = new ZIconWidget(
|
||||
QIcon(":/resources/icons/LetsIconsImport.png"), "Import");
|
||||
m_addToFavoritesBtn =
|
||||
new ZIconWidget(QIcon(":/resources/icons/MaterialSymbolsFavorite.png"),
|
||||
"Add to Favorites");
|
||||
|
||||
// Navigation layout (Address Bar with embedded icons)
|
||||
m_navWidget = new QWidget();
|
||||
@@ -474,17 +467,19 @@ void AfcExplorerWidget::setupFileExplorer()
|
||||
// red;");
|
||||
leftNavLayout->setContentsMargins(0, 0, 0, 0);
|
||||
leftNavLayout->setSpacing(1);
|
||||
|
||||
m_backButton = new ClickableIconWidget(
|
||||
QIcon::fromTheme("go-previous", QIcon("←")), "Go Back");
|
||||
// rename to ziconwidget
|
||||
m_backButton = new ZIconWidget(
|
||||
QIcon(":/resources/icons/MaterialSymbolsArrowLeftAlt.png"), "Go Back");
|
||||
m_backButton->setEnabled(false);
|
||||
|
||||
m_forwardButton = new ClickableIconWidget(
|
||||
QIcon::fromTheme("go-next", QIcon("→")), "Go Forward");
|
||||
m_forwardButton = new ZIconWidget(
|
||||
QIcon(":/resources/icons/MaterialSymbolsArrowRightAlt.png"),
|
||||
"Go Forward");
|
||||
m_forwardButton->setEnabled(false);
|
||||
|
||||
m_enterButton = new ClickableIconWidget(
|
||||
QIcon::fromTheme("go-jump", QIcon("⏎")), "Navigate to path");
|
||||
m_enterButton = new ZIconWidget(
|
||||
QIcon(":/resources/icons/MaterialSymbolsLightKeyboardReturn.png"),
|
||||
"Navigate to path");
|
||||
|
||||
m_addressBar = new QLineEdit();
|
||||
m_addressBar->setPlaceholderText("Enter path...");
|
||||
@@ -495,6 +490,9 @@ void AfcExplorerWidget::setupFileExplorer()
|
||||
leftNavLayout->addWidget(m_forwardButton);
|
||||
navLayout->addWidget(explorerLeftSideNavButtons);
|
||||
navLayout->addWidget(m_addressBar);
|
||||
navLayout->addWidget(m_importBtn);
|
||||
navLayout->addWidget(m_exportBtn);
|
||||
navLayout->addWidget(m_addToFavoritesBtn);
|
||||
navLayout->addWidget(m_enterButton);
|
||||
|
||||
// Add the container layout (which centers navWidget) to the main layout
|
||||
@@ -515,24 +513,28 @@ void AfcExplorerWidget::setupFileExplorer()
|
||||
explorerLayout->addWidget(m_fileList);
|
||||
|
||||
// Connect buttons and actions
|
||||
connect(m_backButton, &ClickableIconWidget::clicked, this,
|
||||
connect(m_backButton, &ZIconWidget::clicked, this,
|
||||
&AfcExplorerWidget::goBack);
|
||||
connect(m_forwardButton, &ClickableIconWidget::clicked, this,
|
||||
connect(m_forwardButton, &ZIconWidget::clicked, this,
|
||||
&AfcExplorerWidget::goForward);
|
||||
connect(m_enterButton, &ClickableIconWidget::clicked, this,
|
||||
connect(m_enterButton, &ZIconWidget::clicked, this,
|
||||
&AfcExplorerWidget::onAddressBarReturnPressed);
|
||||
connect(m_addressBar, &QLineEdit::returnPressed, this,
|
||||
&AfcExplorerWidget::onAddressBarReturnPressed);
|
||||
connect(m_fileList, &QListWidget::itemDoubleClicked, this,
|
||||
&AfcExplorerWidget::onItemDoubleClicked);
|
||||
connect(m_exportBtn, &QPushButton::clicked, this,
|
||||
connect(m_exportBtn, &ZIconWidget::clicked, this,
|
||||
&AfcExplorerWidget::onExportClicked);
|
||||
connect(m_importBtn, &QPushButton::clicked, this,
|
||||
connect(m_importBtn, &ZIconWidget::clicked, this,
|
||||
&AfcExplorerWidget::onImportClicked);
|
||||
connect(m_addToFavoritesBtn, &QPushButton::clicked, this,
|
||||
connect(m_addToFavoritesBtn, &ZIconWidget::clicked, this,
|
||||
&AfcExplorerWidget::onAddToFavoritesClicked);
|
||||
connect(m_fileList->selectionModel(),
|
||||
&QItemSelectionModel::selectionChanged, this,
|
||||
&AfcExplorerWidget::updateButtonStates);
|
||||
|
||||
updateNavigationButtons();
|
||||
updateButtonStates(); // Initialize button states
|
||||
updateNavStyles();
|
||||
}
|
||||
|
||||
@@ -562,8 +564,10 @@ void AfcExplorerWidget::saveFavoritePlace(const QString &path,
|
||||
|
||||
void AfcExplorerWidget::updateNavStyles()
|
||||
{
|
||||
QColor bgColor = isDarkMode() ? qApp->palette().color(QPalette::Light)
|
||||
: qApp->palette().color(QPalette::Dark);
|
||||
bool isDark = isDarkMode();
|
||||
QColor lightColor = qApp->palette().color(QPalette::Light);
|
||||
QColor darkColor = qApp->palette().color(QPalette::Dark);
|
||||
QColor bgColor = isDark ? lightColor : darkColor;
|
||||
QColor borderColor = qApp->palette().color(QPalette::Mid);
|
||||
QColor accentColor = qApp->palette().color(QPalette::Highlight);
|
||||
|
||||
@@ -585,9 +589,27 @@ void AfcExplorerWidget::updateNavStyles()
|
||||
// Update address bar styles to complement the nav widget
|
||||
QString addressBarStyles =
|
||||
QString("QLineEdit { background-color: %1; border-radius: 10px; "
|
||||
"border: 1px solid %2; }")
|
||||
.arg(bgColor.name())
|
||||
.arg(borderColor.lighter().name());
|
||||
"border: 1px solid %2; padding: 2px 4px; color: %3; }"
|
||||
"QLineEdit:focus {border: 3px solid %4; }")
|
||||
.arg(isDark ? QColor(Qt::white).name() : QColor(Qt::black).name())
|
||||
.arg(borderColor.lighter().name())
|
||||
.arg(isDark ? QColor(Qt::black).name() : QColor(Qt::white).name())
|
||||
.arg(COLOR_ACCENT_BLUE.name());
|
||||
|
||||
m_addressBar->setStyleSheet(addressBarStyles);
|
||||
}
|
||||
|
||||
void AfcExplorerWidget::updateButtonStates()
|
||||
{
|
||||
QList<QListWidgetItem *> selectedItems = m_fileList->selectedItems();
|
||||
|
||||
// Export is only enabled if non-directory items are selected
|
||||
bool hasExportableFiles = false;
|
||||
for (QListWidgetItem *item : selectedItems) {
|
||||
if (!item->data(Qt::UserRole).toBool()) { // Not a directory
|
||||
hasExportableFiles = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
m_exportBtn->setEnabled(hasExportableFiles);
|
||||
}
|
||||
@@ -43,17 +43,17 @@ private slots:
|
||||
private:
|
||||
QWidget *m_explorer;
|
||||
QWidget *m_navWidget;
|
||||
QPushButton *m_exportBtn;
|
||||
QPushButton *m_importBtn;
|
||||
QPushButton *m_addToFavoritesBtn;
|
||||
ZIconWidget *m_exportBtn;
|
||||
ZIconWidget *m_importBtn;
|
||||
ZIconWidget *m_addToFavoritesBtn;
|
||||
QListWidget *m_fileList;
|
||||
QStack<QString> m_history;
|
||||
QStack<QString> m_forwardHistory;
|
||||
int m_currentHistoryIndex;
|
||||
QLineEdit *m_addressBar;
|
||||
ClickableIconWidget *m_backButton;
|
||||
ClickableIconWidget *m_forwardButton;
|
||||
ClickableIconWidget *m_enterButton;
|
||||
ZIconWidget *m_backButton;
|
||||
ZIconWidget *m_forwardButton;
|
||||
ZIconWidget *m_enterButton;
|
||||
iDescriptorDevice *m_device;
|
||||
|
||||
// Current AFC mode
|
||||
@@ -73,6 +73,7 @@ private:
|
||||
int import_file_to_device(afc_client_t afc, const char *device_path,
|
||||
const char *local_path);
|
||||
void updateNavStyles();
|
||||
void updateButtonStates();
|
||||
};
|
||||
|
||||
#endif // AFCEXPLORER_H
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include <QLabel>
|
||||
#include <QMessageBox>
|
||||
#include <QPushButton>
|
||||
#include <QTemporaryDir>
|
||||
#include <QVBoxLayout>
|
||||
#include <QtConcurrent/QtConcurrent>
|
||||
|
||||
@@ -170,8 +171,23 @@ void AppInstallDialog::onInstallClicked()
|
||||
m_actionButton->deleteLater();
|
||||
m_actionButton = nullptr;
|
||||
|
||||
m_tempDir = QDir::tempPath();
|
||||
startDownloadProcess(m_bundleId, m_tempDir, buttonIndex, false);
|
||||
if (m_tempDir) {
|
||||
delete m_tempDir;
|
||||
m_tempDir = nullptr;
|
||||
}
|
||||
// Create a new temporary directory for each installation
|
||||
m_tempDir = new QTemporaryDir();
|
||||
if (!m_tempDir->isValid()) {
|
||||
m_statusLabel->setText("Failed to create temporary directory");
|
||||
m_statusLabel->setStyleSheet(
|
||||
"font-size: 14px; color: #FF3B30; padding: 5px;");
|
||||
QMessageBox::critical(
|
||||
this, "Error",
|
||||
"Could not create temporary directory for download.");
|
||||
return;
|
||||
}
|
||||
|
||||
startDownloadProcess(m_bundleId, m_tempDir->path(), buttonIndex, false);
|
||||
connect(this, &AppDownloadBaseDialog::downloadFinished, this,
|
||||
[this, selectedDevice](bool success) {
|
||||
if (success) {
|
||||
@@ -182,7 +198,7 @@ void AppInstallDialog::onInstallClicked()
|
||||
it.
|
||||
*/
|
||||
// Find the actual downloaded IPA file
|
||||
QDir outDir = m_tempDir;
|
||||
QDir outDir(m_tempDir->path());
|
||||
QStringList filters;
|
||||
filters << m_bundleId + "*.ipa";
|
||||
QStringList matches =
|
||||
@@ -226,3 +242,11 @@ void AppInstallDialog::reject()
|
||||
|
||||
AppDownloadBaseDialog::reject();
|
||||
}
|
||||
|
||||
AppInstallDialog::~AppInstallDialog()
|
||||
{
|
||||
if (m_tempDir) {
|
||||
delete m_tempDir;
|
||||
m_tempDir = nullptr;
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,7 @@
|
||||
#include <QDialog>
|
||||
#include <QFutureWatcher>
|
||||
#include <QLabel>
|
||||
#include <QTemporaryDir>
|
||||
|
||||
class AppInstallDialog : public AppDownloadBaseDialog
|
||||
{
|
||||
@@ -15,6 +16,7 @@ public:
|
||||
const QString &description,
|
||||
const QString &bundleId,
|
||||
QWidget *parent = nullptr);
|
||||
~AppInstallDialog();
|
||||
|
||||
protected:
|
||||
void reject() override;
|
||||
@@ -27,7 +29,7 @@ private:
|
||||
QString m_bundleId;
|
||||
QLabel *m_statusLabel;
|
||||
QFutureWatcher<int> *m_installWatcher;
|
||||
QString m_tempDir;
|
||||
QTemporaryDir *m_tempDir;
|
||||
void updateDeviceList();
|
||||
void performInstallation(const QString &ipaPath, const QString &deviceUdid);
|
||||
};
|
||||
|
||||
+5
-11
@@ -61,13 +61,7 @@ void AppsWidget::setupUI()
|
||||
|
||||
m_loginButton = new QPushButton();
|
||||
m_searchEdit = new ZLineEdit();
|
||||
m_searchEdit->setMaximumWidth(400);
|
||||
m_searchEdit->setStyleSheet("QLineEdit { "
|
||||
" padding: 8px; "
|
||||
" border: 1px solid #ccc; "
|
||||
" border-radius: 4px; "
|
||||
" font-size: 14px; "
|
||||
"}");
|
||||
m_searchEdit->setMaximumWidth(350);
|
||||
|
||||
// --- Status and Login Button ---
|
||||
m_manager = AppStoreManager::sharedInstance();
|
||||
@@ -86,10 +80,10 @@ void AppsWidget::setupUI()
|
||||
m_statusLabel->setStyleSheet("font-size: 14px; color: #666;");
|
||||
|
||||
mainLayout->addWidget(headerWidget);
|
||||
|
||||
QAction *searchAction = m_searchEdit->addAction(
|
||||
this->style()->standardIcon(QStyle::SP_FileDialogContentsView),
|
||||
QLineEdit::TrailingPosition);
|
||||
// todo: implement theme aware icon
|
||||
QAction *searchAction =
|
||||
m_searchEdit->addAction(QIcon(":/resources/icons/MdiLightMagnify.png"),
|
||||
QLineEdit::TrailingPosition);
|
||||
searchAction->setToolTip("Search");
|
||||
connect(searchAction, &QAction::triggered, this,
|
||||
&AppsWidget::performSearch);
|
||||
|
||||
@@ -128,7 +128,6 @@ void AvahiService::browseCallback(AvahiServiceBrowser *browser,
|
||||
|
||||
switch (event) {
|
||||
case AVAHI_BROWSER_NEW:
|
||||
qDebug() << "Found Apple device:" << name;
|
||||
if (!avahi_service_resolver_new(service->m_client, interface, protocol,
|
||||
name, type, domain, AVAHI_PROTO_UNSPEC,
|
||||
(AvahiLookupFlags)0, resolveCallback,
|
||||
|
||||
@@ -100,8 +100,6 @@ void DNSSD_API DnssdService::browseCallback(
|
||||
DnssdService *service = static_cast<DnssdService *>(context);
|
||||
|
||||
if (flags & kDNSServiceFlagsAdd) {
|
||||
qDebug() << "Found Apple device:" << serviceName;
|
||||
|
||||
// Start resolving the service
|
||||
DNSServiceRef resolveRef;
|
||||
DNSServiceErrorType err =
|
||||
|
||||
@@ -157,7 +157,7 @@ int DeviceImageWidget::getIosVersionFromDevice() const
|
||||
/*
|
||||
this method is only here to calculate the screen area
|
||||
so that wallpaper perfectly fits to the screen size
|
||||
it's costy so if you want to add a new mock run
|
||||
it's costy so if you want to add a new mockup run
|
||||
through this method qDebug the result and add it to createCompositeImage
|
||||
example : screenRect = QRect(152, 79, 195, 296);
|
||||
*/
|
||||
@@ -204,12 +204,7 @@ QRect DeviceImageWidget::findScreenArea(const QPixmap &mockup) const
|
||||
bottom++;
|
||||
}
|
||||
|
||||
// Add a small margin to avoid drawing over the bezel anti-aliasing
|
||||
int margin = 2;
|
||||
|
||||
return QRect(left + 1 + margin, top + 1 + margin,
|
||||
right - left - 2 - (margin * 2),
|
||||
bottom - top - 2 - (margin * 2));
|
||||
return QRect(left + 1, top + 1, right - left - 2, bottom - top - 2);
|
||||
}
|
||||
|
||||
QPixmap DeviceImageWidget::createCompositeImage() const
|
||||
@@ -239,19 +234,19 @@ QPixmap DeviceImageWidget::createCompositeImage() const
|
||||
QString::fromStdString(m_device->deviceInfo.productType));
|
||||
|
||||
if (mockupName == "3") {
|
||||
screenRect = QRect(152, 79, 195, 296);
|
||||
screenRect = QRect(145, 72, 209, 310);
|
||||
} else if (mockupName == "4") {
|
||||
screenRect = QRect(421, 188, 366, 534);
|
||||
screenRect = QRect(414, 181, 380, 548);
|
||||
} else if (mockupName == "5") {
|
||||
screenRect = QRect(34, 113, 290, 523);
|
||||
screenRect = QRect(27, 106, 304, 537);
|
||||
} else if (mockupName == "6") {
|
||||
screenRect = QRect(75, 355, 1265, 2256);
|
||||
screenRect = QRect(68, 348, 1279, 2270);
|
||||
} else if (mockupName == "x") {
|
||||
screenRect = QRect(252, 436, 2375, 4989);
|
||||
screenRect = QRect(245, 429, 2389, 5003);
|
||||
} else if (mockupName == "15") {
|
||||
screenRect = QRect(22, 56, 323, 674);
|
||||
screenRect = QRect(15, 49, 337, 688);
|
||||
} else if (mockupName == "16") {
|
||||
screenRect = QRect(24, 61, 319, 668);
|
||||
screenRect = QRect(17, 54, 333, 682);
|
||||
} else {
|
||||
// Fallback for unknown devices
|
||||
screenRect = QRect(mockup.width() * 0.12, mockup.height() * 0.08,
|
||||
|
||||
@@ -54,23 +54,23 @@ DeviceInfoWidget::DeviceInfoWidget(iDescriptorDevice *device, QWidget *parent)
|
||||
actionsLayout->setContentsMargins(1, 1, 1, 1);
|
||||
actionsLayout->setSpacing(10);
|
||||
|
||||
ClickableIconWidget *shutdownBtn = new ClickableIconWidget(
|
||||
ZIconWidget *shutdownBtn = new ZIconWidget(
|
||||
QIcon(":/resources/icons/IcOutlinePowerSettingsNew.png"), "Shutdown",
|
||||
this);
|
||||
shutdownBtn->setIconSize(QSize(20, 20));
|
||||
connect(shutdownBtn, &ClickableIconWidget::clicked, this,
|
||||
connect(shutdownBtn, &ZIconWidget::clicked, this,
|
||||
[device]() { ToolboxWidget::shutdownDevice(device); });
|
||||
|
||||
ClickableIconWidget *restartBtn = new ClickableIconWidget(
|
||||
ZIconWidget *restartBtn = new ZIconWidget(
|
||||
QIcon(":/resources/icons/IcTwotoneRestartAlt.png"), "Restart", this);
|
||||
restartBtn->setIconSize(QSize(20, 20));
|
||||
connect(restartBtn, &ClickableIconWidget::clicked, this,
|
||||
connect(restartBtn, &ZIconWidget::clicked, this,
|
||||
[device]() { ToolboxWidget::restartDevice(device); });
|
||||
|
||||
ClickableIconWidget *recoveryBtn = new ClickableIconWidget(
|
||||
ZIconWidget *recoveryBtn = new ZIconWidget(
|
||||
QIcon(":/resources/icons/HugeiconsWrench01.png"), "Recovery", this);
|
||||
recoveryBtn->setIconSize(QSize(20, 20));
|
||||
connect(recoveryBtn, &ClickableIconWidget::clicked, this,
|
||||
connect(recoveryBtn, &ZIconWidget::clicked, this,
|
||||
[device]() { ToolboxWidget::_enterRecoveryMode(device); });
|
||||
|
||||
actionsLayout->addWidget(shutdownBtn);
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "fileexportdialog.h"
|
||||
#include <QApplication>
|
||||
#include <QDesktopServices>
|
||||
#include <QHBoxLayout>
|
||||
#include <QLabel>
|
||||
#include <QMessageBox>
|
||||
@@ -8,9 +9,10 @@
|
||||
#include <QVBoxLayout>
|
||||
|
||||
// TODO: needs progress bar improvements
|
||||
FileExportDialog::FileExportDialog(QWidget *parent)
|
||||
FileExportDialog::FileExportDialog(const QString &exportDir, QWidget *parent)
|
||||
: QDialog(parent), m_progressBar(nullptr), m_statusLabel(nullptr),
|
||||
m_fileLabel(nullptr), m_cancelButton(nullptr), m_layout(nullptr)
|
||||
m_fileLabel(nullptr), m_cancelButton(nullptr), m_layout(nullptr),
|
||||
m_exportDir(exportDir)
|
||||
{
|
||||
setupUI();
|
||||
}
|
||||
@@ -136,9 +138,17 @@ void FileExportDialog::showCompletionMessage(int successful, int failed)
|
||||
QString message;
|
||||
|
||||
if (failed == 0) {
|
||||
message =
|
||||
QString("Successfully exported all %1 files!").arg(successful);
|
||||
QMessageBox::information(parentWidget(), "Export Complete", message);
|
||||
// ASK USER TO OPEN FOLDER
|
||||
QMessageBox::StandardButton reply;
|
||||
reply = QMessageBox::question(
|
||||
parentWidget(), "Export Complete",
|
||||
QString("Successfully exported all %1 files! Would you like to "
|
||||
"open the output folder ?")
|
||||
.arg(successful),
|
||||
QMessageBox::Yes | QMessageBox::No);
|
||||
if (reply == QMessageBox::Yes) {
|
||||
QDesktopServices::openUrl(QUrl::fromLocalFile(m_exportDir));
|
||||
}
|
||||
} else {
|
||||
message =
|
||||
QString("Export completed with %1 successful and %2 failed files.")
|
||||
|
||||
@@ -15,7 +15,8 @@ class FileExportDialog : public QDialog
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit FileExportDialog(QWidget *parent = nullptr);
|
||||
explicit FileExportDialog(const QString &exportDir,
|
||||
QWidget *parent = nullptr);
|
||||
~FileExportDialog() override;
|
||||
|
||||
public slots:
|
||||
@@ -38,6 +39,7 @@ private:
|
||||
QLabel *m_fileLabel;
|
||||
QPushButton *m_cancelButton;
|
||||
QVBoxLayout *m_layout;
|
||||
QString m_exportDir;
|
||||
};
|
||||
|
||||
#endif // FILEEXPORTDIALOG_H
|
||||
@@ -4,6 +4,7 @@
|
||||
#include "mediapreviewdialog.h"
|
||||
#include "photoexportmanager.h"
|
||||
#include "photomodel.h"
|
||||
#include "servicemanager.h"
|
||||
#include <QComboBox>
|
||||
#include <QDebug>
|
||||
#include <QFileDialog>
|
||||
@@ -19,7 +20,6 @@
|
||||
#include <QStandardPaths>
|
||||
#include <QVBoxLayout>
|
||||
#include <QtConcurrent/QtConcurrent>
|
||||
#include "servicemanager.h"
|
||||
|
||||
void GalleryWidget::load()
|
||||
{
|
||||
@@ -209,7 +209,7 @@ void GalleryWidget::onExportSelected()
|
||||
|
||||
// Create export dialog and connect signals
|
||||
// todo:cleanup
|
||||
auto *exportDialog = new FileExportDialog(this);
|
||||
auto *exportDialog = new FileExportDialog(exportDir, this);
|
||||
|
||||
// Connect PhotoExportManager signals to FileExportDialog
|
||||
connect(m_exportManager, &PhotoExportManager::exportStarted, exportDialog,
|
||||
@@ -267,7 +267,7 @@ void GalleryWidget::onExportAll()
|
||||
|
||||
// Create export dialog and connect signals
|
||||
// todo:cleanup
|
||||
auto *exportDialog = new FileExportDialog(this);
|
||||
auto *exportDialog = new FileExportDialog(exportDir, this);
|
||||
|
||||
// Connect PhotoExportManager signals to FileExportDialog
|
||||
connect(m_exportManager, &PhotoExportManager::exportStarted, exportDialog,
|
||||
@@ -399,8 +399,7 @@ void GalleryWidget::loadAlbumList()
|
||||
{
|
||||
// Get DCIM directory contents
|
||||
qDebug() << "Loading album list from /DCIM";
|
||||
AFCFileTree dcimTree =
|
||||
ServiceManager::safeGetFileTree(m_device, "/DCIM");
|
||||
AFCFileTree dcimTree = ServiceManager::safeGetFileTree(m_device, "/DCIM");
|
||||
|
||||
if (!dcimTree.success) {
|
||||
qDebug() << "Failed to read DCIM directory";
|
||||
|
||||
@@ -61,12 +61,12 @@ protected:
|
||||
}
|
||||
};
|
||||
|
||||
class ClickableIconWidget : public QWidget
|
||||
class ZIconWidget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
ClickableIconWidget(const QIcon &icon, const QString &tooltip,
|
||||
QWidget *parent = nullptr)
|
||||
ZIconWidget(const QIcon &icon, const QString &tooltip,
|
||||
QWidget *parent = nullptr)
|
||||
: QWidget(parent), m_icon(icon), m_iconSize(24, 24), m_pressed(false)
|
||||
{
|
||||
setToolTip(tooltip);
|
||||
@@ -190,6 +190,7 @@ enum class iDescriptorTool {
|
||||
TouchIdTest,
|
||||
FaceIdTest,
|
||||
UnmountDevImage,
|
||||
NetworkDevices,
|
||||
Unknown,
|
||||
iFuse
|
||||
};
|
||||
|
||||
+10
-30
@@ -24,7 +24,7 @@
|
||||
AppTabWidget::AppTabWidget(const QString &appName, const QString &bundleId,
|
||||
const QString &version, QWidget *parent)
|
||||
: QGroupBox(parent), m_appName(appName), m_bundleId(bundleId),
|
||||
m_version(version), m_selected(false), m_hovered(false)
|
||||
m_version(version), m_selected(false)
|
||||
{
|
||||
setFixedHeight(60);
|
||||
setMinimumWidth(100);
|
||||
@@ -122,41 +122,22 @@ void AppTabWidget::mousePressEvent(QMouseEvent *event)
|
||||
emit clicked();
|
||||
}
|
||||
|
||||
void AppTabWidget::enterEvent(QEnterEvent *event)
|
||||
{
|
||||
Q_UNUSED(event)
|
||||
m_hovered = true;
|
||||
updateStyles();
|
||||
}
|
||||
|
||||
void AppTabWidget::leaveEvent(QEvent *event)
|
||||
{
|
||||
Q_UNUSED(event)
|
||||
m_hovered = false;
|
||||
updateStyles();
|
||||
}
|
||||
|
||||
void AppTabWidget::updateStyles()
|
||||
{
|
||||
// QStyleHints::colorScheme()
|
||||
QString borderStyle;
|
||||
// QColor bgColor = qApp->palette().color(QPalette::Window);
|
||||
QString style;
|
||||
QColor bgColor = isDarkMode() ? qApp->palette().color(QPalette::Light)
|
||||
: qApp->palette().color(QPalette::Dark);
|
||||
qDebug() << styleSheet();
|
||||
if (m_selected) {
|
||||
borderStyle = "QGroupBox { background-color: " +
|
||||
qApp->palette().color(QPalette::Highlight).name() +
|
||||
"; border-radius: "
|
||||
"10px; border : 1px solid " +
|
||||
bgColor.lighter().name() + "; }";
|
||||
style = "QGroupBox { background-color: " + COLOR_ACCENT_BLUE.name() +
|
||||
"; border-radius: "
|
||||
"10px; border : 1px solid " +
|
||||
bgColor.lighter().name() + "; }";
|
||||
} else {
|
||||
borderStyle = "QGroupBox { background-color: " + bgColor.name() +
|
||||
"; border-radius: 10px; border: 1px solid " +
|
||||
bgColor.lighter().name() + "; }";
|
||||
style = "QGroupBox { background-color: " + bgColor.name() +
|
||||
"; border-radius: 10px; border: 1px solid " +
|
||||
bgColor.lighter().name() + "; }";
|
||||
}
|
||||
// update();
|
||||
setStyleSheet(borderStyle);
|
||||
setStyleSheet(style);
|
||||
}
|
||||
|
||||
InstalledAppsWidget::InstalledAppsWidget(iDescriptorDevice *device,
|
||||
@@ -547,7 +528,6 @@ void InstalledAppsWidget::createAppTab(const QString &appName,
|
||||
new AppTabWidget(appName, bundleId, version, this);
|
||||
connect(tabWidget, &AppTabWidget::clicked, this,
|
||||
&InstalledAppsWidget::onAppTabClicked);
|
||||
m_appTabs.append(tabWidget);
|
||||
|
||||
// Remove the stretch before adding the new tab
|
||||
m_tabLayout->removeItem(m_tabLayout->itemAt(m_tabLayout->count() - 1));
|
||||
|
||||
@@ -45,8 +45,6 @@ signals:
|
||||
|
||||
protected:
|
||||
void mousePressEvent(QMouseEvent *event) override;
|
||||
void enterEvent(QEnterEvent *event) override;
|
||||
void leaveEvent(QEvent *event) override;
|
||||
|
||||
private:
|
||||
void fetchAppIcon();
|
||||
@@ -56,7 +54,6 @@ private:
|
||||
QString m_bundleId;
|
||||
QString m_version;
|
||||
bool m_selected = false;
|
||||
bool m_hovered = false;
|
||||
|
||||
QLabel *m_iconLabel;
|
||||
QLabel *m_nameLabel;
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include <QVBoxLayout>
|
||||
#include <QWidget>
|
||||
|
||||
// TODO: theming is broken
|
||||
JailbrokenWidget::JailbrokenWidget(QWidget *parent) : QWidget{parent}
|
||||
{
|
||||
QHBoxLayout *mainLayout = new QHBoxLayout(this);
|
||||
|
||||
@@ -0,0 +1,230 @@
|
||||
#include "networkdeviceswidget.h"
|
||||
|
||||
#ifdef __linux__
|
||||
#include "core/services/avahi/avahi_service.h"
|
||||
#else
|
||||
#include "core/services/dnssd/dnssd_service.h"
|
||||
#endif
|
||||
|
||||
#include <QApplication>
|
||||
#include <QFrame>
|
||||
#include <QHBoxLayout>
|
||||
#include <QLabel>
|
||||
#include <QPalette>
|
||||
|
||||
NetworkDevicesWidget::NetworkDevicesWidget(QWidget *parent) : QWidget(parent)
|
||||
{
|
||||
setWindowTitle("Network Devices - iDescriptor");
|
||||
setupUI();
|
||||
|
||||
#ifdef __linux__
|
||||
m_networkProvider = new AvahiService(this);
|
||||
connect(m_networkProvider, &AvahiService::deviceAdded, this,
|
||||
&NetworkDevicesWidget::onWirelessDeviceAdded);
|
||||
connect(m_networkProvider, &AvahiService::deviceRemoved, this,
|
||||
&NetworkDevicesWidget::onWirelessDeviceRemoved);
|
||||
#else
|
||||
m_networkProvider = new DnssdService(this);
|
||||
connect(m_networkProvider, &DnssdService::deviceAdded, this,
|
||||
&NetworkDevicesWidget::onWirelessDeviceAdded);
|
||||
connect(m_networkProvider, &DnssdService::deviceRemoved, this,
|
||||
&NetworkDevicesWidget::onWirelessDeviceRemoved);
|
||||
#endif
|
||||
|
||||
// Start scanning for network devices
|
||||
m_networkProvider->startBrowsing();
|
||||
|
||||
// Initial device list update
|
||||
updateDeviceList();
|
||||
}
|
||||
|
||||
NetworkDevicesWidget::~NetworkDevicesWidget()
|
||||
{
|
||||
if (m_networkProvider) {
|
||||
m_networkProvider->stopBrowsing();
|
||||
}
|
||||
}
|
||||
|
||||
void NetworkDevicesWidget::setupUI()
|
||||
{
|
||||
QVBoxLayout *mainLayout = new QVBoxLayout(this);
|
||||
mainLayout->setContentsMargins(10, 10, 10, 10);
|
||||
mainLayout->setSpacing(10);
|
||||
|
||||
// Status label
|
||||
m_statusLabel = new QLabel("Scanning for network devices...");
|
||||
QFont statusFont = m_statusLabel->font();
|
||||
statusFont.setPointSize(12);
|
||||
statusFont.setWeight(QFont::Medium);
|
||||
m_statusLabel->setFont(statusFont);
|
||||
m_statusLabel->setAlignment(Qt::AlignCenter);
|
||||
mainLayout->addWidget(m_statusLabel);
|
||||
|
||||
// Device group
|
||||
m_deviceGroup = new QGroupBox("Network Devices");
|
||||
QFont groupFont = m_deviceGroup->font();
|
||||
groupFont.setPointSize(14);
|
||||
groupFont.setWeight(QFont::Bold);
|
||||
m_deviceGroup->setFont(groupFont);
|
||||
|
||||
QVBoxLayout *groupLayout = new QVBoxLayout(m_deviceGroup);
|
||||
groupLayout->setContentsMargins(5, 15, 5, 5);
|
||||
groupLayout->setSpacing(0);
|
||||
|
||||
// Scroll area
|
||||
m_scrollArea = new QScrollArea();
|
||||
m_scrollArea->setWidgetResizable(true);
|
||||
m_scrollArea->setMinimumHeight(200);
|
||||
m_scrollArea->setMaximumHeight(400);
|
||||
m_scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||||
m_scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
|
||||
m_scrollArea->setStyleSheet(
|
||||
"QScrollArea { background: transparent; border: none; }");
|
||||
/* FIXME: We need a better approach to theme awareness */
|
||||
connect(qApp, &QApplication::paletteChanged, this, [this]() {
|
||||
m_scrollArea->setStyleSheet(
|
||||
"QScrollArea { background: transparent; border: none; }");
|
||||
});
|
||||
|
||||
// Scroll content
|
||||
m_scrollContent = new QWidget();
|
||||
m_deviceLayout = new QVBoxLayout(m_scrollContent);
|
||||
m_deviceLayout->setContentsMargins(5, 5, 5, 5);
|
||||
m_deviceLayout->setSpacing(8);
|
||||
m_deviceLayout->addStretch();
|
||||
|
||||
m_scrollArea->setWidget(m_scrollContent);
|
||||
groupLayout->addWidget(m_scrollArea);
|
||||
|
||||
mainLayout->addWidget(m_deviceGroup);
|
||||
mainLayout->addStretch();
|
||||
}
|
||||
|
||||
void NetworkDevicesWidget::createDeviceCard(const NetworkDevice &device)
|
||||
{
|
||||
// Main card frame
|
||||
QWidget *card = new QWidget();
|
||||
|
||||
QVBoxLayout *cardLayout = new QVBoxLayout(card);
|
||||
cardLayout->setContentsMargins(12, 10, 12, 10);
|
||||
cardLayout->setSpacing(4);
|
||||
|
||||
// Device name (primary)
|
||||
QLabel *nameLabel = new QLabel(device.name);
|
||||
nameLabel->setWordWrap(true);
|
||||
QFont nameFont = nameLabel->font();
|
||||
nameFont.setPointSize(13);
|
||||
nameFont.setWeight(QFont::Medium);
|
||||
nameLabel->setFont(nameFont);
|
||||
QPalette namePalette = nameLabel->palette();
|
||||
namePalette.setColor(QPalette::WindowText,
|
||||
palette().color(QPalette::WindowText));
|
||||
nameLabel->setPalette(namePalette);
|
||||
|
||||
// Device info container
|
||||
QWidget *infoContainer = new QWidget();
|
||||
QHBoxLayout *infoLayout = new QHBoxLayout(infoContainer);
|
||||
infoLayout->setContentsMargins(0, 0, 0, 0);
|
||||
infoLayout->setSpacing(12);
|
||||
|
||||
// Address info
|
||||
QLabel *addressLabel = new QLabel(QString("IP: %1").arg(device.address));
|
||||
QFont addressFont = addressLabel->font();
|
||||
addressFont.setPointSize(11);
|
||||
addressLabel->setFont(addressFont);
|
||||
QPalette addressPalette = addressLabel->palette();
|
||||
QColor secondaryColor = palette().color(QPalette::WindowText);
|
||||
secondaryColor.setAlpha(180);
|
||||
addressPalette.setColor(QPalette::WindowText, secondaryColor);
|
||||
addressLabel->setPalette(addressPalette);
|
||||
|
||||
// Port info
|
||||
QLabel *portLabel = new QLabel(QString("Port: %1").arg(device.port));
|
||||
portLabel->setFont(addressFont);
|
||||
portLabel->setPalette(addressPalette);
|
||||
|
||||
infoLayout->addWidget(addressLabel);
|
||||
infoLayout->addWidget(portLabel);
|
||||
infoLayout->addStretch();
|
||||
|
||||
// Status indicator
|
||||
QLabel *statusIndicator = new QLabel("●");
|
||||
QFont statusFont = statusIndicator->font();
|
||||
statusFont.setPointSize(12);
|
||||
statusIndicator->setFont(statusFont);
|
||||
QPalette statusPalette = statusIndicator->palette();
|
||||
statusPalette.setColor(QPalette::WindowText,
|
||||
QColor(52, 199, 89)); // iOS green
|
||||
statusIndicator->setPalette(statusPalette);
|
||||
|
||||
infoLayout->addWidget(statusIndicator);
|
||||
|
||||
cardLayout->addWidget(nameLabel);
|
||||
cardLayout->addWidget(infoContainer);
|
||||
|
||||
// Store the device info as property for later removal
|
||||
card->setProperty("deviceName", device.name);
|
||||
card->setProperty("deviceAddress", device.address);
|
||||
|
||||
// Insert before the stretch
|
||||
m_deviceLayout->insertWidget(m_deviceLayout->count() - 1, card);
|
||||
m_deviceCards.append(card);
|
||||
}
|
||||
|
||||
void NetworkDevicesWidget::clearDeviceCards()
|
||||
{
|
||||
for (QWidget *card : m_deviceCards) {
|
||||
card->deleteLater();
|
||||
}
|
||||
m_deviceCards.clear();
|
||||
}
|
||||
|
||||
void NetworkDevicesWidget::updateDeviceList()
|
||||
{
|
||||
clearDeviceCards();
|
||||
|
||||
QList<NetworkDevice> devices = m_networkProvider->getNetworkDevices();
|
||||
|
||||
if (devices.isEmpty()) {
|
||||
m_statusLabel->setText("No network devices found");
|
||||
} else {
|
||||
m_statusLabel->setText(
|
||||
QString("Found %1 network device(s)").arg(devices.count()));
|
||||
|
||||
for (const NetworkDevice &device : devices) {
|
||||
createDeviceCard(device);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NetworkDevicesWidget::onWirelessDeviceAdded(const NetworkDevice &device)
|
||||
{
|
||||
createDeviceCard(device);
|
||||
|
||||
// Update status
|
||||
int deviceCount = m_deviceCards.count();
|
||||
m_statusLabel->setText(
|
||||
QString("Found %1 network device(s)").arg(deviceCount));
|
||||
}
|
||||
|
||||
void NetworkDevicesWidget::onWirelessDeviceRemoved(const QString &deviceName)
|
||||
{
|
||||
// Find and remove the corresponding card
|
||||
for (int i = 0; i < m_deviceCards.count(); ++i) {
|
||||
QWidget *card = m_deviceCards[i];
|
||||
if (card->property("deviceName").toString() == deviceName) {
|
||||
m_deviceCards.removeAt(i);
|
||||
card->deleteLater();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Update status
|
||||
int deviceCount = m_deviceCards.count();
|
||||
if (deviceCount == 0) {
|
||||
m_statusLabel->setText("No network devices found");
|
||||
} else {
|
||||
m_statusLabel->setText(
|
||||
QString("Found %1 network device(s)").arg(deviceCount));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
#ifndef NETWORKDEVICESWIDGET_H
|
||||
#define NETWORKDEVICESWIDGET_H
|
||||
|
||||
#ifdef __linux__
|
||||
#include "core/services/avahi/avahi_service.h"
|
||||
#else
|
||||
#include "core/services/dnssd/dnssd_service.h"
|
||||
#endif
|
||||
|
||||
#include <QGroupBox>
|
||||
#include <QLabel>
|
||||
#include <QScrollArea>
|
||||
#include <QVBoxLayout>
|
||||
#include <QWidget>
|
||||
|
||||
class NetworkDevicesWidget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit NetworkDevicesWidget(QWidget *parent = nullptr);
|
||||
~NetworkDevicesWidget();
|
||||
|
||||
private slots:
|
||||
void onWirelessDeviceAdded(const NetworkDevice &device);
|
||||
void onWirelessDeviceRemoved(const QString &deviceName);
|
||||
|
||||
private:
|
||||
void setupUI();
|
||||
void createDeviceCard(const NetworkDevice &device);
|
||||
void clearDeviceCards();
|
||||
void updateDeviceList();
|
||||
|
||||
QGroupBox *m_deviceGroup = nullptr;
|
||||
QScrollArea *m_scrollArea = nullptr;
|
||||
QWidget *m_scrollContent = nullptr;
|
||||
QVBoxLayout *m_deviceLayout = nullptr;
|
||||
QLabel *m_statusLabel = nullptr;
|
||||
|
||||
#ifdef __linux__
|
||||
AvahiService *m_networkProvider = nullptr;
|
||||
#else
|
||||
DnssdService *m_networkProvider = nullptr;
|
||||
#endif
|
||||
|
||||
QList<QWidget *> m_deviceCards;
|
||||
};
|
||||
|
||||
#endif // NETWORKDEVICESWIDGET_H
|
||||
@@ -141,6 +141,9 @@ void ToolboxWidget::setupUI()
|
||||
"Mount your iPhone's filesystem on your PC", true, ""});
|
||||
toolWidgets.append({iDescriptorTool::CableInfoWidget,
|
||||
"View detailed cable and connection info", true, ""});
|
||||
toolWidgets.append({iDescriptorTool::NetworkDevices,
|
||||
"Discover and monitor devices on your network", false,
|
||||
""});
|
||||
|
||||
for (int i = 0; i < toolWidgets.size(); ++i) {
|
||||
const auto &tool = toolWidgets[i];
|
||||
@@ -225,6 +228,9 @@ ClickableWidget *ToolboxWidget::createToolbox(iDescriptorTool tool,
|
||||
case iDescriptorTool::UnmountDevImage:
|
||||
title = "Unmount Dev Image";
|
||||
break;
|
||||
case iDescriptorTool::NetworkDevices:
|
||||
title = "Network Devices";
|
||||
break;
|
||||
default:
|
||||
title = "Unknown Tool";
|
||||
break;
|
||||
@@ -431,6 +437,21 @@ void ToolboxWidget::onToolboxClicked(iDescriptorTool tool)
|
||||
cableInfoWidget->resize(600, 400);
|
||||
cableInfoWidget->show();
|
||||
} break;
|
||||
case iDescriptorTool::NetworkDevices: {
|
||||
// single instance lock
|
||||
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();
|
||||
} else {
|
||||
m_networkDevicesWidget->raise();
|
||||
m_networkDevicesWidget->activateWindow();
|
||||
}
|
||||
} break;
|
||||
default:
|
||||
qDebug() << "Clicked on unimplemented tool";
|
||||
break;
|
||||
|
||||
+3
-1
@@ -4,6 +4,7 @@
|
||||
#include "devdiskimageswidget.h"
|
||||
#include "iDescriptor-ui.h"
|
||||
#include "iDescriptor.h"
|
||||
#include "networkdeviceswidget.h"
|
||||
#include <QComboBox>
|
||||
#include <QGridLayout>
|
||||
#include <QHBoxLayout>
|
||||
@@ -42,7 +43,8 @@ private:
|
||||
QList<bool> m_requiresDevice;
|
||||
iDescriptorDevice *m_currentDevice;
|
||||
std::string m_uuid;
|
||||
DevDiskImagesWidget *m_devDiskImagesWidget;
|
||||
DevDiskImagesWidget *m_devDiskImagesWidget = nullptr;
|
||||
NetworkDevicesWidget *m_networkDevicesWidget = nullptr;
|
||||
|
||||
signals:
|
||||
};
|
||||
|
||||
+2
-1
@@ -1,4 +1,5 @@
|
||||
#include "zlineedit.h"
|
||||
#include "iDescriptor-ui.h"
|
||||
|
||||
ZLineEdit::ZLineEdit(QWidget *parent) : QLineEdit(parent) { setupStyles(); }
|
||||
|
||||
@@ -29,7 +30,7 @@ void ZLineEdit::updateStyles()
|
||||
"} "
|
||||
"QLineEdit:focus { "
|
||||
" border: 2px solid " +
|
||||
qApp->palette().color(QPalette::Highlight).name() +
|
||||
COLOR_ACCENT_BLUE.name() +
|
||||
"; "
|
||||
" outline: none; "
|
||||
"}");
|
||||
|
||||
Reference in New Issue
Block a user