From ee479260d0e90eb56e5e2e66f10c528271f60687 Mon Sep 17 00:00:00 2001
From: spycrab <spycrab@users.noreply.github.com>
Date: Wed, 6 Jun 2018 10:52:27 +0200
Subject: [PATCH] Qt: Add option to disable auto-refresh

---
 .../Core/DolphinQt2/GameList/GameTracker.cpp  | 46 ++++++++++++++++---
 Source/Core/DolphinQt2/GameList/GameTracker.h |  5 ++
 Source/Core/DolphinQt2/Settings.cpp           | 15 ++++++
 Source/Core/DolphinQt2/Settings.h             |  3 ++
 Source/Core/DolphinQt2/Settings/PathPane.cpp  | 15 ++++--
 5 files changed, 74 insertions(+), 10 deletions(-)

diff --git a/Source/Core/DolphinQt2/GameList/GameTracker.cpp b/Source/Core/DolphinQt2/GameList/GameTracker.cpp
index b585fe88fd..71f4db70d6 100644
--- a/Source/Core/DolphinQt2/GameList/GameTracker.cpp
+++ b/Source/Core/DolphinQt2/GameList/GameTracker.cpp
@@ -30,6 +30,15 @@ GameTracker::GameTracker(QObject* parent) : QFileSystemWatcher(parent)
 
   connect(this, &QFileSystemWatcher::directoryChanged, this, &GameTracker::UpdateDirectory);
   connect(this, &QFileSystemWatcher::fileChanged, this, &GameTracker::UpdateFile);
