diff options
| author | Al <26797547+Al12rs@users.noreply.github.com> | 2020-06-07 12:21:41 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2020-06-07 12:21:41 -0700 |
| commit | ec5a78cefa610df153063c3cbfcc42b36998a542 (patch) | |
| tree | 0345d3543d85d0aaf93b6c1b1761b8c2dc554ebd /src | |
| parent | 8b667fe69a268c7d183f60dd43ec95dbd976c47b (diff) | |
| parent | 6d7c0866859a0fe27a8055068552470b67d680e3 (diff) | |
Merge pull request #1112 from Al12rs/updateProblemsButton
Move Problems Checks on a thread and avoid redundant calls
Diffstat (limited to 'src')
| -rw-r--r-- | src/mainwindow.cpp | 61 | ||||
| -rw-r--r-- | src/mainwindow.h | 20 |
2 files changed, 55 insertions, 26 deletions
diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 477cbc70..c3a19bf4 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -266,6 +266,8 @@ MainWindow::MainWindow(Settings &settings , m_LinkToolbar(nullptr) , m_LinkDesktop(nullptr) , m_LinkStartMenu(nullptr) + , m_NumberOfProblems(0) + , m_ProblemsCheckRequired(false) { // disables incredibly slow menu fade in effect that looks and feels like crap. // this was only happening to users with the windows @@ -400,7 +402,7 @@ MainWindow::MainWindow(Settings &settings ui->bossButton->setToolTip(tr("There is no supported sort mechanism for this game. You will probably have to use a third-party tool.")); } - connect(&m_PluginContainer, SIGNAL(diagnosisUpdate()), this, SLOT(updateProblemsButton())); + connect(&m_PluginContainer, SIGNAL(diagnosisUpdate()), this, SLOT(scheduleCheckForProblems())); connect(ui->savegameList, SIGNAL(itemEntered(QListWidgetItem*)), this, SLOT(saveSelectionChanged(QListWidgetItem*))); @@ -473,7 +475,8 @@ MainWindow::MainWindow(Settings &settings setFilterShortcuts(ui->downloadView, ui->downloadFilterEdit); m_UpdateProblemsTimer.setSingleShot(true); - connect(&m_UpdateProblemsTimer, SIGNAL(timeout()), this, SLOT(updateProblemsButton())); + connect(&m_UpdateProblemsTimer, &QTimer::timeout, this, &MainWindow::checkForProblemsAsync); + connect(this, &MainWindow::checkForProblemsDone, this, &MainWindow::updateProblemsButton, Qt::ConnectionType::QueuedConnection); m_SaveMetaTimer.setSingleShot(false); connect(&m_SaveMetaTimer, SIGNAL(timeout()), this, SLOT(saveModMetas())); @@ -1000,21 +1003,19 @@ void MainWindow::on_centralWidget_customContextMenuRequested(const QPoint &pos) createPopupMenu()->exec(ui->centralWidget->mapToGlobal(pos)); } -void MainWindow::scheduleUpdateButton() +void MainWindow::scheduleCheckForProblems() { if (!m_UpdateProblemsTimer.isActive()) { - m_UpdateProblemsTimer.start(1000); + m_UpdateProblemsTimer.start(500); } } void MainWindow::updateProblemsButton() { - TimeThis tt("MainWindow::updateProblemsButton()"); - // if the current stylesheet doesn't provide an icon, this is used instead const char* DefaultIconName = ":/MO/gui/warning"; - const std::size_t numProblems = checkForProblems(); + const std::size_t numProblems = m_NumberOfProblems; // original icon without a count painted on it const QIcon original = m_originalNotificationIcon.isNull() ? @@ -1097,19 +1098,34 @@ bool MainWindow::errorReported(QString &logFile) return false; } +QFuture<void> MainWindow::checkForProblemsAsync() { + return QtConcurrent::run([this]() { + checkForProblemsImpl(); + }); +} -size_t MainWindow::checkForProblems() +void MainWindow::checkForProblemsImpl() { - size_t numProblems = 0; - for (QObject *pluginObj : m_PluginContainer.plugins<QObject>()) { - IPlugin *plugin = qobject_cast<IPlugin*>(pluginObj); - if (plugin == nullptr || plugin->isActive()) { - IPluginDiagnose *diagnose = qobject_cast<IPluginDiagnose*>(pluginObj); - if (diagnose != nullptr) - numProblems += diagnose->activeProblems().size(); + m_ProblemsCheckRequired = true; + + std::scoped_lock lk(m_CheckForProblemsMutex); + + // another thread might already have checked while this one was waiting on the lock + if (m_ProblemsCheckRequired) { + m_ProblemsCheckRequired = false; + TimeThis tt("MainWindow::checkForProblemsImpl()"); + size_t numProblems = 0; + for (QObject *pluginObj : m_PluginContainer.plugins<QObject>()) { + IPlugin *plugin = qobject_cast<IPlugin*>(pluginObj); + if (plugin == nullptr || plugin->isActive()) { + IPluginDiagnose *diagnose = qobject_cast<IPluginDiagnose*>(pluginObj); + if (diagnose != nullptr) + numProblems += diagnose->activeProblems().size(); + } } + m_NumberOfProblems = numProblems; + emit checkForProblemsDone(); } - return numProblems; } void MainWindow::about() @@ -1353,7 +1369,7 @@ void MainWindow::showEvent(QShowEvent *event) m_OrganizerCore.settings().nexus().registerAsNXMHandler(false); m_WasVisible = true; - updateProblemsButton(); + updateProblemsButton(); } } @@ -2456,7 +2472,7 @@ void MainWindow::directory_refreshed() { // some problem-reports may rely on the virtual directory tree so they need to be updated // now - updateProblemsButton(); + scheduleCheckForProblems(); //Some better check for the current tab is needed. if (ui->tabWidget->currentIndex() == 2) { @@ -3782,7 +3798,7 @@ void MainWindow::clearOverwrite() for (auto f : overwriteDir.entryList(QDir::AllDirs | QDir::Files | QDir::NoDotAndDotDot)) delList.push_back(overwriteDir.absoluteFilePath(f)); if (shellDelete(delList, true)) { - updateProblemsButton(); + scheduleCheckForProblems(); m_OrganizerCore.refreshModList(); } else { const auto e = GetLastError(); @@ -5162,7 +5178,6 @@ void MainWindow::languageChange(const QString &newLanguage) createHelpMenu(); updateDownloadView(); - updateProblemsButton(); QMenu *listOptionsMenu = new QMenu(ui->listOptionsBtn); initModListContextMenu(listOptionsMenu); @@ -5869,12 +5884,14 @@ void MainWindow::on_bsaList_itemChanged(QTreeWidgetItem*, int) void MainWindow::on_actionNotifications_triggered() { - updateProblemsButton(); + auto future = checkForProblemsAsync(); + + future.waitForFinished(); ProblemsDialog problems(m_PluginContainer.plugins<QObject>(), this); problems.exec(); - updateProblemsButton(); + scheduleCheckForProblems(); } void MainWindow::on_actionChange_Game_triggered() diff --git a/src/mainwindow.h b/src/mainwindow.h index 25d09584..94626ff3 100644 --- a/src/mainwindow.h +++ b/src/mainwindow.h @@ -178,6 +178,8 @@ signals: void modListDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight); + void checkForProblemsDone(); + protected: virtual void showEvent(QShowEvent *event); @@ -244,8 +246,9 @@ private: void fixCategories(); bool extractProgress(QProgressDialog &extractProgress, int percentage, std::string fileName); - - size_t checkForProblems(); + + // Performs checks, sets the m_NumberOfProblems and signals checkForProblemsDone(). + void checkForProblemsImpl(); void setCategoryListVisible(bool visible); @@ -267,8 +270,6 @@ private: QMenu *openFolderMenu(); - void scheduleUpdateButton(); - QDir currentSavesDir() const; void startMonitorSaves(); @@ -358,6 +359,10 @@ private: // when painting the count QIcon m_originalNotificationIcon; + std::atomic<std::size_t> m_NumberOfProblems; + std::atomic<bool> m_ProblemsCheckRequired; + std::mutex m_CheckForProblemsMutex; + Executable* getSelectedExecutable(); private slots: @@ -523,8 +528,15 @@ private slots: void checkBSAList(); + // Only visually update the problems icon. void updateProblemsButton(); + // Queue a problem check to allow collapsing of multiple requests in short amount of time. + void scheduleCheckForProblems(); + + // Perform the actual problem check in another thread. + QFuture<void> checkForProblemsAsync(); + void saveModMetas(); void updateStyle(const QString &style); |
