diff options
| author | Al12rs <gabriel.cortesi@outlook.com> | 2018-05-11 20:16:48 +0200 |
|---|---|---|
| committer | Al12rs <gabriel.cortesi@outlook.com> | 2018-05-17 00:02:34 +0200 |
| commit | 1c6543454ef4d3b84e2ce1f6928b6c99005eee29 (patch) | |
| tree | 49e591b095f94adf789003addeb752362483505f | |
| parent | 941c50bff903bdd241764240167d21013d9e8f5c (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.cpp | 85 | ||||
| -rw-r--r-- | src/downloadmanager.h | 16 |
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;
|
