Index: dataengines/soliddevice/CMakeLists.txt =================================================================== --- dataengines/soliddevice/CMakeLists.txt +++ dataengines/soliddevice/CMakeLists.txt @@ -18,6 +18,7 @@ KF5::Plasma KF5::Solid KF5::CoreAddons + KF5::Notifications ) kcoreaddons_desktop_to_json(plasma_engine_soliddevice plasma-dataengine-soliddevice.desktop) Index: dataengines/soliddevice/soliddeviceengine.h =================================================================== --- dataengines/soliddevice/soliddeviceengine.h +++ dataengines/soliddevice/soliddeviceengine.h @@ -35,6 +35,7 @@ #include "devicesignalmapmanager.h" #include "devicesignalmapper.h" #include "hddtemp.h" +#include enum State { Idle = 0, @@ -80,6 +81,8 @@ QMap m_devicemap; //udi, corresponding encrypted container udi; QMap m_encryptedContainerMap; + //udi, corresponding thread timer + QMap m_timers; DeviceSignalMapManager *m_signalmanager; HddTemp *m_temperature; @@ -94,6 +97,31 @@ void setUnmountingState(const QString &udi); void setIdleState(Solid::ErrorType error, QVariant errorData, const QString &udi); void deviceChanged(const QMap & props); + void slotInfoObtained(QString path, QString udi, bool isValid, KIO::filesize_t available, KIO::filesize_t size); +}; + + +/** + * This class provides obtaining filesystem info in different thread. + */ +class SolidDeviceEngineWorker : public QObject +{ + Q_OBJECT + +public: + SolidDeviceEngineWorker(QString path, QString udi); + ~SolidDeviceEngineWorker(); + +public slots: + void getFreeSpaceInfo(); + +signals: + void finished(); + void infoObtained(QString path, QString udi, bool isValid, KIO::filesize_t available, KIO::filesize_t size); + +private: + QString m_path; + QString m_udi; }; #endif Index: dataengines/soliddevice/soliddeviceengine.cpp =================================================================== --- dataengines/soliddevice/soliddeviceengine.cpp +++ dataengines/soliddevice/soliddeviceengine.cpp @@ -24,9 +24,12 @@ #include #include +#include #include +#include #include #include +#include #include @@ -46,12 +49,34 @@ } } +Q_DECLARE_METATYPE(KIO::filesize_t) + +SolidDeviceEngineWorker::SolidDeviceEngineWorker(QString path, QString udi) + : m_path(path) + , m_udi(udi) +{ +} + +SolidDeviceEngineWorker::~SolidDeviceEngineWorker() +{ +} + +void SolidDeviceEngineWorker::getFreeSpaceInfo() +{ + KDiskFreeSpaceInfo info = KDiskFreeSpaceInfo::freeSpaceInfo(m_path); + emit infoObtained(m_path, m_udi, info.isValid(), info.available(), info.size()); + emit finished(); +} + SolidDeviceEngine::SolidDeviceEngine(QObject* parent, const QVariantList& args) : Plasma::DataEngine(parent, args), m_temperature(nullptr), m_notifier(nullptr) { Q_UNUSED(args) + + qRegisterMetaType("KIO::filesize_t"); + m_signalmanager = new DeviceSignalMapManager(this); listenForNewDevices(); @@ -547,17 +571,58 @@ return false; } - KDiskFreeSpaceInfo info = KDiskFreeSpaceInfo::freeSpaceInfo(storageaccess->filePath()); - if (info.isValid()) { - setData(udi, I18N_NOOP("Free Space"), QVariant(info.available())); - setData(udi, I18N_NOOP("Free Space Text"), KFormat().formatByteSize(info.available())); - setData(udi, I18N_NOOP("Size"), QVariant(info.size())); - return true; + QString path = storageaccess->filePath(); + if (!m_timers.contains(path)) { + QThread *thread = new QThread; + SolidDeviceEngineWorker *worker = new SolidDeviceEngineWorker(path, udi); + + QTimer *timer = new QTimer(this); + timer->setSingleShot(true); + connect(timer, &QTimer::timeout, [path]() { + KNotification::event(KNotification::Error, i18n("Filesystem is not responding", path), + i18n("Filesystem mounted at '%1' is not responding", path), + QApplication::activeWindow(), KNotification::CloseWhenWidgetActivated); + }); + + m_timers[path] = timer; + + worker->moveToThread(thread); + // start worker after starting thread, and stop thread when finished + connect(thread, &QThread::started, worker, &SolidDeviceEngineWorker::getFreeSpaceInfo); + connect(worker, &SolidDeviceEngineWorker::finished, thread, &QThread::quit); + + // delete later thread, worker and timer + connect(worker, &SolidDeviceEngineWorker::finished, worker, &SolidDeviceEngineWorker::deleteLater); + connect(worker, &SolidDeviceEngineWorker::finished, thread, &QTimer::deleteLater); + connect(thread, &QThread::finished, thread, &QThread::deleteLater); + + // collect and process info + connect(worker, &SolidDeviceEngineWorker::infoObtained, + this, &SolidDeviceEngine::slotInfoObtained, + Qt::QueuedConnection); + + // start thread and timer: after 15 seconds we will get an error + thread->start(); + timer->start(15000); } return false; } +void SolidDeviceEngine::slotInfoObtained(QString path, QString udi, bool isValid, KIO::filesize_t available, KIO::filesize_t size) +{ + if (m_timers[path]->isActive()) + m_timers[path]->stop(); + + if (isValid) { + setData(udi, I18N_NOOP("Free Space"), QVariant(available)); + setData(udi, I18N_NOOP("Free Space Text"), KFormat().formatByteSize(available)); + setData(udi, I18N_NOOP("Size"), QVariant(size)); + } + + m_timers.remove(path); +} + bool SolidDeviceEngine::updateHardDiskTemperature(const QString &udi) { Solid::Device device = m_devicemap.value(udi);