diff --git a/src/core/devicescanner.cpp b/src/core/devicescanner.cpp index cdcf784..58906f5 100644 --- a/src/core/devicescanner.cpp +++ b/src/core/devicescanner.cpp @@ -90,4 +90,5 @@ void DeviceScanner::run() } operationStack().sortDevices(); + emit devicesChanged(); } diff --git a/src/core/operationstack.cpp b/src/core/operationstack.cpp index e0d9a96..83473d1 100644 --- a/src/core/operationstack.cpp +++ b/src/core/operationstack.cpp @@ -38,14 +38,17 @@ #include "util/globallog.h" - #include #include +#include +#include + /** Constructs a new OperationStack */ OperationStack::OperationStack() : m_Operations(), - m_PreviewDevices() + m_PreviewDevices(), + m_Lock(QReadWriteLock::Recursive) { } @@ -420,6 +423,8 @@ void OperationStack::clearOperations() /** Clears the list of Devices. */ void OperationStack::clearDevices() { + QWriteLocker lockDevices(&lock()); + qDeleteAll(previewDevices()); previewDevices().clear(); } @@ -430,6 +435,8 @@ void OperationStack::clearDevices() */ Device* OperationStack::findDeviceForPartition(const Partition* p) { + QReadLocker lockDevices(&lock()); + foreach (Device* d, previewDevices()) { if (d->partitionTable() == NULL) @@ -456,6 +463,8 @@ void OperationStack::addDevice(Device* d) { Q_ASSERT(d); + QWriteLocker lockDevices(&lock()); + previewDevices().append(d); } @@ -466,5 +475,7 @@ static bool deviceLessThan(const Device* d1, const Device* d2) void OperationStack::sortDevices() { + QWriteLocker lockDevices(&lock()); + qSort(previewDevices().begin(), previewDevices().end(), deviceLessThan); } diff --git a/src/core/operationstack.h b/src/core/operationstack.h index de1e150..18d8e2f 100644 --- a/src/core/operationstack.h +++ b/src/core/operationstack.h @@ -22,6 +22,8 @@ #define OPERATIONSTACK__H #include +#include + #include class Device; @@ -64,6 +66,8 @@ class OperationStack Device* findDeviceForPartition(const Partition* p); + QReadWriteLock& lock() { return m_Lock; } + protected: void clearDevices(); void addDevice(Device* d); @@ -78,6 +82,7 @@ class OperationStack private: Operations m_Operations; mutable Devices m_PreviewDevices; + QReadWriteLock m_Lock; }; #endif diff --git a/src/gui/listdevices.cpp b/src/gui/listdevices.cpp index effb182..dc8c625 100644 --- a/src/gui/listdevices.cpp +++ b/src/gui/listdevices.cpp @@ -26,6 +26,7 @@ #include #include +#include class ListDeviceWidgetItem : public QListWidgetItem { diff --git a/src/gui/mainwindow.cpp b/src/gui/mainwindow.cpp index 8926ba3..38c6f0e 100644 --- a/src/gui/mainwindow.cpp +++ b/src/gui/mainwindow.cpp @@ -34,6 +34,7 @@ #include #include +#include #include @@ -176,6 +177,8 @@ void MainWindow::on_m_PartitionManagerWidget_operationsChanged() void MainWindow::on_m_PartitionManagerWidget_devicesChanged() { + QReadLocker lockDevices(&pmWidget().operationStack().lock()); + listDevices().updateDevices(pmWidget().previewDevices(), pmWidget().selectedDevice()); if (pmWidget().selectedDevice()) diff --git a/src/gui/partitionmanagerwidget.cpp b/src/gui/partitionmanagerwidget.cpp index 146955c..7d755f3 100644 --- a/src/gui/partitionmanagerwidget.cpp +++ b/src/gui/partitionmanagerwidget.cpp @@ -66,6 +66,7 @@ #include #include +#include #include @@ -325,15 +326,10 @@ void PartitionManagerWidget::onScanDevicesProgressChanged(const QString& device_ void PartitionManagerWidget::onScanDevicesFinished() { + QReadLocker lockDevices(&operationStack().lock()); + 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(); @@ -398,6 +394,8 @@ void PartitionManagerWidget::clearSelectedPartition() void PartitionManagerWidget::setSelectedDevice(const QString& device_node) { + QReadLocker lockDevices(&operationStack().lock()); + foreach(Device* d, operationStack().previewDevices()) if (d->deviceNode() == device_node) { @@ -410,9 +408,10 @@ void PartitionManagerWidget::setSelectedDevice(const QString& device_node) void PartitionManagerWidget::setSelectedDevice(Device* d) { + // NOTE: we cannot emit devicesChanged() here because it will end up calling + // ListDevices::updateDevices() which in turn will modify the QListWidget, which + // will then emit itemSelectionChanged() which will in the end lead us back here. m_SelectedDevice = d; - // FIXME: We should emit devicesChanged() here, but if we do that we get terrible - // races. See onScanDevicesFinished() clearSelectedPartition(); } diff --git a/src/gui/partitionmanagerwidget.h b/src/gui/partitionmanagerwidget.h index 376778d..f00bd40 100644 --- a/src/gui/partitionmanagerwidget.h +++ b/src/gui/partitionmanagerwidget.h @@ -80,6 +80,9 @@ class LIBPARTITIONMANAGERPRIVATE_EXPORT PartitionManagerWidget : public QWidget, const OperationStack::Devices& previewDevices() const { return operationStack().previewDevices(); } const OperationStack::Operations& operations() const { return operationStack().operations(); } + OperationStack& operationStack() { return m_OperationStack; } + const OperationStack& operationStack() const { return m_OperationStack; } + void updatePartitions(); Partition* clipboardPartition() { return m_ClipboardPartition; } @@ -111,9 +114,6 @@ class LIBPARTITIONMANAGERPRIVATE_EXPORT PartitionManagerWidget : public QWidget, 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; } diff --git a/src/kcm/partitionmanagerkcm.cpp b/src/kcm/partitionmanagerkcm.cpp index 10e22ef..d2af000 100644 --- a/src/kcm/partitionmanagerkcm.cpp +++ b/src/kcm/partitionmanagerkcm.cpp @@ -34,6 +34,7 @@ #include #include +#include K_PLUGIN_FACTORY( PartitionManagerKCMFactory, @@ -116,6 +117,8 @@ void PartitionManagerKCM::on_m_PartitionManagerWidget_operationsChanged() void PartitionManagerKCM::on_m_PartitionManagerWidget_devicesChanged() { + QReadLocker lockDevices(&pmWidget().operationStack().lock()); + listDevices().updateDevices(pmWidget().previewDevices(), pmWidget().selectedDevice()); }