summaryrefslogtreecommitdiff
path: root/Source/Core/DolphinQt/GameList/GameTracker.h
blob: 97ec5bb2688f2ab2707c40f258a4282b41cdf27e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
// Copyright 2015 Dolphin Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later

#pragma once

#include <atomic>
#include <memory>
#include <string>

#include <QFileSystemWatcher>
#include <QMap>
#include <QSet>
#include <QString>
#include <QVector>

#include "Common/Event.h"
#include "Common/WorkQueueThread.h"
#include "UICommon/GameFileCache.h"

namespace UICommon
{
class GameFile;
}

// Watches directories and loads GameFiles in a separate thread.
// To use this, just add directories using AddDirectory, and listen for the
// GameLoaded and GameRemoved signals.
class GameTracker final : public QFileSystemWatcher
{
  Q_OBJECT

public:
  explicit GameTracker(QObject* parent = nullptr);

  // A GameTracker won't emit any signals until this function has been called.
  // Before you call this function, make sure to call AddDirectory for all
  // directories you want to track, otherwise games will briefly disappear
  // until you call AddDirectory and the GameTracker finishes scanning the file system.
  void Start();

  void AddDirectory(const QString& dir);
  void RemoveDirectory(const QString& dir);
  void RefreshAll();
  void PurgeCache();

signals:
  void GameLoaded(const std::shared_ptr<const UICommon::GameFile>& game);
  void GameUpdated(const std::shared_ptr<const UICommon::GameFile>& game);
  void GameRemoved(const std::string& path);

private:
  void LoadCache();
  void StartInternal();
  void UpdateDirectory(const QString& dir);
  void UpdateFile(const QString& path);
  void AddDirectoryInternal(const QString& dir);
  void RemoveDirectoryInternal(const QString& dir);
  void UpdateDirectoryInternal(const QString& dir);
  void UpdateFileInternal(const QString& path);
  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,
    Start,
    AddDirectory,
    RemoveDirectory,
    UpdateDirectory,
    UpdateFile,
    UpdateMetadata,
    ResumeProcessing,
    PurgeCache,
    BeginRefresh,
    EndRefresh,
  };

  struct Command
  {
    CommandType type;
    QString path;
  };

  // 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;
  Common::Event m_initial_games_emitted_event;
  bool m_initial_games_emitted = false;
  bool m_started = false;
  bool m_needs_purge = false;
  bool m_refresh_in_progress = false;
  std::atomic_bool m_processing_halted = false;
};

Q_DECLARE_METATYPE(std::shared_ptr<const UICommon::GameFile>)
Q_DECLARE_METATYPE(std::string)