1 // Copyright 2015 Dolphin Emulator Project 2 // Licensed under GPLv2+ 3 // Refer to the license.txt file included. 4 5 #pragma once 6 7 #include <memory> 8 #include <string> 9 10 #include <QFileSystemWatcher> 11 #include <QMap> 12 #include <QSet> 13 #include <QString> 14 #include <QVector> 15 16 #include "Common/Event.h" 17 #include "Common/WorkQueueThread.h" 18 #include "UICommon/GameFileCache.h" 19 20 namespace UICommon 21 { 22 class GameFile; 23 } 24 25 // Watches directories and loads GameFiles in a separate thread. 26 // To use this, just add directories using AddDirectory, and listen for the 27 // GameLoaded and GameRemoved signals. 28 class GameTracker final : public QFileSystemWatcher 29 { 30 Q_OBJECT 31 32 public: 33 explicit GameTracker(QObject* parent = nullptr); 34 35 // A GameTracker won't emit any signals until this function has been called. 36 // Before you call this function, make sure to call AddDirectory for all 37 // directories you want to track, otherwise games will briefly disappear 38 // until you call AddDirectory and the GameTracker finishes scanning the file system. 39 void Start(); 40 41 void AddDirectory(const QString& dir); 42 void RemoveDirectory(const QString& dir); 43 void RefreshAll(); 44 void PurgeCache(); 45 46 signals: 47 void GameLoaded(const std::shared_ptr<const UICommon::GameFile>& game); 48 void GameUpdated(const std::shared_ptr<const UICommon::GameFile>& game); 49 void GameRemoved(const std::string& path); 50 51 private: 52 void LoadCache(); 53 void StartInternal(); 54 void UpdateDirectory(const QString& dir); 55 void UpdateFile(const QString& path); 56 void AddDirectoryInternal(const QString& dir); 57 void RemoveDirectoryInternal(const QString& dir); 58 void UpdateDirectoryInternal(const QString& dir); 59 void UpdateFileInternal(const QString& path); 60 QSet<QString> FindMissingFiles(const QString& dir); 61 void LoadGame(const QString& path); 62 63 bool AddPath(const QString& path); 64 bool RemovePath(const QString& path); 65 66 enum class CommandType 67 { 68 LoadCache, 69 Start, 70 AddDirectory, 71 RemoveDirectory, 72 UpdateDirectory, 73 UpdateFile, 74 UpdateMetadata, 75 PurgeCache, 76 BeginRefresh, 77 EndRefresh, 78 }; 79 80 struct Command 81 { 82 CommandType type; 83 QString path; 84 }; 85 86 // game path -> directories that track it 87 QMap<QString, QSet<QString>> m_tracked_files; 88 QVector<QString> m_tracked_paths; 89 Common::WorkQueueThread<Command> m_load_thread; 90 UICommon::GameFileCache m_cache; 91 Common::Event m_cache_loaded_event; 92 Common::Event m_initial_games_emitted_event; 93 bool m_initial_games_emitted = false; 94 bool m_started = false; 95 // Count of currently running refresh jobs 96 u32 m_busy_count = 0; 97 }; 98 99 Q_DECLARE_METATYPE(std::shared_ptr<const UICommon::GameFile>) 100 Q_DECLARE_METATYPE(std::string) 101