summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAl12rs <gabriel.cortesi@outlook.com>2018-05-11 20:16:48 +0200
committerAl12rs <gabriel.cortesi@outlook.com>2018-05-17 00:02:34 +0200
commit1c6543454ef4d3b84e2ce1f6928b6c99005eee29 (patch)
tree49e591b095f94adf789003addeb752362483505f
parent941c50bff903bdd241764240167d21013d9e8f5c (diff)
Initial work on avoiding the spamming of the Downlods tab refresh caused by the fileSystemWatcher picking up changes made by MO itself and triggering multiple refreshes
-rw-r--r--src/downloadmanager.cpp85
-rw-r--r--src/downloadmanager.h16
2 files changed, 99 insertions, 2 deletions
diff --git a/src/downloadmanager.cpp b/src/downloadmanager.cpp
index 8aba42aa..ea8253be 100644
--- a/src/downloadmanager.cpp
+++ b/src/downloadmanager.cpp
@@ -180,7 +180,7 @@ QString DownloadManager::DownloadInfo::currentURL()
DownloadManager::DownloadManager(NexusInterface *nexusInterface, QObject *parent)
- : IDownloadManager(parent), m_NexusInterface(nexusInterface), m_DirWatcher(), m_ShowHidden(false),
+ : IDownloadManager(parent), m_NexusInterface(nexusInterface), m_DirWatcher(), m_DirWatcherDisabler(0), m_ShowHidden(false),
m_DateExpression("/Date\\((\\d+)\\)/")
{
connect(&m_DirWatcher, SIGNAL(directoryChanged(QString)), this, SLOT(directoryChanged(QString)));
@@ -209,8 +209,10 @@ bool DownloadManager::downloadsInProgress()
return false;
}
+
void DownloadManager::pauseAll()
{
+
// first loop: pause all downloads
for (int i = 0; i < m_ActiveDownloads.count(); ++i) {
if (m_ActiveDownloads[i]->m_State < STATE_READY) {
@@ -238,6 +240,7 @@ void DownloadManager::pauseAll()
::Sleep(100);
}
}
+
}
@@ -276,9 +279,30 @@ void DownloadManager::setPluginContainer(PluginContainer *pluginContainer)
m_NexusInterface->setPluginContainer(pluginContainer);
}
+
+void DownloadManager::startDisableDirWatcher()
+{
+ m_DirWatcherDisabler++;
+}
+
+
+void DownloadManager::endDisableDirWatcher()
+{
+ QCoreApplication::processEvents();
+ if (m_DirWatcherDisabler > 0)
+ m_DirWatcherDisabler--;
+ else
+ m_DirWatcherDisabler = 0;
+}
+
+
+
void DownloadManager::refreshList()
{
try {
+ //avoid triggering other refreshes
+ startDisableDirWatcher();
+
int downloadsBefore = m_ActiveDownloads.size();
// remove finished downloads
@@ -339,6 +363,10 @@ void DownloadManager::refreshList()
qDebug("downloads after refresh: %d", m_ActiveDownloads.size());
}
emit update(-1);
+
+ //let watcher trigger refreshes again
+ endDisableDirWatcher();
+
} catch (const std::bad_alloc&) {
reportError(tr("Memory allocation error (in refreshing directory)."));
}
@@ -388,7 +416,10 @@ bool DownloadManager::addDownload(QNetworkReply *reply, const QStringList &URLs,
baseName = dispoName;
}
}
+
+ startDisableDirWatcher();
newDownload->setName(getDownloadFileName(baseName), false);
+ endDisableDirWatcher();
startDownload(reply, newDownload, false);
// emit update(-1);
@@ -458,7 +489,9 @@ void DownloadManager::startDownload(QNetworkReply *reply, DownloadInfo *newDownl
else
setState(newDownload, STATE_CANCELING);
} else {
+ startDisableDirWatcher();
newDownload->setName(getDownloadFileName(newDownload->m_FileName, true), true);
+ endDisableDirWatcher();
if (newDownload->m_State == STATE_PAUSED)
resumeDownload(indexByName(newDownload->m_FileName));
else
@@ -530,6 +563,9 @@ void DownloadManager::addNXMDownload(const QString &url)
void DownloadManager::removeFile(int index, bool deleteFile)
{
+ //Avoid triggering refreshes from DirWatcher
+ startDisableDirWatcher();
+
if (index >= m_ActiveDownloads.size()) {
throw MyException(tr("remove: invalid download index %1").arg(index));
}
@@ -540,6 +576,7 @@ void DownloadManager::removeFile(int index, bool deleteFile)
(download->m_State == STATE_DOWNLOADING)) {
// shouldn't have been possible
qCritical("tried to remove active download");
+ endDisableDirWatcher();
return;
}
@@ -550,6 +587,7 @@ void DownloadManager::removeFile(int index, bool deleteFile)
if (deleteFile) {
if (!shellDelete(QStringList(filePath), true)) {
reportError(tr("failed to delete %1").arg(filePath));
+ endDisableDirWatcher();
return;
}
@@ -561,6 +599,8 @@ void DownloadManager::removeFile(int index, bool deleteFile)
QSettings metaSettings(filePath.append(".meta"), QSettings::IniFormat);
metaSettings.setValue("removed", true);
}
+
+ endDisableDirWatcher();
}
class LessThanWrapper
@@ -606,14 +646,22 @@ void DownloadManager::restoreDownload(int index)
QString filePath = m_OutputDirectory + "/" + download->m_FileName;
+ //avoid dirWatcher triggering refreshes
+ startDisableDirWatcher();
+
QSettings metaSettings(filePath.append(".meta"), QSettings::IniFormat);
metaSettings.setValue("removed", false);
+
+ endDisableDirWatcher();
}
void DownloadManager::removeDownload(int index, bool deleteFile)
{
try {
+ //avoid dirWatcher triggering refreshes
+ startDisableDirWatcher();
+
emit aboutToUpdate();
if (index < 0) {
@@ -634,6 +682,7 @@ void DownloadManager::removeDownload(int index, bool deleteFile)
} else {
if (index >= m_ActiveDownloads.size()) {
reportError(tr("remove: invalid download index %1").arg(index));
+ endDisableDirWatcher();
return;
}
@@ -641,6 +690,7 @@ void DownloadManager::removeDownload(int index, bool deleteFile)
delete m_ActiveDownloads.at(index);
m_ActiveDownloads.erase(m_ActiveDownloads.begin() + index);
}
+ endDisableDirWatcher();
emit update(-1);
} catch (const std::exception &e) {
qCritical("failed to remove download: %s", e.what());
@@ -970,11 +1020,16 @@ void DownloadManager::markInstalled(int index)
throw MyException(tr("mark installed: invalid download index %1").arg(index));
}
+ //Avoid triggering refreshes from DirWatcher
+ startDisableDirWatcher();
+
DownloadInfo *info = m_ActiveDownloads.at(index);
QSettings metaFile(info->m_Output.fileName() + ".meta", QSettings::IniFormat);
metaFile.setValue("installed", true);
metaFile.setValue("uninstalled", false);
+ endDisableDirWatcher();
+
setState(m_ActiveDownloads.at(index), STATE_INSTALLED);
}
@@ -986,10 +1041,15 @@ void DownloadManager::markInstalled(QString fileName)
} else {
DownloadInfo *info = getDownloadInfo(fileName);
if (info != nullptr) {
+ //Avoid triggering refreshes from DirWatcher
+ startDisableDirWatcher();
+
QSettings metaFile(info->m_Output.fileName() + ".meta", QSettings::IniFormat);
metaFile.setValue("installed", true);
metaFile.setValue("uninstalled", false);
delete info;
+
+ endDisableDirWatcher();
}
}
}
@@ -1005,10 +1065,15 @@ void DownloadManager::markUninstalled(int index)
throw MyException(tr("mark uninstalled: invalid download index %1").arg(index));
}
+ //Avoid triggering refreshes from DirWatcher
+ startDisableDirWatcher();
+
DownloadInfo *info = m_ActiveDownloads.at(index);
QSettings metaFile(info->m_Output.fileName() + ".meta", QSettings::IniFormat);
metaFile.setValue("uninstalled", true);
+ endDisableDirWatcher();
+
setState(m_ActiveDownloads.at(index), STATE_UNINSTALLED);
}
@@ -1022,9 +1087,15 @@ void DownloadManager::markUninstalled(QString fileName)
QString filePath = QDir::fromNativeSeparators(m_OutputDirectory) + "/" + fileName;
DownloadInfo *info = getDownloadInfo(filePath);
if (info != nullptr) {
+
+ //Avoid triggering refreshes from DirWatcher
+ startDisableDirWatcher();
+
QSettings metaFile(info->m_Output.fileName() + ".meta", QSettings::IniFormat);
metaFile.setValue("uninstalled", true);
delete info;
+
+ endDisableDirWatcher();
}
}
}
@@ -1183,6 +1254,9 @@ void DownloadManager::downloadReadyRead()
void DownloadManager::createMetaFile(DownloadInfo *info)
{
+ //Avoid triggering refreshes from DirWatcher
+ startDisableDirWatcher();
+
QSettings metaFile(QString("%1.meta").arg(info->m_Output.fileName()), QSettings::IniFormat);
metaFile.setValue("gameName", info->m_FileInfo->gameName);
metaFile.setValue("modID", info->m_FileInfo->modID);
@@ -1204,6 +1278,7 @@ void DownloadManager::createMetaFile(DownloadInfo *info)
(info->m_State == DownloadManager::STATE_ERROR));
metaFile.setValue("removed", info->m_Hidden);
+ endDisableDirWatcher();
// slightly hackish...
for (int i = 0; i < m_ActiveDownloads.size(); ++i) {
if (m_ActiveDownloads[i] == info) {
@@ -1572,11 +1647,14 @@ void DownloadManager::downloadFinished(int index)
QString newName = getFileNameFromNetworkReply(reply);
QString oldName = QFileInfo(info->m_Output).fileName();
+
+ startDisableDirWatcher();
if (!newName.isEmpty() && (oldName.isEmpty())) {
info->setName(getDownloadFileName(newName), true);
} else {
info->setName(m_OutputDirectory + "/" + info->m_FileName, true); // don't rename but remove the ".unfinished" extension
}
+ endDisableDirWatcher();
if (!isNexus) {
setState(info, STATE_READY);
@@ -1616,7 +1694,9 @@ void DownloadManager::metaDataChanged()
if (info != nullptr) {
QString newName = getFileNameFromNetworkReply(info->m_Reply);
if (!newName.isEmpty() && (info->m_FileName.isEmpty())) {
+ startDisableDirWatcher();
info->setName(getDownloadFileName(newName), true);
+ endDisableDirWatcher();
refreshAlphabeticalTranslation();
if (!info->m_Output.isOpen() && !info->m_Output.open(QIODevice::WriteOnly | QIODevice::Append)) {
reportError(tr("failed to re-open %1").arg(info->m_FileName));
@@ -1630,7 +1710,8 @@ void DownloadManager::metaDataChanged()
void DownloadManager::directoryChanged(const QString&)
{
- refreshList();
+ if(m_DirWatcherDisabler==0)
+ refreshList();
}
void DownloadManager::managedGameChanged(MOBase::IPluginGame const *managedGame)
diff --git a/src/downloadmanager.h b/src/downloadmanager.h
index 17ae8a35..74627be5 100644
--- a/src/downloadmanager.h
+++ b/src/downloadmanager.h
@@ -144,6 +144,17 @@ public:
**/
void setOutputDirectory(const QString &outputDirectory);
+ /**
+ * @brief disables feedback from the downlods fileSystemWhatcher untill disableDownloadsWatcherEnd() is called
+ *
+ **/
+ void startDisableDirWatcher();
+
+ /**
+ * @brief re-enables feedback from the downlods fileSystemWhatcher after disableDownloadsWatcherStart() was called
+ **/
+ void endDisableDirWatcher();
+
/**
* @return current download directory
**/
@@ -519,6 +530,11 @@ private:
QFileSystemWatcher m_DirWatcher;
+ //The dirWatcher is actually triggering off normal Mo operations such as deleting downloads or editing .meta files
+ //so it needs to be disabled during operations that are known to cause the creation or deletion of files in the Downloads folder.
+ //Notably using QSettings to edit a file creates a temporarily .lock file that causes the Watcher to trigger multiple listRefreshes freezing the ui.
+ int m_DirWatcherDisabler;
+
std::map<QString, int> m_DownloadFails;
bool m_ShowHidden;