GameList: Update time played while game is running

Add an UpdateEvent for time played updates and use it to update the Game
List time played while a game is running (instead of just when it
stops).
This commit is contained in:
Dentomologist 2025-03-16 14:41:18 -07:00
parent e234f99f42
commit 0161065959
4 changed files with 44 additions and 27 deletions

View File

@ -9,13 +9,15 @@
#include "Common/CommonTypes.h"
#include "Common/FileUtil.h"
#include "Common/HookableEvent.h"
#include "Common/IniFile.h"
#include "Common/NandPaths.h"
TimePlayedManager::TimePlayedManager()
: m_ini_path(File::GetUserPath(D_CONFIG_IDX) + "TimePlayed.ini")
{
Reload();
m_ini.Load(m_ini_path);
m_time_list = m_ini.GetOrCreateSection("TimePlayed");
}
TimePlayedManager::~TimePlayedManager() = default;
@ -30,11 +32,18 @@ void TimePlayedManager::AddTime(const std::string& game_id, std::chrono::millise
{
std::string filtered_game_id = Common::EscapeFileName(game_id);
u64 previous_time;
u64 new_time;
std::lock_guard guard(m_mutex);
m_time_list->Get(filtered_game_id, &previous_time);
m_time_list->Set(filtered_game_id, previous_time + static_cast<u64>(time_emulated.count()));
m_ini.Save(m_ini_path);
{
std::lock_guard guard(m_mutex);
m_time_list->Get(filtered_game_id, &previous_time);
new_time = previous_time + static_cast<u64>(time_emulated.count());
m_time_list->Set(filtered_game_id, new_time);
m_ini.Save(m_ini_path);
}
UpdateEvent::Trigger(filtered_game_id, static_cast<std::chrono::milliseconds>(new_time));
}
std::chrono::milliseconds TimePlayedManager::GetTimePlayed(const std::string& game_id) const
@ -46,10 +55,3 @@ std::chrono::milliseconds TimePlayedManager::GetTimePlayed(const std::string& ga
m_time_list->Get(filtered_game_id, &previous_time);
return std::chrono::milliseconds(previous_time);
}
void TimePlayedManager::Reload()
{
std::lock_guard guard(m_mutex);
m_ini.Load(m_ini_path);
m_time_list = m_ini.GetOrCreateSection("TimePlayed");
}

View File

@ -8,6 +8,7 @@
#include <string>
#include "Common/CommonTypes.h"
#include "Common/HookableEvent.h"
#include "Common/IniFile.h"
class TimePlayedManager
@ -26,7 +27,8 @@ public:
std::chrono::milliseconds GetTimePlayed(const std::string& game_id) const;
void Reload();
using UpdateEvent =
Common::HookableEvent<"Time Played Update", const std::string&, std::chrono::milliseconds>;
private:
TimePlayedManager();

View File

@ -3,18 +3,21 @@
#include "DolphinQt/GameList/GameListModel.h"
#include <chrono>
#include <string>
#include <QDir>
#include <QFileInfo>
#include <QPixmap>
#include <QRegularExpression>
#include "Core/Config/MainSettings.h"
#include "Core/Core.h"
#include "Core/TimePlayed.h"
#include "DiscIO/Enums.h"
#include "DolphinQt/QtUtils/ImageConverter.h"
#include "DolphinQt/QtUtils/QueueOnObject.h"
#include "DolphinQt/Resources.h"
#include "DolphinQt/Settings.h"
@ -35,8 +38,6 @@ GameListModel::GameListModel(QObject* parent)
&GameTracker::RefreshAll);
connect(&Settings::Instance(), &Settings::TitleDBReloadRequested,
[this] { m_title_database = Core::TitleDatabase(); });
connect(&Settings::Instance(), &Settings::EmulationStateChanged, this,
&GameListModel::OnEmulationStateChanged);
for (const QString& dir : Settings::Instance().GetPaths())
m_tracker.AddDirectory(dir);
@ -50,6 +51,28 @@ GameListModel::GameListModel(QObject* parent)
emit layoutChanged();
});
const auto on_time_played_update = [this](const std::string& game_id,
const std::chrono::milliseconds) {
const auto update_cell = [this, game_id]() {
for (int model_row = 0; model_row < m_games.size(); ++model_row)
{
if (game_id != m_games[model_row]->GetGameID())
continue;
const QModelIndex time_played_index =
index(model_row, static_cast<int>(Column::TimePlayed));
emit dataChanged(time_played_index, time_played_index);
// Multiple entries in the GameList can have the same GameID, so don't break out of the
// loop when a match is found.
}
};
QueueOnObject(this, update_cell);
};
m_time_played_update_event =
TimePlayedManager::UpdateEvent::Register(on_time_played_update, "GameListModel");
auto& settings = Settings::GetQSettings();
m_tag_list = settings.value(QStringLiteral("gamelist/tags")).toStringList();
@ -508,11 +531,3 @@ void GameListModel::PurgeCache()
{
m_tracker.PurgeCache();
}
void GameListModel::OnEmulationStateChanged(Core::State state)
{
if (state == Core::State::Uninitialized)
{
m_time_played_manager.Reload();
}
}

View File

@ -12,7 +12,6 @@
#include <QStringList>
#include <QVariant>
#include "Core/Core.h"
#include "Core/TimePlayed.h"
#include "Core/TitleDatabase.h"
@ -90,8 +89,6 @@ private:
// Index in m_games, or -1 if it isn't found
int FindGameIndex(const std::string& path) const;
void OnEmulationStateChanged(Core::State state);
QStringList m_tag_list;
QMap<QString, QVariant> m_game_tags;
@ -99,6 +96,7 @@ private:
QList<std::shared_ptr<const UICommon::GameFile>> m_games;
Core::TitleDatabase m_title_database;
TimePlayedManager& m_time_played_manager;
Common::EventHook m_time_played_update_event;
QString m_term;
float m_scale = 1.0;
};