From decbbb611edf002bc1458a651c331d1832ed2a6a Mon Sep 17 00:00:00 2001 From: Silarn Date: Sun, 13 May 2018 18:32:59 -0500 Subject: Download resume fixes for restarting MO, hung downloads --- src/downloadmanager.h | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src/downloadmanager.h') diff --git a/src/downloadmanager.h b/src/downloadmanager.h index 98f5e468..17ae8a35 100644 --- a/src/downloadmanager.h +++ b/src/downloadmanager.h @@ -29,6 +29,7 @@ along with Mod Organizer. If not, see . #include #include #include +#include #include #include #include @@ -443,6 +444,7 @@ private slots: void downloadError(QNetworkReply::NetworkError error); void metaDataChanged(); void directoryChanged(const QString &dirctory); + void checkDownloadTimeout(); private: @@ -524,6 +526,8 @@ private: QRegExp m_DateExpression; MOBase::IPluginGame const *m_ManagedGame; + + QTimer m_TimeoutTimer; }; -- cgit v1.3.1 From 1c6543454ef4d3b84e2ce1f6928b6c99005eee29 Mon Sep 17 00:00:00 2001 From: Al12rs Date: Fri, 11 May 2018 20:16:48 +0200 Subject: 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 --- src/downloadmanager.cpp | 85 +++++++++++++++++++++++++++++++++++++++++++++++-- src/downloadmanager.h | 16 ++++++++++ 2 files changed, 99 insertions(+), 2 deletions(-) (limited to 'src/downloadmanager.h') 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 m_DownloadFails; bool m_ShowHidden; -- cgit v1.3.1 From 8731159bfbaa34c431343b4e415590ae079a24bb Mon Sep 17 00:00:00 2001 From: Al12rs Date: Thu, 17 May 2018 00:01:54 +0200 Subject: Huge performace improvements for downloads tab by disabling the dirWatcher triggered refreshes. Avoid app freezes caused by stacked refresh calls. Added chack to see if a download is alerady hidden before trying to hide it. Made sure to refresh Download tab where it was othwerwise relying in the dirwatcher to refresh. --- src/downloadmanager.cpp | 50 +++++++++++++++++++++++++++++-------------------- src/downloadmanager.h | 7 ++++--- 2 files changed, 34 insertions(+), 23 deletions(-) (limited to 'src/downloadmanager.h') diff --git a/src/downloadmanager.cpp b/src/downloadmanager.cpp index ea8253be..6cd86ece 100644 --- a/src/downloadmanager.cpp +++ b/src/downloadmanager.cpp @@ -54,6 +54,7 @@ using namespace MOBase; static const char UNFINISHED[] = ".unfinished"; unsigned int DownloadManager::DownloadInfo::s_NextDownloadID = 1U; +int DownloadManager::m_DirWatcherDisabler = 0; DownloadManager::DownloadInfo *DownloadManager::DownloadInfo::createNew(const ModRepositoryFileInfo *fileInfo, const QStringList &URLs) @@ -142,6 +143,25 @@ DownloadManager::DownloadInfo *DownloadManager::DownloadInfo::createFromMeta(con return info; } +void DownloadManager::startDisableDirWatcher() +{ + DownloadManager::m_DirWatcherDisabler++; +} + + +void DownloadManager::endDisableDirWatcher() +{ + if (DownloadManager::m_DirWatcherDisabler > 0) + { + if (DownloadManager::m_DirWatcherDisabler == 1) + QCoreApplication::processEvents(); + DownloadManager::m_DirWatcherDisabler--; + } + else { + DownloadManager::m_DirWatcherDisabler = 0; + } +} + void DownloadManager::DownloadInfo::setName(QString newName, bool renameFile) { QString oldMetaFileName = QString("%1.meta").arg(m_FileName); @@ -180,7 +200,7 @@ QString DownloadManager::DownloadInfo::currentURL() DownloadManager::DownloadManager(NexusInterface *nexusInterface, QObject *parent) - : IDownloadManager(parent), m_NexusInterface(nexusInterface), m_DirWatcher(), m_DirWatcherDisabler(0), m_ShowHidden(false), + : IDownloadManager(parent), m_NexusInterface(nexusInterface), m_DirWatcher(), m_ShowHidden(false), m_DateExpression("/Date\\((\\d+)\\)/") { connect(&m_DirWatcher, SIGNAL(directoryChanged(QString)), this, SLOT(directoryChanged(QString))); @@ -280,20 +300,7 @@ void DownloadManager::setPluginContainer(PluginContainer *pluginContainer) } -void DownloadManager::startDisableDirWatcher() -{ - m_DirWatcherDisabler++; -} - -void DownloadManager::endDisableDirWatcher() -{ - QCoreApplication::processEvents(); - if (m_DirWatcherDisabler > 0) - m_DirWatcherDisabler--; - else - m_DirWatcherDisabler = 0; -} @@ -359,9 +366,9 @@ void DownloadManager::refreshList() } } - if (m_ActiveDownloads.size() != downloadsBefore) { + //if (m_ActiveDownloads.size() != downloadsBefore) { qDebug("downloads after refresh: %d", m_ActiveDownloads.size()); - } + //} emit update(-1); //let watcher trigger refreshes again @@ -597,9 +604,10 @@ void DownloadManager::removeFile(int index, bool deleteFile) } } else { QSettings metaSettings(filePath.append(".meta"), QSettings::IniFormat); - metaSettings.setValue("removed", true); + if(!download->m_Hidden) + metaSettings.setValue("removed", true); } - + endDisableDirWatcher(); } @@ -682,6 +690,7 @@ void DownloadManager::removeDownload(int index, bool deleteFile) } else { if (index >= m_ActiveDownloads.size()) { reportError(tr("remove: invalid download index %1").arg(index)); + //emit update(-1); endDisableDirWatcher(); return; } @@ -690,11 +699,12 @@ void DownloadManager::removeDownload(int index, bool deleteFile) delete m_ActiveDownloads.at(index); m_ActiveDownloads.erase(m_ActiveDownloads.begin() + index); } - endDisableDirWatcher(); emit update(-1); + endDisableDirWatcher(); } catch (const std::exception &e) { qCritical("failed to remove download: %s", e.what()); } + refreshList(); } @@ -1710,7 +1720,7 @@ void DownloadManager::metaDataChanged() void DownloadManager::directoryChanged(const QString&) { - if(m_DirWatcherDisabler==0) + if(DownloadManager::m_DirWatcherDisabler==0) refreshList(); } diff --git a/src/downloadmanager.h b/src/downloadmanager.h index 74627be5..aa859b13 100644 --- a/src/downloadmanager.h +++ b/src/downloadmanager.h @@ -148,12 +148,12 @@ public: * @brief disables feedback from the downlods fileSystemWhatcher untill disableDownloadsWatcherEnd() is called * **/ - void startDisableDirWatcher(); + static void startDisableDirWatcher(); /** * @brief re-enables feedback from the downlods fileSystemWhatcher after disableDownloadsWatcherStart() was called **/ - void endDisableDirWatcher(); + static void endDisableDirWatcher(); /** * @return current download directory @@ -533,7 +533,8 @@ private: //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; + static int m_DirWatcherDisabler; + std::map m_DownloadFails; -- cgit v1.3.1 From ddb40b712edf0676f6083a0ecd5a67509e60e6fe Mon Sep 17 00:00:00 2001 From: Al12rs Date: Fri, 25 May 2018 15:33:53 +0200 Subject: *Avoided some unnecessary refreshes while removing mods. *Added "Visit on Nexus" menu entry in the downloads tab. *Added confirmation message when deleting a single download. *Changed text of messages to more easily distinguish deleting from hiding. --- src/downloadlistwidget.cpp | 20 +++++++++++++++++--- src/downloadlistwidget.h | 6 ++++-- src/downloadlistwidgetcompact.cpp | 33 ++++++++++++++++++++++----------- src/downloadlistwidgetcompact.h | 7 ++++--- src/downloadmanager.cpp | 35 ++++++++++++++++++++++++++++++++--- src/downloadmanager.h | 2 ++ src/mainwindow.cpp | 11 +++++++---- 7 files changed, 88 insertions(+), 26 deletions(-) (limited to 'src/downloadmanager.h') diff --git a/src/downloadlistwidget.cpp b/src/downloadlistwidget.cpp index d7bd01bb..75470056 100644 --- a/src/downloadlistwidget.cpp +++ b/src/downloadlistwidget.cpp @@ -245,7 +245,11 @@ void DownloadListWidgetDelegate::issueQueryInfo() void DownloadListWidgetDelegate::issueDelete() { - emit removeDownload(m_ContextRow, true); + if (QMessageBox::question(nullptr, tr("Delete Files?"), + tr("This will permanently delete the selected download."), + QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) { + emit removeDownload(m_ContextRow, true); + } } void DownloadListWidgetDelegate::issueRemoveFromView() @@ -263,6 +267,11 @@ void DownloadListWidgetDelegate::issueRestoreToViewAll() emit restoreDownload(-1); } +void DownloadListWidgetDelegate::issueVisitOnNexus() +{ + emit visitOnNexus(m_ContextRow); +} + void DownloadListWidgetDelegate::issueCancel() { @@ -281,7 +290,7 @@ void DownloadListWidgetDelegate::issueResume() void DownloadListWidgetDelegate::issueDeleteAll() { - if (QMessageBox::question(nullptr, tr("Are you sure?"), + if (QMessageBox::question(nullptr, tr("Delete Files?"), tr("This will remove all finished downloads from this list and from disk."), QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) { emit removeDownload(-1, true); @@ -290,7 +299,7 @@ void DownloadListWidgetDelegate::issueDeleteAll() void DownloadListWidgetDelegate::issueDeleteCompleted() { - if (QMessageBox::question(nullptr, tr("Are you sure?"), + if (QMessageBox::question(nullptr, tr("Delete Files?"), tr("This will remove all installed downloads from this list and from disk."), QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) { emit removeDownload(-2, true); @@ -340,7 +349,12 @@ bool DownloadListWidgetDelegate::editorEvent(QEvent *event, QAbstractItemModel * menu.addAction(tr("Install"), this, SLOT(issueInstall())); if (m_Manager->isInfoIncomplete(m_ContextRow)) { menu.addAction(tr("Query Info"), this, SLOT(issueQueryInfo())); + }else { + menu.addAction(tr("Visit on Nexus"), this,SLOT(issueVisitOnNexus())); } + + menu.addSeparator(); + menu.addAction(tr("Delete"), this, SLOT(issueDelete())); if (hidden) { menu.addAction(tr("Un-Hide"), this, SLOT(issueRestoreToView())); diff --git a/src/downloadlistwidget.h b/src/downloadlistwidget.h index 6e628cc7..e2746f3a 100644 --- a/src/downloadlistwidget.h +++ b/src/downloadlistwidget.h @@ -71,6 +71,7 @@ signals: void cancelDownload(int index); void pauseDownload(int index); void resumeDownload(int index); + void visitOnNexus(int index); protected: @@ -80,7 +81,7 @@ protected: private: - + void drawCache(QPainter *painter, const QStyleOptionViewItem &option, const QPixmap &cache) const; private slots: @@ -89,7 +90,8 @@ private slots: void issueDelete(); void issueRemoveFromView(); void issueRestoreToView(); - void issueRestoreToViewAll(); + void issueRestoreToViewAll(); + void issueVisitOnNexus(); void issueCancel(); void issuePause(); void issueResume(); diff --git a/src/downloadlistwidgetcompact.cpp b/src/downloadlistwidgetcompact.cpp index 97e3655b..cdce8d7f 100644 --- a/src/downloadlistwidgetcompact.cpp +++ b/src/downloadlistwidgetcompact.cpp @@ -209,7 +209,11 @@ void DownloadListWidgetCompactDelegate::issueQueryInfo() void DownloadListWidgetCompactDelegate::issueDelete() { - emit removeDownload(m_ContextIndex.row(), true); + if (QMessageBox::question(nullptr, tr("Are you sure?"), + tr("This will permanently delete the selected download."), + QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) { + emit removeDownload(m_ContextIndex.row(), true); + } } void DownloadListWidgetCompactDelegate::issueRemoveFromView() @@ -217,6 +221,11 @@ void DownloadListWidgetCompactDelegate::issueRemoveFromView() emit removeDownload(m_ContextIndex.row(), false); } +void DownloadListWidgetCompactDelegate::issueVisitOnNexus() +{ + emit visitOnNexus(m_ContextIndex.row()); +} + void DownloadListWidgetCompactDelegate::issueRestoreToView() { emit restoreDownload(m_ContextIndex.row()); @@ -305,7 +314,10 @@ bool DownloadListWidgetCompactDelegate::editorEvent(QEvent *event, QAbstractItem menu.addAction(tr("Install"), this, SLOT(issueInstall())); if (m_Manager->isInfoIncomplete(m_ContextIndex.row())) { menu.addAction(tr("Query Info"), this, SLOT(issueQueryInfo())); + }else { + menu.addAction(tr("Visit on Nexus"), this, SLOT(issueVisitOnNexus())); } + menu.addSeparator(); menu.addAction(tr("Delete"), this, SLOT(issueDelete())); if (hidden) { menu.addAction(tr("Un-Hide"), this, SLOT(issueRestoreToView())); @@ -324,15 +336,15 @@ bool DownloadListWidgetCompactDelegate::editorEvent(QEvent *event, QAbstractItem } menu.addAction(tr("Delete Installed..."), this, SLOT(issueDeleteCompleted())); menu.addAction(tr("Delete All..."), this, SLOT(issueDeleteAll())); - if (!hidden) { - menu.addSeparator(); - menu.addAction(tr("Hide Installed..."), this, SLOT(issueRemoveFromViewCompleted())); - menu.addAction(tr("Hide All..."), this, SLOT(issueRemoveFromViewAll())); - } - if (hidden) { - menu.addSeparator(); - menu.addAction(tr("Un-Hide All..."), this, SLOT(issueRestoreToViewAll())); - } + if (!hidden) { + menu.addSeparator(); + menu.addAction(tr("Hide Installed..."), this, SLOT(issueRemoveFromViewCompleted())); + menu.addAction(tr("Hide All..."), this, SLOT(issueRemoveFromViewAll())); + } + if (hidden) { + menu.addSeparator(); + menu.addAction(tr("Un-Hide All..."), this, SLOT(issueRestoreToViewAll())); + } menu.exec(mouseEvent->globalPos()); event->accept(); @@ -345,4 +357,3 @@ bool DownloadListWidgetCompactDelegate::editorEvent(QEvent *event, QAbstractItem return QItemDelegate::editorEvent(event, model, option, index); } - diff --git a/src/downloadlistwidgetcompact.h b/src/downloadlistwidgetcompact.h index df1a5f58..28a376eb 100644 --- a/src/downloadlistwidgetcompact.h +++ b/src/downloadlistwidgetcompact.h @@ -35,7 +35,7 @@ class DownloadListWidgetCompact; class DownloadListWidgetCompact : public QWidget { Q_OBJECT - + public: explicit DownloadListWidgetCompact(QWidget *parent = 0); ~DownloadListWidgetCompact(); @@ -69,6 +69,7 @@ signals: void cancelDownload(int index); void pauseDownload(int index); void resumeDownload(int index); + void visitOnNexus(int index); protected: @@ -87,7 +88,8 @@ private slots: void issueDelete(); void issueRemoveFromView(); void issueRestoreToView(); - void issueRestoreToViewAll(); + void issueRestoreToViewAll(); + void issueVisitOnNexus(); void issueCancel(); void issuePause(); void issueResume(); @@ -120,4 +122,3 @@ private: }; #endif // DOWNLOADLISTWIDGETCOMPACT_H - diff --git a/src/downloadmanager.cpp b/src/downloadmanager.cpp index 93a46d78..0341152a 100644 --- a/src/downloadmanager.cpp +++ b/src/downloadmanager.cpp @@ -36,6 +36,7 @@ along with Mod Organizer. If not, see . #include #include #include +#include #include #include #include @@ -607,7 +608,7 @@ void DownloadManager::removeFile(int index, bool deleteFile) if(!download->m_Hidden) metaSettings.setValue("removed", true); } - + endDisableDirWatcher(); } @@ -651,7 +652,7 @@ void DownloadManager::restoreDownload(int index) index = 0; for (QVector::const_iterator iter = m_ActiveDownloads.begin(); iter != m_ActiveDownloads.end(); ++iter ) { - + if ((*iter)->m_State >= minState) { restoreDownload(index); } @@ -876,6 +877,34 @@ void DownloadManager::queryInfo(int index) setState(info, STATE_FETCHINGMODINFO); } +void DownloadManager::visitOnNexus(int index) +{ + if ((index < 0) || (index >= m_ActiveDownloads.size())) { + reportError(tr("VisitNexus: invalid download index %1").arg(index)); + return; + } + DownloadInfo *info = m_ActiveDownloads[index]; + + if (info->m_FileInfo->repository != "Nexus") { + qWarning("Visiting mod page is currently only possible with Nexus"); + return; + } + + if (info->m_State < DownloadManager::STATE_READY) { + // UI shouldn't allow this + return; + } + int modID = info->m_FileInfo->modID; + + QString gameName = info->m_FileInfo->gameName; + if (modID > 0) { + QDesktopServices::openUrl(QUrl(m_NexusInterface->getModURL(modID, gameName))); + } + else { + emit showMessage(tr("Nexus ID for this Mod is unknown")); + } +} + int DownloadManager::numTotalDownloads() const { @@ -1756,4 +1785,4 @@ void DownloadManager::checkDownloadTimeout() resumeDownload(i); } } -} \ No newline at end of file +} diff --git a/src/downloadmanager.h b/src/downloadmanager.h index aa859b13..24bc6d7f 100644 --- a/src/downloadmanager.h +++ b/src/downloadmanager.h @@ -435,6 +435,8 @@ public slots: void queryInfo(int index); + void visitOnNexus(int index); + void nxmDescriptionAvailable(QString gameName, int modID, QVariant userData, QVariant resultData, int requestID); void nxmFilesAvailable(QString gameName, int modID, QVariant userData, QVariant resultData, int requestID); diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index a428d5b3..7ddd35c5 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -254,7 +254,7 @@ MainWindow::MainWindow(QSettings &initSettings actionToToolButton(ui->actionHelp); createHelpWidget(); - + for (QAction *action : ui->toolBar->actions()) { if (action->isSeparator()) { // insert spacers @@ -400,7 +400,7 @@ MainWindow::MainWindow(QSettings &initSettings new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_Enter), this, SLOT(openExplorer_activated())); new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_Return), this, SLOT(openExplorer_activated())); - + new QShortcut(QKeySequence::Refresh, this, SLOT(refreshProfile_activated())); @@ -2336,9 +2336,11 @@ void MainWindow::removeMod_clicked() tr("Remove the following mods?
    %1
").arg(mods), QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) { // use mod names instead of indexes because those become invalid during the removal + DownloadManager::startDisableDirWatcher(); for (QString name : modNames) { m_OrganizerCore.modList()->removeRowForce(ModInfo::getIndex(name), QModelIndex()); } + DownloadManager::endDisableDirWatcher(); } } else { m_OrganizerCore.modList()->removeRow(m_ContextRow, QModelIndex()); @@ -2500,7 +2502,7 @@ void MainWindow::displayModInformation(ModInfo::Ptr modInfo, unsigned int index, connect(&dialog, SIGNAL(modOpenPrev(int)), this, SLOT(modOpenPrev(int)), Qt::QueuedConnection); connect(&dialog, SIGNAL(originModified(int)), this, SLOT(originModified(int))); connect(&dialog, SIGNAL(endorseMod(ModInfo::Ptr)), this, SLOT(endorseMod(ModInfo::Ptr))); - + //Open the tab first if we want to use the standard indexes of the tabs. if (tab != -1) { dialog.openTab(tab); @@ -2687,7 +2689,7 @@ void MainWindow::openExplorer_activated() QModelIndex idx = selection->currentIndex(); QString fileName = idx.data().toString(); - + ModInfo::Ptr modInfo = ModInfo::getByIndex(ModInfo::getIndex(m_OrganizerCore.pluginList()->origin(fileName))); std::vector flags = modInfo->getFlags(); @@ -4239,6 +4241,7 @@ void MainWindow::updateDownloadListDelegate() connect(ui->downloadView->itemDelegate(), SIGNAL(installDownload(int)), &m_OrganizerCore, SLOT(installDownload(int))); connect(ui->downloadView->itemDelegate(), SIGNAL(queryInfo(int)), m_OrganizerCore.downloadManager(), SLOT(queryInfo(int))); + connect(ui->downloadView->itemDelegate(), SIGNAL(visitOnNexus(int)), m_OrganizerCore.downloadManager(), SLOT(visitOnNexus(int))); connect(ui->downloadView->itemDelegate(), SIGNAL(removeDownload(int, bool)), m_OrganizerCore.downloadManager(), SLOT(removeDownload(int, bool))); connect(ui->downloadView->itemDelegate(), SIGNAL(restoreDownload(int)), m_OrganizerCore.downloadManager(), SLOT(restoreDownload(int))); connect(ui->downloadView->itemDelegate(), SIGNAL(cancelDownload(int)), m_OrganizerCore.downloadManager(), SLOT(cancelDownload(int))); -- cgit v1.3.1 From 181de232f43941b5ffefbccca78a6076e1e854a9 Mon Sep 17 00:00:00 2001 From: Silarn Date: Mon, 25 Jun 2018 20:50:49 -0500 Subject: Potential fix for corrupted downloads --- src/downloadmanager.cpp | 5 +++-- src/downloadmanager.h | 3 ++- 2 files changed, 5 insertions(+), 3 deletions(-) (limited to 'src/downloadmanager.h') diff --git a/src/downloadmanager.cpp b/src/downloadmanager.cpp index ecbcc03b..6d8658c9 100644 --- a/src/downloadmanager.cpp +++ b/src/downloadmanager.cpp @@ -1251,6 +1251,7 @@ void DownloadManager::downloadProgress(qint64 bytesReceived, qint64 bytesTotal) try { DownloadInfo *info = findDownload(this->sender(), &index); if (info != nullptr) { + info->m_HasData = true; if (info->m_State == STATE_CANCELING) { setState(info, STATE_CANCELED); } else if (info->m_State == STATE_PAUSING) { @@ -1637,7 +1638,7 @@ void DownloadManager::downloadFinished(int index) if (info != nullptr) { QNetworkReply *reply = info->m_Reply; QByteArray data; - if (reply->isOpen()) { + if (reply->isOpen() && info->m_HasData) { data = reply->readAll(); info->m_Output.write(data); } @@ -1666,7 +1667,7 @@ void DownloadManager::downloadFinished(int index) if (info->m_State == STATE_CANCELING) { setState(info, STATE_CANCELED); } else if (info->m_State == STATE_PAUSING) { - if (info->m_Output.isOpen()) { + if (info->m_Output.isOpen() && info->m_HasData) { info->m_Output.write(info->m_Reply->readAll()); } setState(info, STATE_PAUSED); diff --git a/src/downloadmanager.h b/src/downloadmanager.h index 24bc6d7f..fa3764b7 100644 --- a/src/downloadmanager.h +++ b/src/downloadmanager.h @@ -78,6 +78,7 @@ private: qint64 m_PreResumeSize; std::pair m_Progress; std::tuple m_SpeedDiff; + bool m_HasData; DownloadState m_State; int m_CurrentUrl; QStringList m_Urls; @@ -115,7 +116,7 @@ private: private: static unsigned int s_NextDownloadID; private: - DownloadInfo() : m_TotalSize(0), m_ReQueried(false), m_Hidden(false), m_SpeedDiff(std::tuple(0,0,0,0,0)) {} + DownloadInfo() : m_TotalSize(0), m_ReQueried(false), m_Hidden(false), m_SpeedDiff(std::tuple(0,0,0,0,0)), m_HasData(false) {} }; public: -- cgit v1.3.1 From 2524d65441e99cbb14037144b8af60e1d25e1179 Mon Sep 17 00:00:00 2001 From: Al12rs Date: Mon, 16 Jul 2018 20:56:47 +0200 Subject: Added "Open in Folder" option to downloads tab. --- src/downloadlistwidget.cpp | 10 +++++++++- src/downloadlistwidget.h | 2 ++ src/downloadlistwidgetcompact.cpp | 9 ++++++++- src/downloadlistwidgetcompact.h | 2 ++ src/downloadmanager.cpp | 25 +++++++++++++++++++++++++ src/downloadmanager.h | 2 ++ src/mainwindow.cpp | 1 + 7 files changed, 49 insertions(+), 2 deletions(-) (limited to 'src/downloadmanager.h') diff --git a/src/downloadlistwidget.cpp b/src/downloadlistwidget.cpp index 5ab5d397..0ef408fb 100644 --- a/src/downloadlistwidget.cpp +++ b/src/downloadlistwidget.cpp @@ -272,6 +272,10 @@ void DownloadListWidgetDelegate::issueVisitOnNexus() emit visitOnNexus(m_ContextRow); } +void DownloadListWidgetDelegate::issueOpenInDownloadsFolder() +{ + emit openInDownloadsFolder(m_ContextRow); +} void DownloadListWidgetDelegate::issueCancel() { @@ -352,6 +356,8 @@ bool DownloadListWidgetDelegate::editorEvent(QEvent *event, QAbstractItemModel * }else { menu.addAction(tr("Visit on Nexus"), this,SLOT(issueVisitOnNexus())); } + + menu.addAction(tr("Show in Folder"), this, SLOT(issueOpenInDownloadsFolder())); menu.addSeparator(); @@ -364,9 +370,11 @@ bool DownloadListWidgetDelegate::editorEvent(QEvent *event, QAbstractItemModel * } else if (state == DownloadManager::STATE_DOWNLOADING){ menu.addAction(tr("Cancel"), this, SLOT(issueCancel())); menu.addAction(tr("Pause"), this, SLOT(issuePause())); + menu.addAction(tr("Show in Folder"), this, SLOT(issueOpenInDownloadsFolder())); } else if ((state == DownloadManager::STATE_PAUSED) || (state == DownloadManager::STATE_ERROR) || (state == DownloadManager::STATE_PAUSING)) { - menu.addAction(tr("Remove"), this, SLOT(issueDelete())); + menu.addAction(tr("Delete"), this, SLOT(issueDelete())); menu.addAction(tr("Resume"), this, SLOT(issueResume())); + menu.addAction(tr("Show in Folder"), this, SLOT(issueOpenInDownloadsFolder())); } menu.addSeparator(); diff --git a/src/downloadlistwidget.h b/src/downloadlistwidget.h index e2746f3a..4dcbea99 100644 --- a/src/downloadlistwidget.h +++ b/src/downloadlistwidget.h @@ -72,6 +72,7 @@ signals: void pauseDownload(int index); void resumeDownload(int index); void visitOnNexus(int index); + void openInDownloadsFolder(int index); protected: @@ -92,6 +93,7 @@ private slots: void issueRestoreToView(); void issueRestoreToViewAll(); void issueVisitOnNexus(); + void issueOpenInDownloadsFolder(); void issueCancel(); void issuePause(); void issueResume(); diff --git a/src/downloadlistwidgetcompact.cpp b/src/downloadlistwidgetcompact.cpp index 99cbd7cb..1d1805ef 100644 --- a/src/downloadlistwidgetcompact.cpp +++ b/src/downloadlistwidgetcompact.cpp @@ -226,6 +226,11 @@ void DownloadListWidgetCompactDelegate::issueVisitOnNexus() emit visitOnNexus(m_ContextIndex.row()); } +void DownloadListWidgetCompactDelegate::issueOpenInDownloadsFolder() +{ + emit openInDownloadsFolder(m_ContextIndex.row()); +} + void DownloadListWidgetCompactDelegate::issueRestoreToView() { emit restoreDownload(m_ContextIndex.row()); @@ -317,6 +322,7 @@ bool DownloadListWidgetCompactDelegate::editorEvent(QEvent *event, QAbstractItem }else { menu.addAction(tr("Visit on Nexus"), this, SLOT(issueVisitOnNexus())); } + menu.addAction(tr("Show in Folder"), this, SLOT(issueOpenInDownloadsFolder())); menu.addSeparator(); menu.addAction(tr("Delete"), this, SLOT(issueDelete())); if (hidden) { @@ -327,11 +333,12 @@ bool DownloadListWidgetCompactDelegate::editorEvent(QEvent *event, QAbstractItem } else if (state == DownloadManager::STATE_DOWNLOADING){ menu.addAction(tr("Cancel"), this, SLOT(issueCancel())); menu.addAction(tr("Pause"), this, SLOT(issuePause())); + menu.addAction(tr("Show in Folder"), this, SLOT(issueOpenInDownloadsFolder())); } else if ((state == DownloadManager::STATE_PAUSED) || (state == DownloadManager::STATE_ERROR) || (state == DownloadManager::STATE_PAUSING)) { menu.addAction(tr("Remove"), this, SLOT(issueDelete())); menu.addAction(tr("Resume"), this, SLOT(issueResume())); + menu.addAction(tr("Show in Folder"), this, SLOT(issueOpenInDownloadsFolder())); } - menu.addSeparator(); } menu.addAction(tr("Delete Installed..."), this, SLOT(issueDeleteCompleted())); diff --git a/src/downloadlistwidgetcompact.h b/src/downloadlistwidgetcompact.h index 28a376eb..c25b7e99 100644 --- a/src/downloadlistwidgetcompact.h +++ b/src/downloadlistwidgetcompact.h @@ -70,6 +70,7 @@ signals: void pauseDownload(int index); void resumeDownload(int index); void visitOnNexus(int index); + void openInDownloadsFolder(int index); protected: @@ -90,6 +91,7 @@ private slots: void issueRestoreToView(); void issueRestoreToViewAll(); void issueVisitOnNexus(); + void issueOpenInDownloadsFolder(); void issueCancel(); void issuePause(); void issueResume(); diff --git a/src/downloadmanager.cpp b/src/downloadmanager.cpp index 9761fee4..1a2934a5 100644 --- a/src/downloadmanager.cpp +++ b/src/downloadmanager.cpp @@ -911,6 +911,31 @@ void DownloadManager::visitOnNexus(int index) } } +void DownloadManager::openInDownloadsFolder(int index) +{ + if ((index < 0) || (index >= m_ActiveDownloads.size())) { + reportError(tr("VisitNexus: invalid download index %1").arg(index)); + return; + } + QString params = "/select,\""; + QDir path = QDir(m_OutputDirectory); + if (path.exists(getFileName(index))) { + params = params + QDir::toNativeSeparators(getFilePath(index)) + "\""; + + ::ShellExecuteW(nullptr, nullptr, L"explorer", ToWString(params).c_str(), nullptr, SW_SHOWNORMAL); + return; + } + else if (path.exists(getFileName(index) + ".unfinished")) { + params = params + QDir::toNativeSeparators(getFilePath(index)+".unfinished") + "\""; + + ::ShellExecuteW(nullptr, nullptr, L"explorer", ToWString(params).c_str(), nullptr, SW_SHOWNORMAL); + return; + } + + ::ShellExecuteW(nullptr, L"explore", ToWString(QDir::toNativeSeparators(m_OutputDirectory)).c_str(), nullptr, nullptr, SW_SHOWNORMAL); + return; +} + int DownloadManager::numTotalDownloads() const { diff --git a/src/downloadmanager.h b/src/downloadmanager.h index fa3764b7..514402ee 100644 --- a/src/downloadmanager.h +++ b/src/downloadmanager.h @@ -438,6 +438,8 @@ public slots: void visitOnNexus(int index); + void openInDownloadsFolder(int index); + void nxmDescriptionAvailable(QString gameName, int modID, QVariant userData, QVariant resultData, int requestID); void nxmFilesAvailable(QString gameName, int modID, QVariant userData, QVariant resultData, int requestID); diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index fc666a49..436d4d26 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -4242,6 +4242,7 @@ void MainWindow::updateDownloadListDelegate() connect(ui->downloadView->itemDelegate(), SIGNAL(installDownload(int)), &m_OrganizerCore, SLOT(installDownload(int))); connect(ui->downloadView->itemDelegate(), SIGNAL(queryInfo(int)), m_OrganizerCore.downloadManager(), SLOT(queryInfo(int))); connect(ui->downloadView->itemDelegate(), SIGNAL(visitOnNexus(int)), m_OrganizerCore.downloadManager(), SLOT(visitOnNexus(int))); + connect(ui->downloadView->itemDelegate(), SIGNAL(openInDownloadsFolder(int)), m_OrganizerCore.downloadManager(), SLOT(openInDownloadsFolder(int))); connect(ui->downloadView->itemDelegate(), SIGNAL(removeDownload(int, bool)), m_OrganizerCore.downloadManager(), SLOT(removeDownload(int, bool))); connect(ui->downloadView->itemDelegate(), SIGNAL(restoreDownload(int)), m_OrganizerCore.downloadManager(), SLOT(restoreDownload(int))); connect(ui->downloadView->itemDelegate(), SIGNAL(cancelDownload(int)), m_OrganizerCore.downloadManager(), SLOT(cancelDownload(int))); -- cgit v1.3.1 From 75478f68a12c89af790ba2aae127d4834c6d44a5 Mon Sep 17 00:00:00 2001 From: Al12rs Date: Tue, 17 Jul 2018 13:32:53 +0200 Subject: Avoid asking users if they are sure they want to close of all downlaods are paused. --- src/downloadmanager.cpp | 10 ++++++++++ src/downloadmanager.h | 7 +++++++ src/mainwindow.cpp | 2 +- 3 files changed, 18 insertions(+), 1 deletion(-) (limited to 'src/downloadmanager.h') diff --git a/src/downloadmanager.cpp b/src/downloadmanager.cpp index 385d2246..beb498c1 100644 --- a/src/downloadmanager.cpp +++ b/src/downloadmanager.cpp @@ -230,6 +230,16 @@ bool DownloadManager::downloadsInProgress() return false; } +bool DownloadManager::downloadsInProgressNoPause() +{ + for (QVector::iterator iter = m_ActiveDownloads.begin(); iter != m_ActiveDownloads.end(); ++iter) { + if ((*iter)->m_State < STATE_READY && (*iter)->m_State != STATE_PAUSED) { + return true; + } + } + return false; +} + void DownloadManager::pauseAll() { diff --git a/src/downloadmanager.h b/src/downloadmanager.h index 514402ee..136ecf2a 100644 --- a/src/downloadmanager.h +++ b/src/downloadmanager.h @@ -138,6 +138,13 @@ public: **/ bool downloadsInProgress(); + /** + * @brief determine if a download is currently in progress, does not count paused ones. + * + * @return true if there is currently a download in progress (that is not paused already). + **/ + bool downloadsInProgressNoPause(); + /** * @brief set the output directory to write to * diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index f70e66a6..5999608c 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -883,7 +883,7 @@ void MainWindow::closeEvent(QCloseEvent* event) { m_closing = true; - if (m_OrganizerCore.downloadManager()->downloadsInProgress()) { + if (m_OrganizerCore.downloadManager()->downloadsInProgressNoPause()) { if (QMessageBox::question(this, tr("Downloads in progress"), tr("There are still downloads in progress, do you really want to quit?"), QMessageBox::Yes | QMessageBox::Cancel) == QMessageBox::Cancel) { -- cgit v1.3.1