+  connect(&Settings::Instance(), &Settings::AutoRefreshToggled, this, [this] {
+    const auto paths = Settings::Instance().GetPaths();
+
+    for (const auto& path : paths)
+    {
+      Settings::Instance().RemovePath(path);
+      Settings::Instance().AddPath(path);
+    }
+  });
 
   m_load_thread.Reset([this](Command command) {
     switch (command.type)
@@ -110,6 +119,31 @@ void GameTracker::StartInternal()
     m_cache.Save();
 }
 
+bool GameTracker::AddPath(const QString& dir)
+{
+  if (Settings::Instance().IsAutoRefreshEnabled())
+    return addPath(dir);
+
+  m_tracked_paths.push_back(dir);
+
+  return true;
+}
+
+bool GameTracker::RemovePath(const QString& dir)
+{
+  if (Settings::Instance().IsAutoRefreshEnabled())
+    return removePath(dir);
+
+  const auto index = m_tracked_paths.indexOf(dir);
+
+  if (index == -1)
+    return false;
+
+  m_tracked_paths.remove(index);
+
+  return true;
+}
+
 void GameTracker::AddDirectory(const QString& dir)
 {
   m_load_thread.EmplaceItem(Command{CommandType::AddDirectory, dir});
@@ -140,7 +174,7 @@ void GameTracker::AddDirectoryInternal(const QString& dir)
 {
   if (!QFileInfo(dir).exists())
     return;
-  addPath(dir);
+  AddPath(dir);
   UpdateDirectoryInternal(dir);
 }
 
@@ -154,7 +188,7 @@ static std::unique_ptr<QDirIterator> GetIterator(const QString& dir)
 
 void GameTracker::RemoveDirectoryInternal(const QString& dir)
 {
-  removePath(dir);
+  RemovePath(dir);
   auto it = GetIterator(dir);
   while (it->hasNext())
   {
@@ -164,7 +198,7 @@ void GameTracker::RemoveDirectoryInternal(const QString& dir)
       m_tracked_files[path].remove(dir);
       if (m_tracked_files[path].empty())
       {
-        removePath(path);
+        RemovePath(path);
         m_tracked_files.remove(path);
         if (m_started)
           emit GameRemoved(path.toStdString());
@@ -188,7 +222,7 @@ void GameTracker::UpdateDirectoryInternal(const QString& dir)
     }
     else
     {
-      addPath(path);
+      AddPath(path);
       m_tracked_files[path] = QSet<QString>{dir};
       LoadGame(path);
     }
@@ -214,10 +248,10 @@ void GameTracker::UpdateFileInternal(const QString& file)
   {
     if (m_started)
       GameRemoved(file.toStdString());
-    addPath(file);
+    AddPath(file);
     LoadGame(file);
   }
-  else if (removePath(file))
+  else if (RemovePath(file))
   {
     m_tracked_files.remove(file);
     if (m_started)
diff --git a/Source/Core/DolphinQt2/GameList/GameTracker.h b/Source/Core/DolphinQt2/GameList/GameTracker.h
index 0504e06bab..9a1e9f353a 100644
--- a/Source/Core/DolphinQt2/GameList/GameTracker.h
+++ b/Source/Core/DolphinQt2/GameList/GameTracker.h
@@ -11,6 +11,7 @@
 #include <QMap>
 #include <QSet>
 #include <QString>
+#include <QVector>
 
 #include "Common/Event.h"
 #include "Common/WorkQueueThread.h"
@@ -54,6 +55,9 @@ private:
   QSet<QString> FindMissingFiles(const QString& dir);
   void LoadGame(const QString& path);
 
+  bool AddPath(const QString& path);
+  bool RemovePath(const QString& path);
+
   enum class CommandType
   {
     LoadCache,
@@ -72,6 +76,7 @@ private:
 
   // game path -> directories that track it
   QMap<QString, QSet<QString>> m_tracked_files;
+  QVector<QString> m_tracked_paths;
   Common::WorkQueueThread<Command> m_load_thread;
   UICommon::GameFileCache m_cache;
   Common::Event m_cache_loaded_event;
diff --git a/Source/Core/DolphinQt2/Settings.cpp b/Source/Core/DolphinQt2/Settings.cpp
index b377b833ea..65097a2825 100644
--- a/Source/Core/DolphinQt2/Settings.cpp
+++ b/Source/Core/DolphinQt2/Settings.cpp
@@ -133,6 +133,21 @@ void Settings::ReloadTitleDB()
   emit TitleDBReloadRequested();
 }
 
+bool Settings::IsAutoRefreshEnabled() const
+{
+  return GetQSettings().value(QStringLiteral("gamelist/autorefresh"), true).toBool();
+}
+
+void Settings::SetAutoRefreshEnabled(bool enabled)
+{
+  if (IsAutoRefreshEnabled() == enabled)
+    return;
+
+  GetQSettings().setValue(QStringLiteral("gamelist/autorefresh"), enabled);
+
+  emit AutoRefreshToggled(enabled);
+}
+
 QString Settings::GetDefaultGame() const
 {
   return QString::fromStdString(SConfig::GetInstance().m_strDefaultISO);
diff --git a/Source/Core/DolphinQt2/Settings.h b/Source/Core/DolphinQt2/Settings.h
index 27082ae491..9e9a8fb9a0 100644
--- a/Source/Core/DolphinQt2/Settings.h
+++ b/Source/Core/DolphinQt2/Settings.h
@@ -71,6 +71,8 @@ public:
   void SetDefaultGame(QString path);
   void ReloadPath(const QString& qpath);
   void ReloadTitleDB();
+  bool IsAutoRefreshEnabled() const;
+  void SetAutoRefreshEnabled(bool enabled);
 
   // Emulation
   int GetStateSlot() const;
@@ -137,6 +139,7 @@ signals:
   void DefaultGameChanged(const QString&);
   void PathReloadRequested(const QString&);
   void TitleDBReloadRequested();
+  void AutoRefreshToggled(bool enabled);
   void HideCursorChanged();
   void KeepWindowOnTopChanged(bool top);
   void VolumeChanged(int volume);
diff --git a/Source/Core/DolphinQt2/Settings/PathPane.cpp b/Source/Core/DolphinQt2/Settings/PathPane.cpp
index 69062f6e32..ee6441d7e7 100644
--- a/Source/Core/DolphinQt2/Settings/PathPane.cpp
+++ b/Source/Core/DolphinQt2/Settings/PathPane.cpp
@@ -127,20 +127,27 @@ QGroupBox* PathPane::MakeGameFolderBox()
 
   m_remove_path->setEnabled(false);
 
-  auto* checkbox = new QCheckBox(tr("Search Subfolders"));
-  checkbox->setChecked(SConfig::GetInstance().m_RecursiveISOFolder);
+  auto* recursive_checkbox = new QCheckBox(tr("Search Subfolders"));
+  recursive_checkbox->setChecked(SConfig::GetInstance().m_RecursiveISOFolder);
+
+  auto* auto_checkbox = new QCheckBox(tr("Check for Game List Changes in the Background"));
+  auto_checkbox->setChecked(Settings::Instance().IsAutoRefreshEnabled());
 
   hlayout->addWidget(add);
   hlayout->addWidget(m_remove_path);
   vlayout->addLayout(hlayout);
-  vlayout->addWidget(checkbox);
+  vlayout->addWidget(recursive_checkbox);
+  vlayout->addWidget(auto_checkbox);
 
-  connect(checkbox, &QCheckBox::toggled, this, [](bool checked) {
+  connect(recursive_checkbox, &QCheckBox::toggled, this, [](bool checked) {
     SConfig::GetInstance().m_RecursiveISOFolder = checked;
     for (const auto& path : Settings::Instance().GetPaths())
       Settings::Instance().ReloadPath(path);
   });
 
+  connect(auto_checkbox, &QCheckBox::toggled, &Settings::Instance(),
+          &Settings::SetAutoRefreshEnabled);
+
   connect(add, &QPushButton::pressed, this, &PathPane::Browse);
   connect(m_remove_path, &QPushButton::pressed, this, &PathPane::RemovePath);