diff --git a/isoimagewriter/main.cpp b/isoimagewriter/main.cpp index 43bf911..4b63a8d 100644 --- a/isoimagewriter/main.cpp +++ b/isoimagewriter/main.cpp @@ -1,74 +1,77 @@ /* * Copyright 2016 ROSA * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include #include #include #include #include #include #include #include "common.h" #include "mainapplication.h" #include "maindialog.h" #include "mainwindow.h" #include "usbdevicemonitor.h" #if !defined(Q_OS_WIN32) && !defined(Q_OS_LINUX) && !defined(Q_OS_MAC) #error Unsupported platform! #endif int main(int argc, char *argv[]) { #if defined(Q_OS_MAC) // On Mac OS X elevated launch is treated as setuid which is forbidden by default -> enable it // TODO: Try to find a more "kosher" way, as well as get rid of deprecated AuthorizationExecuteWithPrivileges() QCoreApplication::setSetuidAllowed(true); #endif MainApplication a(argc, argv); if (!ensureElevated()) return 1; #if defined(Q_OS_WIN32) // CoInitialize() seems to be called by Qt automatically, so only set security attributes HRESULT res = CoInitializeSecurity(NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_PKT, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, 0); if (res != S_OK) { printf("CoInitializeSecurity failed! (Code: 0x%08lx)\n", res); return res; } #endif MainDialog w; w.show(); MainWindow w2; w2.show(); UsbDeviceMonitor deviceMonitor; deviceMonitor.startMonitoring(); // When device changing event comes, refresh the list of USB flash disks // Using QueuedConnection to avoid delays in processing the message QObject::connect(&deviceMonitor, &UsbDeviceMonitor::deviceChanged, &w, &MainDialog::scheduleEnumFlashDevices, Qt::QueuedConnection); + QObject::connect(&deviceMonitor, &UsbDeviceMonitor::deviceChanged, &w2, + &MainWindow::scheduleEnumFlashDevices, Qt::QueuedConnection); + return a.exec(); } diff --git a/isoimagewriter/mainwindow.cpp b/isoimagewriter/mainwindow.cpp index 38c8d4e..cb08cb7 100644 --- a/isoimagewriter/mainwindow.cpp +++ b/isoimagewriter/mainwindow.cpp @@ -1,192 +1,208 @@ #include "mainwindow.h" #include "mainapplication.h" #include "common.h" #include #include #include #include #include #include #include #include #include #include #include MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), - m_lastOpenedDir("") + m_lastOpenedDir(""), + m_isWriting(false), + m_enumFlashDevicesWaiting(false) { setupUi(); // Set initial directory m_lastOpenedDir = mApp->getInitialDir(); // Get path to ISO image from command line args (if supplied) QString isoImagePath = mApp->getInitialImage(); if (!isoImagePath.isEmpty()) { if (isoImagePath.left(7) == "file://") isoImagePath = QUrl(isoImagePath).toLocalFile(); if (!isoImagePath.isEmpty()) { isoImagePath = QDir(isoImagePath).absolutePath(); // Update the default open dir m_lastOpenedDir = isoImagePath.left(isoImagePath.lastIndexOf('/')); preprocessIsoImage(isoImagePath); } } // Load the list of USB flash devices QTimer::singleShot(0, this, &MainWindow::enumFlashDevices); } +void MainWindow::scheduleEnumFlashDevices() +{ + if (m_isWriting) + m_enumFlashDevicesWaiting = true; + else + enumFlashDevices(); +} + void MainWindow::setupUi() { // Logo QLabel *logoLabel = new QLabel; logoLabel->setPixmap(QIcon::fromTheme("drive-removable-media").pixmap(QSize(50, 50))); logoLabel->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); QLabel *titleLabel = new QLabel; titleLabel->setTextFormat(Qt::RichText); titleLabel->setText("

KDE ISO Image Writer

" "A quick and simple way to create a bootable USB drive."); QHBoxLayout *headerHBoxLayout = new QHBoxLayout; headerHBoxLayout->addWidget(logoLabel); headerHBoxLayout->addWidget(titleLabel); QStackedWidget *stackedWidget = new QStackedWidget; stackedWidget->addWidget(createFormWidget()); QVBoxLayout *mainVBoxLayout = new QVBoxLayout; mainVBoxLayout->addLayout(headerHBoxLayout); mainVBoxLayout->addSpacing(15); mainVBoxLayout->addWidget(stackedWidget); QWidget *centralWidget = new QWidget; centralWidget->setLayout(mainVBoxLayout); setCentralWidget(centralWidget); } QWidget* MainWindow::createFormWidget() { // Form m_isoImageLineEdit = new QLineEdit; m_isoImageLineEdit->setReadOnly(true); m_isoImageLineEdit->setPlaceholderText(i18n("Path to ISO image...")); QAction *openIsoImageAction = m_isoImageLineEdit->addAction( QIcon::fromTheme("folder-open"), QLineEdit::TrailingPosition); connect(openIsoImageAction, &QAction::triggered, this, &MainWindow::openIsoImage); m_usbDriveComboBox = new QComboBox; QPushButton *createButton = new QPushButton(i18n("Create")); QVBoxLayout *mainVBoxLayout = new QVBoxLayout; mainVBoxLayout->addWidget(new QLabel(i18n("Write this ISO image:"))); mainVBoxLayout->addWidget(m_isoImageLineEdit); mainVBoxLayout->addSpacing(5); mainVBoxLayout->addWidget(new QLabel(i18n("To this USB drive:"))); mainVBoxLayout->addWidget(m_usbDriveComboBox); mainVBoxLayout->addStretch(15); mainVBoxLayout->addWidget(createButton, 0, Qt::AlignRight); QWidget *formWidget = new QWidget; formWidget->setLayout(mainVBoxLayout); return formWidget; } void MainWindow::openIsoImage() { const QString filter = i18n("Disk Images (%1)", QString("*.iso *.bin *.img")) + ";;" + i18n("All Files (%1)", QString("*")); QString isoImagePath = QFileDialog::getOpenFileName(this, "", m_lastOpenedDir, filter, nullptr, QFileDialog::ReadOnly); if (!isoImagePath.isEmpty()) { m_lastOpenedDir = isoImagePath.left(isoImagePath.lastIndexOf('/')); preprocessIsoImage(isoImagePath); } } void MainWindow::preprocessIsoImage(const QString& isoImagePath) { QFile file(isoImagePath); if (!file.open(QIODevice::ReadOnly)) { QMessageBox::critical(this, "Error", i18n("Failed to open the image file:") + "\n" + QDir::toNativeSeparators(isoImagePath) + "\n" + file.errorString()); return; } m_isoImageSize = file.size(); m_isoImagePath = isoImagePath; m_isoImageLineEdit->setText(QDir::toNativeSeparators(m_isoImagePath) + " (" + KFormat().formatByteSize(m_isoImageSize) + ")"); file.close(); // TODO: Verify ISO image } void MainWindow::cleanUp() { // Delete all the allocated UsbDevice objects attached to the combobox for (int i = 0; i < m_usbDriveComboBox->count(); ++i) { delete m_usbDriveComboBox->itemData(i).value(); } } void MainWindow::addFlashDeviceCallback(void* cbParam, UsbDevice* device) { auto usbDriveComboBox = (QComboBox*)cbParam; usbDriveComboBox->addItem(device->formatDisplayName(), QVariant::fromValue(device)); } void MainWindow::enumFlashDevices() { + m_enumFlashDevicesWaiting = false; + // Remember the currently selected device QString selectedDevice = ""; int idx = m_usbDriveComboBox->currentIndex(); if (idx >= 0) { UsbDevice* dev = m_usbDriveComboBox->itemData(idx).value(); selectedDevice = dev->m_PhysicalDevice; } + // Remove the existing entries cleanUp(); m_usbDriveComboBox->clear(); + // Disable the combobox m_usbDriveComboBox->setEnabled(false); + // Add the USB flash devices to the combobox platformEnumFlashDevices(addFlashDeviceCallback, m_usbDriveComboBox); // Restore the previously selected device (if present) if (!selectedDevice.isEmpty()) for (int i = 0; i < m_usbDriveComboBox->count(); ++i) { UsbDevice* dev = m_usbDriveComboBox->itemData(i).value(); if (dev->m_PhysicalDevice == selectedDevice) { m_usbDriveComboBox->setCurrentIndex(i); break; } } - // Reenable the combobox + + // Re-enable the combobox m_usbDriveComboBox->setEnabled(true); // Update the Write button enabled/disabled state // m_writeButton->setEnabled((m_usbDriveComboBox->count() > 0) && (m_isoImagePath != "")); // Update the Clear button enabled/disabled state // m_clearButton->setEnabled(m_usbDriveComboBox->count() > 0); } diff --git a/isoimagewriter/mainwindow.h b/isoimagewriter/mainwindow.h index 230c372..1ab960f 100644 --- a/isoimagewriter/mainwindow.h +++ b/isoimagewriter/mainwindow.h @@ -1,35 +1,40 @@ #ifndef MAINWINDOW_H #define MAINWINDOW_H #include "usbdevice.h" #include #include #include class MainWindow : public QMainWindow { public: MainWindow(QWidget *parent = nullptr); +public slots: + void scheduleEnumFlashDevices(); + private: QLineEdit *m_isoImageLineEdit; QComboBox *m_usbDriveComboBox; QString m_isoImagePath; quint64 m_isoImageSize; QString m_lastOpenedDir; + bool m_isWriting; + bool m_enumFlashDevicesWaiting; void setupUi(); QWidget* createFormWidget(); void preprocessIsoImage(const QString& isoImagePath); void cleanUp(); void enumFlashDevices(); static void addFlashDeviceCallback(void* cbParam, UsbDevice* device); private slots: void openIsoImage(); }; #endif // MAINWINDOW_H