diff --git a/src/core/devicescanner.cpp b/src/core/devicescanner.cpp new file mode 100644 index 0000000..cdcf784 --- /dev/null +++ b/src/core/devicescanner.cpp @@ -0,0 +1,93 @@ +/*************************************************************************** + * Copyright (C) 2010 by Volker Lanz +#include +#include +#include + +/** Constructs a DeviceScanner + @param ostack the OperationStack where the devices will be created +*/ +DeviceScanner::DeviceScanner(OperationStack& ostack) : + QThread(), + m_LibParted(), + m_OperationStack(ostack) +{ +} + +void DeviceScanner::clear() +{ + operationStack().clearOperations(); + emit operationsChanged(); + + operationStack().clearDevices(); + emit devicesChanged(); +} + +static quint32 countDevices(const QList& driveList) +{ + quint32 rval = 0; + + foreach(const Solid::Device& solidDevice, driveList) + { + const Solid::StorageDrive* solidDrive = solidDevice.as(); + if (solidDrive->driveType() == Solid::StorageDrive::HardDisk) + rval++; + } + + return rval; +} + +void DeviceScanner::run() +{ + clear(); + + const QList driveList = Solid::Device::listFromType(Solid::DeviceInterface::StorageDrive, QString()); + const quint32 totalDevices = countDevices(driveList); + quint32 count = 0; + + foreach(const Solid::Device& solidDevice, driveList) + { + const Solid::StorageDrive* solidDrive = solidDevice.as(); + + if (solidDrive->driveType() != Solid::StorageDrive::HardDisk) + continue; + + const Solid::Block* solidBlock = solidDevice.as(); + + Device* d = libParted().scanDevice(solidBlock->device()); + + if (d != NULL) + { + d->setIconName(solidDevice.icon()); + operationStack().addDevice(d); + emit devicesChanged(); + } + + emit progressChanged(solidBlock->device(), (++count) * 100 / totalDevices); + } + + operationStack().sortDevices(); +} diff --git a/src/core/devicescanner.h b/src/core/devicescanner.h new file mode 100644 index 0000000..b16f4d9 --- /dev/null +++ b/src/core/devicescanner.h @@ -0,0 +1,64 @@ +/*************************************************************************** + * Copyright (C) 2010 by Volker Lanz * + * * + * 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 2 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, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * + ***************************************************************************/ + +#ifndef DEVICESCANNER_H +#define DEVICESCANNER_H + +#include + +#include "core/libparted.h" + +class OperationStack; + +/** @brief Thread to scan for all available Devices on this computer. + + This class is used to find all Devices on the computer and to create new Device instances for each of them. It's subclassing QThread to run asynchronously. + + @author vl@fidra.de +*/ +class DeviceScanner : public QThread +{ + Q_OBJECT + + public: + DeviceScanner(OperationStack& ostack); + + public: + void clear(); /**< clear Devices and the OperationStack */ + + signals: + void progressChanged(const QString& device_node, int progress); + void devicesChanged(); + void operationsChanged(); + + protected: + virtual void run(); + + OperationStack& operationStack() { return m_OperationStack; } + const OperationStack& operationStack() const { return m_OperationStack; } + + LibParted& libParted() { return m_LibParted; } + const LibParted& libParted() const { return m_LibParted; } + + private: + LibParted m_LibParted; + OperationStack& m_OperationStack; +}; + +#endif diff --git a/src/core/libparted.cpp b/src/core/libparted.cpp index 0ed6d60..5e79bca 100644 --- a/src/core/libparted.cpp +++ b/src/core/libparted.cpp @@ -45,11 +45,6 @@ #include #include -#include -#include -#include -#include - #include #include @@ -289,60 +284,30 @@ LibParted::LibParted() ped_exception_set_handler(pedExceptionHandler); } -/** Scans for all available Devices on this computer. - - This method tries to find all Devices on the computer and creates new Device instances for each of them. It then calls scanDevicePartitions() to find all Partitions and FileSystems on each Device and set those up. - - The method will clear the list of operations and devices currently in the OperationStack given. - - @param ostack the OperationStack where the devices will be created -*/ -void LibParted::scanDevices(OperationStack& ostack) +Device* LibParted::scanDevice(const QString& device_node) { - ostack.clearOperations(); - ostack.clearDevices(); + PedDevice* pedDevice = ped_device_get(device_node.toLocal8Bit()); - // LibParted's ped_device_probe_all() - // 1) segfaults when it finds "illegal" entries in /dev/mapper - // 2) takes several minutes to time out if the BIOS says there's a floppy drive present - // when in fact there is none. - // For that reason we scan devices on our own using Solid now. - const QList driveList = Solid::Device::listFromType(Solid::DeviceInterface::StorageDrive, QString()); - - foreach(const Solid::Device& solidDevice, driveList) + if (pedDevice == NULL) { - const Solid::StorageDrive* solidDrive = solidDevice.as(); - - if (solidDrive->driveType() != Solid::StorageDrive::HardDisk) - continue; - - const Solid::Block* solidBlock = solidDevice.as(); - PedDevice* pedDevice = ped_device_get(solidBlock->device().toLocal8Bit()); - - if (pedDevice == NULL) - { - Log(Log::warning) << i18nc("@info/plain", "Could not access device %1", solidBlock->device()); - continue; - } - - Log(Log::information) << i18nc("@info/plain", "Device found: %1", pedDevice->model); - - Device* d = new Device(pedDevice->model, pedDevice->path, pedDevice->bios_geom.heads, pedDevice->bios_geom.sectors, pedDevice->bios_geom.cylinders, pedDevice->sector_size, solidDevice.icon()); - - PedDisk* pedDisk = ped_disk_new(pedDevice); - - if (pedDisk) - { - const PartitionTable::LabelType type = PartitionTable::nameToLabelType(pedDisk->type->name); - d->setPartitionTable(new PartitionTable(type, firstUsableSector(*d), lastUsableSector(*d))); - d->partitionTable()->setMaxPrimaries(ped_disk_get_max_primary_partition_count(pedDisk)); - - scanDevicePartitions(pedDevice, *d, pedDisk); - } - - ostack.addDevice(d); + Log(Log::warning) << i18nc("@info/plain", "Could not access device %1", device_node); + return NULL; } - ostack.sortDevices(); -} + Log(Log::information) << i18nc("@info/plain", "Device found: %1", pedDevice->model); + Device* d = new Device(pedDevice->model, pedDevice->path, pedDevice->bios_geom.heads, pedDevice->bios_geom.sectors, pedDevice->bios_geom.cylinders, pedDevice->sector_size); + + PedDisk* pedDisk = ped_disk_new(pedDevice); + + if (pedDisk) + { + const PartitionTable::LabelType type = PartitionTable::nameToLabelType(pedDisk->type->name); + d->setPartitionTable(new PartitionTable(type, firstUsableSector(*d), lastUsableSector(*d))); + d->partitionTable()->setMaxPrimaries(ped_disk_get_max_primary_partition_count(pedDisk)); + + scanDevicePartitions(pedDevice, *d, pedDisk); + } + + return d; +} diff --git a/src/core/libparted.h b/src/core/libparted.h index df189b4..9aefa65 100644 --- a/src/core/libparted.h +++ b/src/core/libparted.h @@ -44,9 +44,9 @@ class LibParted LibParted(); public: - void scanDevices(OperationStack& ostack); static quint64 firstUsableSector(const Device& d); static quint64 lastUsableSector(const Device& d); + static Device* scanDevice(const QString& device_node); }; #endif diff --git a/src/core/operationstack.h b/src/core/operationstack.h index c4fcc3b..de1e150 100644 --- a/src/core/operationstack.h +++ b/src/core/operationstack.h @@ -26,8 +26,8 @@ class Device; class Partition; -class LibParted; class Operation; +class DeviceScanner; /** @brief The list of Operations the user wants to have performed. @@ -40,7 +40,7 @@ class OperationStack { Q_DISABLE_COPY(OperationStack) - friend class LibParted; + friend class DeviceScanner; public: typedef QList Devices; diff --git a/src/gui/progressdialogwidget.cpp b/src/gui/applyprogressdetailswidget.cpp similarity index 92% rename from src/gui/progressdialogwidget.cpp rename to src/gui/applyprogressdetailswidget.cpp index 0477621..de536a1 100644 --- a/src/gui/progressdialogwidget.cpp +++ b/src/gui/applyprogressdetailswidget.cpp @@ -1,5 +1,5 @@ /*************************************************************************** - * Copyright (C) 2008 by Volker Lanz * + * Copyright (C) 2008,2010 by Volker Lanz * * * * 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 * @@ -17,4 +17,4 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * ***************************************************************************/ -#include "gui/progressdialogwidget.h" +#include "gui/applyprogressdetailswidget.h" diff --git a/src/gui/progressdetailswidget.h b/src/gui/applyprogressdetailswidget.h similarity index 82% rename from src/gui/progressdetailswidget.h rename to src/gui/applyprogressdetailswidget.h index dda8ad8..15ce91d 100644 --- a/src/gui/progressdetailswidget.h +++ b/src/gui/applyprogressdetailswidget.h @@ -1,5 +1,5 @@ /*************************************************************************** - * Copyright (C) 2008 by Volker Lanz * + * Copyright (C) 2008,2010 by Volker Lanz * * * * 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 * @@ -17,21 +17,21 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * ***************************************************************************/ -#if !defined(PROGRESSDETAILSWIDGET__H) +#if !defined(APPLYPROGRESSDETAILSWIDGET__H) -#define PROGRESSDETAILSWIDGET__H +#define APPLYPROGRESSDETAILSWIDGET__H -#include "ui_progressdetailswidgetbase.h" +#include "ui_applyprogressdetailswidgetbase.h" /** @brief Details widget for the ProgressDialog. @author vl@fidra.de */ -class ProgressDetailsWidget : public QWidget, public Ui::ProgressDetailsWidgetBase +class ApplyProgressDetailsWidget : public QWidget, public Ui::ApplyProgressDetailsWidgetBase { Q_OBJECT public: - ProgressDetailsWidget(QWidget* parent) : QWidget(parent) { setupUi(this); } + ApplyProgressDetailsWidget(QWidget* parent) : QWidget(parent) { setupUi(this); } public: KTextEdit& editReport() { Q_ASSERT(m_EditReport); return *m_EditReport; } diff --git a/src/gui/applyprogressdetailswidgetbase.ui b/src/gui/applyprogressdetailswidgetbase.ui new file mode 100644 index 0000000..73a4365 --- /dev/null +++ b/src/gui/applyprogressdetailswidgetbase.ui @@ -0,0 +1,59 @@ + + + ApplyProgressDetailsWidgetBase + + + + 0 + 0 + 736 + 600 + + + + + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse + + + + + + + Qt::Horizontal + + + + 608 + 20 + + + + + + + + &Save + + + + + + + &Open in External Browser + + + + + + + + KTextEdit + QTextEdit +
ktextedit.h
+
+
+ + +
diff --git a/src/gui/progressdialog.cpp b/src/gui/applyprogressdialog.cpp similarity index 88% rename from src/gui/progressdialog.cpp rename to src/gui/applyprogressdialog.cpp index b240898..a1c46a0 100644 --- a/src/gui/progressdialog.cpp +++ b/src/gui/applyprogressdialog.cpp @@ -17,10 +17,10 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * ***************************************************************************/ -#include "gui/progressdialog.h" +#include "gui/applyprogressdialog.h" -#include "gui/progressdialogwidget.h" -#include "gui/progressdetailswidget.h" +#include "gui/applyprogressdialogwidget.h" +#include "gui/applyprogressdetailswidget.h" #include "core/operationrunner.h" @@ -45,7 +45,7 @@ #include #include -const QString ProgressDialog::m_TimeFormat = "hh:mm:ss"; +const QString ApplyProgressDialog::m_TimeFormat = "hh:mm:ss"; static QWidget* mainWindow(QWidget* w) { @@ -58,10 +58,10 @@ static QWidget* mainWindow(QWidget* w) @param parent pointer to the parent widget @param orunner the OperationRunner whose progress this dialog is showing */ -ProgressDialog::ProgressDialog(QWidget* parent, OperationRunner& orunner) : +ApplyProgressDialog::ApplyProgressDialog(QWidget* parent, OperationRunner& orunner) : KDialog(parent), - m_ProgressDialogWidget(new ProgressDialogWidget(this)), - m_ProgressDetailsWidget(new ProgressDetailsWidget(this)), + m_ProgressDialogWidget(new ApplyProgressDialogWidget(this)), + m_ProgressDetailsWidget(new ApplyProgressDetailsWidget(this)), m_OperationRunner(orunner), m_Report(NULL), m_SavedParentTitle(mainWindow(this)->windowTitle()), @@ -85,14 +85,14 @@ ProgressDialog::ProgressDialog(QWidget* parent, OperationRunner& orunner) : } /** Destroys a ProgressDialog */ -ProgressDialog::~ProgressDialog() +ApplyProgressDialog::~ApplyProgressDialog() { KConfigGroup kcg(KGlobal::config(), "progressDialog"); saveDialogSize(kcg); delete m_Report; } -void ProgressDialog::setupConnections() +void ApplyProgressDialog::setupConnections() { connect(&operationRunner(), SIGNAL(progressSub(int)), &dialogWidget().progressSub(), SLOT(setValue(int))); connect(&operationRunner(), SIGNAL(finished()), SLOT(onAllOpsFinished())); @@ -106,7 +106,7 @@ void ProgressDialog::setupConnections() } /** Shows the dialog */ -void ProgressDialog::show() +void ApplyProgressDialog::show() { foreach (QWidget* w, kapp->topLevelWidgets()) w->setEnabled(false); @@ -134,7 +134,7 @@ void ProgressDialog::show() KDialog::show(); } -void ProgressDialog::resetReport() +void ApplyProgressDialog::resetReport() { delete m_Report; m_Report = new Report(NULL); @@ -147,13 +147,13 @@ void ProgressDialog::resetReport() connect(&report(), SIGNAL(outputChanged()), SLOT(updateReport())); } -void ProgressDialog::closeEvent(QCloseEvent* e) +void ApplyProgressDialog::closeEvent(QCloseEvent* e) { e->ignore(); slotButtonClicked(operationRunner().isRunning() ? KDialog::Cancel : KDialog::Ok); } -void ProgressDialog::slotButtonClicked(int button) +void ApplyProgressDialog::slotButtonClicked(int button) { if (button == KDialog::Details) { @@ -200,22 +200,22 @@ void ProgressDialog::slotButtonClicked(int button) KDialog::accept(); } -void ProgressDialog::onAllOpsFinished() +void ApplyProgressDialog::onAllOpsFinished() { allOpsDone(i18nc("@info:progress", "All operations successfully finished.")); } -void ProgressDialog::onAllOpsCancelled() +void ApplyProgressDialog::onAllOpsCancelled() { allOpsDone(i18nc("@info:progress", "Operations cancelled.")); } -void ProgressDialog::onAllOpsError() +void ApplyProgressDialog::onAllOpsError() { allOpsDone(i18nc("@info:progress", "There were errors while applying operations. Aborted.")); } -void ProgressDialog::allOpsDone(const QString& msg) +void ApplyProgressDialog::allOpsDone(const QString& msg) { dialogWidget().progressTotal().setValue(operationRunner().numJobs()); showButton(KDialog::Cancel, false); @@ -228,7 +228,7 @@ void ProgressDialog::allOpsDone(const QString& msg) setStatus(msg); } -void ProgressDialog::updateReport(bool force) +void ApplyProgressDialog::updateReport(bool force) { // Rendering the HTML in the KTextEdit is extremely expensive. So make sure not to do that // unnecessarily and not too often: @@ -245,7 +245,7 @@ void ProgressDialog::updateReport(bool force) } } -void ProgressDialog::onOpStarted(int num, Operation* op) +void ApplyProgressDialog::onOpStarted(int num, Operation* op) { addTaskOutput(num, *op); setStatus(op->description()); @@ -257,7 +257,7 @@ void ProgressDialog::onOpStarted(int num, Operation* op) connect(op, SIGNAL(jobFinished(Job*, Operation*)), SLOT(onJobFinished(Job*, Operation*))); } -void ProgressDialog::onJobStarted(Job* job, Operation* op) +void ApplyProgressDialog::onJobStarted(Job* job, Operation* op) { for (qint32 i = 0; i < dialogWidget().treeTasks().topLevelItemCount(); i++) { @@ -277,7 +277,7 @@ void ProgressDialog::onJobStarted(Job* job, Operation* op) } } -void ProgressDialog::onJobFinished(Job* job, Operation* op) +void ApplyProgressDialog::onJobFinished(Job* job, Operation* op) { if (currentJobItem()) currentJobItem()->setIcon(0, job->statusIcon()); @@ -291,7 +291,7 @@ void ProgressDialog::onJobFinished(Job* job, Operation* op) updateReport(true); } -void ProgressDialog::onOpFinished(int num, Operation* op) +void ApplyProgressDialog::onOpFinished(int num, Operation* op) { if (currentOpItem()) { @@ -307,13 +307,13 @@ void ProgressDialog::onOpFinished(int num, Operation* op) updateReport(true); } -void ProgressDialog::setParentTitle(const QString& s) +void ApplyProgressDialog::setParentTitle(const QString& s) { const int percent = dialogWidget().progressTotal().value() * 100 / dialogWidget().progressTotal().maximum(); mainWindow(this)->setWindowTitle(QString::number(percent) + "% - " + s + " - " + savedParentTitle()); } -void ProgressDialog::setStatus(const QString& s) +void ApplyProgressDialog::setStatus(const QString& s) { setCaption(s); dialogWidget().status().setText(s); @@ -321,12 +321,12 @@ void ProgressDialog::setStatus(const QString& s) setParentTitle(s); } -QString ProgressDialog::opDesc(int num, const Operation& op) const +QString ApplyProgressDialog::opDesc(int num, const Operation& op) const { return i18nc("@info:progress", "[%1/%2] - %3: %4", num, operationRunner().numOperations(), op.statusText(), op.description()); } -void ProgressDialog::addTaskOutput(int num, const Operation& op) +void ApplyProgressDialog::addTaskOutput(int num, const Operation& op) { QTreeWidgetItem* item = new QTreeWidgetItem(); item->setIcon(0, op.statusIcon()); @@ -344,7 +344,7 @@ void ProgressDialog::addTaskOutput(int num, const Operation& op) setCurrentOpItem(item); } -void ProgressDialog::onSecondElapsed() +void ApplyProgressDialog::onSecondElapsed() { if (currentJobItem()) { @@ -362,7 +362,7 @@ void ProgressDialog::onSecondElapsed() dialogWidget().totalTime().setText(i18nc("@info:progress", "Total Time: %1", outputTime.toString(timeFormat()))); } -void ProgressDialog::keyPressEvent(QKeyEvent* e) +void ApplyProgressDialog::keyPressEvent(QKeyEvent* e) { e->accept(); @@ -383,7 +383,7 @@ void ProgressDialog::keyPressEvent(QKeyEvent* e) } } -void ProgressDialog::saveReport() +void ApplyProgressDialog::saveReport() { QString fileName = KFileDialog::getSaveFileName(KUrl("kfiledialog://saveReport")); @@ -407,7 +407,7 @@ void ProgressDialog::saveReport() } } -void ProgressDialog::browserReport() +void ApplyProgressDialog::browserReport() { KTemporaryFile file; diff --git a/src/gui/progressdialog.h b/src/gui/applyprogressdialog.h similarity index 80% rename from src/gui/progressdialog.h rename to src/gui/applyprogressdialog.h index 1782156..460531f 100644 --- a/src/gui/progressdialog.h +++ b/src/gui/applyprogressdialog.h @@ -17,9 +17,9 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * ***************************************************************************/ -#if !defined(PROGRESSDIALOG__H) +#if !defined(APPLYPROGRESSDIALOG__H) -#define PROGRESSDIALOG__H +#define APPLYPROGRESSDIALOG__H #include @@ -30,8 +30,8 @@ class OperationRunner; class Operation; class Job; -class ProgressDialogWidget; -class ProgressDetailsWidget; +class ApplyProgressDialogWidget; +class ApplyProgressDetailsWidget; class Report; @@ -45,14 +45,14 @@ class QKeyEvent; @author vl@fidra.de */ -class ProgressDialog : public KDialog +class ApplyProgressDialog : public KDialog { Q_OBJECT - Q_DISABLE_COPY(ProgressDialog) + Q_DISABLE_COPY(ApplyProgressDialog) public: - ProgressDialog(QWidget* parent, OperationRunner& orunner); - ~ProgressDialog(); + ApplyProgressDialog(QWidget* parent, OperationRunner& orunner); + ~ApplyProgressDialog(); public: void show(); @@ -82,11 +82,15 @@ class ProgressDialog : public KDialog const OperationRunner& operationRunner() const { return m_OperationRunner; } - ProgressDialogWidget& dialogWidget() { Q_ASSERT(m_ProgressDialogWidget); return *m_ProgressDialogWidget; } - const ProgressDialogWidget& dialogWidget() const { Q_ASSERT(m_ProgressDialogWidget); return *m_ProgressDialogWidget; } + ApplyProgressDialogWidget +& dialogWidget() { Q_ASSERT(m_ProgressDialogWidget); return *m_ProgressDialogWidget; } + const ApplyProgressDialogWidget +& dialogWidget() const { Q_ASSERT(m_ProgressDialogWidget); return *m_ProgressDialogWidget; } - ProgressDetailsWidget& detailsWidget() { Q_ASSERT(m_ProgressDetailsWidget); return *m_ProgressDetailsWidget; } - const ProgressDetailsWidget& detailsWidget() const { Q_ASSERT(m_ProgressDetailsWidget); return *m_ProgressDetailsWidget; } + ApplyProgressDetailsWidget +& detailsWidget() { Q_ASSERT(m_ProgressDetailsWidget); return *m_ProgressDetailsWidget; } + const ApplyProgressDetailsWidget +& detailsWidget() const { Q_ASSERT(m_ProgressDetailsWidget); return *m_ProgressDetailsWidget; } void setStatus(const QString& s); @@ -119,8 +123,10 @@ class ProgressDialog : public KDialog static const QString& timeFormat() { return m_TimeFormat; } private: - ProgressDialogWidget* m_ProgressDialogWidget; - ProgressDetailsWidget* m_ProgressDetailsWidget; + ApplyProgressDialogWidget +* m_ProgressDialogWidget; + ApplyProgressDetailsWidget +* m_ProgressDetailsWidget; const OperationRunner& m_OperationRunner; Report* m_Report; QString m_SavedParentTitle; diff --git a/src/gui/progressdetailswidget.cpp b/src/gui/applyprogressdialogwidget.cpp similarity index 96% rename from src/gui/progressdetailswidget.cpp rename to src/gui/applyprogressdialogwidget.cpp index d4bc5d8..6fffc7d 100644 --- a/src/gui/progressdetailswidget.cpp +++ b/src/gui/applyprogressdialogwidget.cpp @@ -17,4 +17,4 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * ***************************************************************************/ -#include "gui/progressdetailswidget.h" +#include "gui/applyprogressdialogwidget.h" diff --git a/src/gui/progressdialogwidget.h b/src/gui/applyprogressdialogwidget.h similarity index 86% rename from src/gui/progressdialogwidget.h rename to src/gui/applyprogressdialogwidget.h index 36e6908..1df70ba 100644 --- a/src/gui/progressdialogwidget.h +++ b/src/gui/applyprogressdialogwidget.h @@ -17,19 +17,19 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * ***************************************************************************/ -#if !defined(PROGRESSDIALOGWIDGET__H) +#if !defined(APPLYPROGRESSDIALOGWIDGET__H) -#define PROGRESSDIALOGWIDGET__H +#define APPLYPROGRESSDIALOGWIDGET__H -#include "ui_progressdialogwidgetbase.h" +#include "ui_applyprogressdialogwidgetbase.h" /** @brief Central widget for the ProgressDialog. @author vl@fidra.de */ -class ProgressDialogWidget : public QWidget, public Ui::ProgressDialogWidgetBase +class ApplyProgressDialogWidget : public QWidget, public Ui::ApplyProgressDialogWidgetBase { public: - ProgressDialogWidget(QWidget* parent) : QWidget(parent) { setupUi(this); } + ApplyProgressDialogWidget(QWidget* parent) : QWidget(parent) { setupUi(this); } public: QTreeWidget& treeTasks() { Q_ASSERT(m_TreeTasks); return *m_TreeTasks; } diff --git a/src/gui/progressdialogwidgetbase.ui b/src/gui/applyprogressdialogwidgetbase.ui similarity index 96% rename from src/gui/progressdialogwidgetbase.ui rename to src/gui/applyprogressdialogwidgetbase.ui index d14a2e4..b13c50d 100644 --- a/src/gui/progressdialogwidgetbase.ui +++ b/src/gui/applyprogressdialogwidgetbase.ui @@ -1,7 +1,7 @@ - ProgressDialogWidgetBase - + ApplyProgressDialogWidgetBase + 0 diff --git a/src/gui/mainwindow.cpp b/src/gui/mainwindow.cpp index 181ffd5..6044b33 100644 --- a/src/gui/mainwindow.cpp +++ b/src/gui/mainwindow.cpp @@ -19,7 +19,7 @@ #include "gui/mainwindow.h" #include "gui/infopane.h" -#include "gui/progressdialog.h" +#include "gui/applyprogressdialog.h" #include "core/device.h" @@ -82,7 +82,7 @@ void MainWindow::init() void MainWindow::closeEvent(QCloseEvent* event) { - if (pmWidget().progressDialog().isVisible()) + if (pmWidget().applyProgressDialog().isVisible()) { event->ignore(); return; @@ -109,10 +109,10 @@ void MainWindow::closeEvent(QCloseEvent* event) void MainWindow::changeEvent(QEvent* event) { - if ((event->type() == QEvent::ActivationChange || event->type() == QEvent::WindowStateChange) && event->spontaneous() && isActiveWindow() && pmWidget().progressDialog().isVisible()) + if ((event->type() == QEvent::ActivationChange || event->type() == QEvent::WindowStateChange) && event->spontaneous() && isActiveWindow() && pmWidget().applyProgressDialog().isVisible()) { - pmWidget().progressDialog().activateWindow(); - pmWidget().progressDialog().raise(); + pmWidget().applyProgressDialog().activateWindow(); + pmWidget().applyProgressDialog().raise(); } KXmlGuiWindow::changeEvent(event); @@ -134,8 +134,8 @@ void MainWindow::setupConnections() { connect(&pmWidget(), SIGNAL(devicesChanged()), SLOT(updateDevices())); connect(&pmWidget(), SIGNAL(operationsChanged()), &listOperations(), SLOT(updateOperations())); - connect(&pmWidget(), SIGNAL(statusChanged()), SLOT(updateStatusBar())); - connect(&pmWidget(), SIGNAL(selectionChanged(const Partition*)), SLOT(updateSelection(const Partition*))); + connect(&pmWidget(), SIGNAL(operationsChanged()), SLOT(updateStatusBar())); + connect(&pmWidget(), SIGNAL(selectedPartitionChanged(const Partition*)), SLOT(updateSelection(const Partition*))); connect(&dockInformation(), SIGNAL(dockLocationChanged(Qt::DockWidgetArea)), SLOT(onDockLocationChanged(Qt::DockWidgetArea))); } diff --git a/src/gui/partitionmanagerwidget.cpp b/src/gui/partitionmanagerwidget.cpp index 85c3dbc..fc338aa 100644 --- a/src/gui/partitionmanagerwidget.cpp +++ b/src/gui/partitionmanagerwidget.cpp @@ -24,16 +24,18 @@ #include "gui/infopane.h" #include "gui/newdialog.h" #include "gui/filesystemsupportdialog.h" -#include "gui/progressdialog.h" +#include "gui/applyprogressdialog.h" #include "gui/insertdialog.h" #include "gui/editmountpointdialog.h" #include "gui/createpartitiontabledialog.h" +#include "gui/scanprogressdialog.h" #include "core/partition.h" #include "core/device.h" #include "core/operationstack.h" #include "core/partitiontable.h" #include "core/operationrunner.h" +#include "core/devicescanner.h" #include "fs/filesystemfactory.h" @@ -101,10 +103,11 @@ class PartitionTreeWidgetItem : public QTreeWidgetItem PartitionManagerWidget::PartitionManagerWidget(QWidget* parent, KActionCollection* coll) : QWidget(parent), Ui::PartitionManagerWidgetBase(), - m_LibParted(), m_OperationStack(), m_OperationRunner(operationStack()), - m_ProgressDialog(new ProgressDialog(this, operationRunner())), + m_DeviceScanner(operationStack()), + m_ApplyProgressDialog(new ApplyProgressDialog(this, operationRunner())), + m_ScanProgressDialog(new ScanProgressDialog(this)), m_ActionCollection(coll), m_SelectedDevice(NULL), m_ClipboardPartition(NULL) @@ -300,36 +303,58 @@ void PartitionManagerWidget::setupConnections() Q_ASSERT(actionCollection()); connect(&partTableWidget(), SIGNAL(itemActivated(const PartWidget*)), actionCollection()->action("propertiesPartition"), SLOT(trigger())); - connect(&progressDialog(), SIGNAL(finished(int)), SLOT(onFinished())); + connect(&applyProgressDialog(), SIGNAL(finished(int)), SLOT(scanDevices())); + + connect(&deviceScanner(), SIGNAL(finished()), SLOT(onScanDevicesFinished())); + connect(&deviceScanner(), SIGNAL(progressChanged(const QString&, int)), SLOT(onScanDevicesProgressChanged(const QString&, int))); + connect(&deviceScanner(), SIGNAL(operationsChanged()), SIGNAL(operationsChanged())); + connect(&deviceScanner(), SIGNAL(devicesChanged()), SIGNAL(devicesChanged())); } void PartitionManagerWidget::scanDevices() { - Log() << i18nc("@info/plain", "Rescanning devices..."); + Log() << i18nc("@info/plain", "Scanning devices..."); + + clear(); KApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); - setSelectedDevice(NULL); - setClipboardPartition(NULL); - clear(); + foreach (QWidget* w, kapp->topLevelWidgets()) + w->setEnabled(false); - libParted().scanDevices(operationStack()); + scanProgressDialog().setEnabled(true); + scanProgressDialog().show(); + deviceScanner().start(); +} + +void PartitionManagerWidget::onScanDevicesProgressChanged(const QString& device_node, int percent) +{ + scanProgressDialog().setProgress(percent); + scanProgressDialog().setDeviceName(device_node); +} + +void PartitionManagerWidget::onScanDevicesFinished() +{ if (!operationStack().previewDevices().isEmpty()) { setSelectedDevice(operationStack().previewDevices()[0]); - + // FIXME: Normally this should be emitted in setSelectedDevice(), but if we do that + // now we get all kinds of terrible races and crashes during rescan (because DeviceScanner + // clears the devices in the operationstack while ListDevices is just iterating them). + // Once that is fixed, remove the emit here. + emit devicesChanged(); } updatePartitions(); - Log() << i18nc("@info/plain", "Rescan finished."); + Log() << i18nc("@info/plain", "Scan finished."); KApplication::restoreOverrideCursor(); - emit selectionChanged(NULL); - emit devicesChanged(); - emit operationsChanged(); - emit statusChanged(); + scanProgressDialog().hide(); + + foreach (QWidget* w, kapp->topLevelWidgets()) + w->setEnabled(true); } void PartitionManagerWidget::enableActions() @@ -367,13 +392,17 @@ void PartitionManagerWidget::enableActions() void PartitionManagerWidget::clear() { + setSelectedDevice(NULL); + setClipboardPartition(NULL); treePartitions().clear(); partTableWidget().clear(); + deviceScanner().clear(); } -void PartitionManagerWidget::clearSelection() +void PartitionManagerWidget::clearSelectedPartition() { treePartitions().setCurrentItem(NULL); + emit selectedPartitionChanged(NULL); enableActions(); updatePartitions(); } @@ -381,7 +410,9 @@ void PartitionManagerWidget::clearSelection() void PartitionManagerWidget::setSelectedDevice(Device* d) { m_SelectedDevice = d; - clearSelection(); + // FIXME: We should emit devicesChanged() here, but if we do that we get terrible + // races. See onScanDevicesFinished() + clearSelectedPartition(); } static QTreeWidgetItem* createTreeWidgetItem(const Partition& p) @@ -471,7 +502,7 @@ void PartitionManagerWidget::on_m_PartTableWidget_itemSelectionChanged(PartWidge if (item == NULL) { treePartitions().setCurrentItem(NULL); - emit selectionChanged(NULL); + emit selectedPartitionChanged(NULL); return; } @@ -492,7 +523,7 @@ void PartitionManagerWidget::on_m_PartTableWidget_itemSelectionChanged(PartWidge } } - emit selectionChanged(p); + emit selectedPartitionChanged(p); } void PartitionManagerWidget::on_m_PartTableWidget_customContextMenuRequested(const QPoint& pos) @@ -580,7 +611,6 @@ void PartitionManagerWidget::onPropertiesPartition() updatePartitions(); emit operationsChanged(); - emit statusChanged(); } delete dlg; @@ -684,7 +714,6 @@ void PartitionManagerWidget::onNewPartition() PartitionTable::snap(*selectedDevice(), *newPartition); operationStack().push(new NewOperation(*selectedDevice(), newPartition)); updatePartitions(); - emit statusChanged(); emit operationsChanged(); } else @@ -743,7 +772,6 @@ void PartitionManagerWidget::onDeletePartition(bool shred) operationStack().push(new DeleteOperation(*selectedDevice(), selectedPartition(), shred)); updatePartitions(); - emit statusChanged(); emit operationsChanged(); } @@ -788,7 +816,6 @@ void PartitionManagerWidget::onResizePartition() operationStack().push(new ResizeOperation(*selectedDevice(), *selectedPartition(), resizedPartition.firstSector(), resizedPartition.lastSector())); updatePartitions(); - emit statusChanged(); emit operationsChanged(); } } @@ -848,7 +875,6 @@ void PartitionManagerWidget::onPastePartition() { operationStack().push(new CopyOperation(*selectedDevice(), copiedPartition, *dSource, clipboardPartition())); updatePartitions(); - emit statusChanged(); emit operationsChanged(); } else @@ -920,7 +946,6 @@ void PartitionManagerWidget::onCreateNewPartitionTable() operationStack().push(new CreatePartitionTableOperation(*selectedDevice(), dlg->type())); updatePartitions(); - emit statusChanged(); emit operationsChanged(); emit devicesChanged(); enableActions(); @@ -950,7 +975,6 @@ void PartitionManagerWidget::onUndoOperation() updatePartitions(); emit operationsChanged(); - emit statusChanged(); emit devicesChanged(); enableActions(); } @@ -968,7 +992,6 @@ void PartitionManagerWidget::onClearAllOperations() updatePartitions(); emit operationsChanged(); - emit statusChanged(); enableActions(); } } @@ -990,9 +1013,9 @@ void PartitionManagerWidget::onApplyAllOperations() { Log() << i18nc("@info/plain", "Applying operations..."); - progressDialog().show(); + applyProgressDialog().show(); - operationRunner().setReport(&progressDialog().report()); + operationRunner().setReport(&applyProgressDialog().report()); // Undo all operations so the runner has a defined starting point for (int i = operationStack().operations().size() - 1; i >= 0; i--) @@ -1021,7 +1044,6 @@ void PartitionManagerWidget::onCheckPartition() operationStack().push(new CheckOperation(*selectedDevice(), *selectedPartition())); updatePartitions(); - emit statusChanged(); emit operationsChanged(); } @@ -1046,7 +1068,6 @@ void PartitionManagerWidget::onBackupPartition() { operationStack().push(new BackupOperation(*selectedDevice(), *selectedPartition(), fileName)); updatePartitions(); - emit statusChanged(); emit operationsChanged(); } } @@ -1084,7 +1105,6 @@ void PartitionManagerWidget::onRestorePartition() operationStack().push(new RestoreOperation(*selectedDevice(), restorePartition, fileName)); updatePartitions(); - emit statusChanged(); emit operationsChanged(); } else @@ -1097,8 +1117,3 @@ void PartitionManagerWidget::onFileSystemSupport() FileSystemSupportDialog dlg(this); dlg.exec(); } - -void PartitionManagerWidget::onFinished() -{ - scanDevices(); -} diff --git a/src/gui/partitionmanagerwidget.h b/src/gui/partitionmanagerwidget.h index 5e95762..b34e002 100644 --- a/src/gui/partitionmanagerwidget.h +++ b/src/gui/partitionmanagerwidget.h @@ -23,9 +23,9 @@ #include "util/libpartitionmanagerexport.h" -#include "core/libparted.h" #include "core/operationrunner.h" #include "core/operationstack.h" +#include "core/devicescanner.h" #include "ui_partitionmanagerwidgetbase.h" @@ -36,7 +36,8 @@ class QLabel; class PartWidget; class KActionCollection; class Device; -class ProgressDialog; +class ApplyProgressDialog; +class ScanProgressDialog; /** @brief The central widget for the application. @@ -54,8 +55,7 @@ class LIBPARTITIONMANAGERPRIVATE_EXPORT PartitionManagerWidget : public QWidget, signals: void devicesChanged(); void operationsChanged(); - void statusChanged(); - void selectionChanged(const Partition*); + void selectedPartitionChanged(const Partition*); public slots: void setSelectedDevice(Device* d); @@ -65,7 +65,7 @@ class LIBPARTITIONMANAGERPRIVATE_EXPORT PartitionManagerWidget : public QWidget, KActionCollection* actionCollection() const { return m_ActionCollection; } void clear(); - void clearSelection(); + void clearSelectedPartition(); void setPartitionTable(const PartitionTable* ptable); void setSelection(const Partition* p); void enableActions(); @@ -85,8 +85,11 @@ class LIBPARTITIONMANAGERPRIVATE_EXPORT PartitionManagerWidget : public QWidget, const Partition* clipboardPartition() const { return m_ClipboardPartition; } void setClipboardPartition(Partition* p) { m_ClipboardPartition = p; } - ProgressDialog& progressDialog() { Q_ASSERT(m_ProgressDialog); return *m_ProgressDialog; } - const ProgressDialog& progressDialog() const { Q_ASSERT(m_ProgressDialog); return *m_ProgressDialog; } + ApplyProgressDialog& applyProgressDialog() { Q_ASSERT(m_ApplyProgressDialog); return *m_ApplyProgressDialog; } + const ApplyProgressDialog& applyProgressDialog() const { Q_ASSERT(m_ApplyProgressDialog); return *m_ApplyProgressDialog; } + + ScanProgressDialog& scanProgressDialog() { Q_ASSERT(m_ScanProgressDialog); return *m_ScanProgressDialog; } + const ScanProgressDialog& scanProgressDialog() const { Q_ASSERT(m_ScanProgressDialog); return *m_ScanProgressDialog; } quint32 numPendingOperations(); @@ -104,15 +107,15 @@ class LIBPARTITIONMANAGERPRIVATE_EXPORT PartitionManagerWidget : public QWidget, QTreeWidget& treePartitions() { Q_ASSERT(m_TreePartitions); return *m_TreePartitions; } const QTreeWidget& treePartitions() const { Q_ASSERT(m_TreePartitions); return *m_TreePartitions; } - LibParted& libParted() { return m_LibParted; } - const LibParted& libParted() const { return m_LibParted; } - OperationRunner& operationRunner() { return m_OperationRunner; } const OperationRunner& operationRunner() const { return m_OperationRunner; } OperationStack& operationStack() { return m_OperationStack; } const OperationStack& operationStack() const { return m_OperationStack; } + DeviceScanner& deviceScanner() { return m_DeviceScanner; } + const DeviceScanner& deviceScanner() const { return m_DeviceScanner; } + protected slots: void on_m_TreePartitions_currentItemChanged(QTreeWidgetItem* current, QTreeWidgetItem* previous); void on_m_PartTableWidget_customContextMenuRequested(const QPoint& pos); @@ -121,6 +124,8 @@ class LIBPARTITIONMANAGERPRIVATE_EXPORT PartitionManagerWidget : public QWidget, void on_m_PartTableWidget_itemSelectionChanged(PartWidget* item); void scanDevices(); + void onScanDevicesFinished(); + void onScanDevicesProgressChanged(const QString& device_node, int percent); void onPropertiesPartition(); void onMountPartition(); @@ -140,13 +145,13 @@ class LIBPARTITIONMANAGERPRIVATE_EXPORT PartitionManagerWidget : public QWidget, void onFileSystemSupport(); void onBackupPartition(); void onRestorePartition(); - void onFinished(); private: - LibParted m_LibParted; OperationStack m_OperationStack; OperationRunner m_OperationRunner; - ProgressDialog* m_ProgressDialog; + DeviceScanner m_DeviceScanner; + ApplyProgressDialog* m_ApplyProgressDialog; + ScanProgressDialog* m_ScanProgressDialog; KActionCollection* m_ActionCollection; Device* m_SelectedDevice; Partition* m_ClipboardPartition; diff --git a/src/gui/progressdetailswidgetbase.ui b/src/gui/progressdetailswidgetbase.ui deleted file mode 100644 index 0b69e95..0000000 --- a/src/gui/progressdetailswidgetbase.ui +++ /dev/null @@ -1,51 +0,0 @@ - - ProgressDetailsWidgetBase - - - - 0 - 0 - 736 - 600 - - - - - - - Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse - - - - - - - Qt::Horizontal - - - - 608 - 20 - - - - - - - - &Save - - - - - - - &Open in External Browser - - - - - - - - diff --git a/src/gui/scanprogressdialog.cpp b/src/gui/scanprogressdialog.cpp new file mode 100644 index 0000000..06db531 --- /dev/null +++ b/src/gui/scanprogressdialog.cpp @@ -0,0 +1,42 @@ +/*************************************************************************** + * Copyright (C) 2010 by Volker Lanz * + * * + * 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 2 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, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ + +#include "gui/scanprogressdialog.h" + +#include + +ScanProgressDialog::ScanProgressDialog(QWidget* parent) : + KProgressDialog(parent) +{ + setCaption(i18nc("@title:window", "Scanning devices...")); + setMinimumWidth(280); + setMinimumDuration(150); +} + +void ScanProgressDialog::setDeviceName(const QString& d) +{ + setLabelText(i18nc("@label", "Scanning device: %1", d)); +} + +void ScanProgressDialog::showEvent(QShowEvent* e) +{ + setAllowCancel(false); + + KProgressDialog::showEvent(e); +} diff --git a/src/gui/scanprogressdialog.h b/src/gui/scanprogressdialog.h new file mode 100644 index 0000000..2c0fb4a --- /dev/null +++ b/src/gui/scanprogressdialog.h @@ -0,0 +1,44 @@ +/*************************************************************************** + * Copyright (C) 2010 by Volker Lanz * + * * + * 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 2 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, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ + +#if !defined(SCANPROGRESSDIALOG__H) + +#define SCANPROGRESSDIALOG__H + +#include + +class QShowEvent; + +class ScanProgressDialog : public KProgressDialog +{ + Q_OBJECT + + public: + ScanProgressDialog(QWidget* parent); + + protected: + virtual void showEvent(QShowEvent* e); + + public: + void setProgress(quint32 p) { progressBar()->setValue(p); } + void setDeviceName(const QString& d); +}; + +#endif + diff --git a/src/kcm/partitionmanagerkcm.cpp b/src/kcm/partitionmanagerkcm.cpp index fea0c05..09fb38b 100644 --- a/src/kcm/partitionmanagerkcm.cpp +++ b/src/kcm/partitionmanagerkcm.cpp @@ -107,7 +107,7 @@ void PartitionManagerKCM::setupConnections() connect(&pmWidget(), SIGNAL(devicesChanged()), &listDevices(), SLOT(updateDevices())); connect(&pmWidget(), SIGNAL(operationsChanged()), &listOperations(), SLOT(updateOperations())); connect(&listDevices(), SIGNAL(selectionChanged(Device*)), &pmWidget(), SLOT(setSelectedDevice(Device*))); - connect(&pmWidget(), SIGNAL(statusChanged()), SLOT(onStatusChanged())); + connect(&pmWidget(), SIGNAL(operationsChanged()), SLOT(onStatusChanged())); } void PartitionManagerKCM::onStatusChanged()