* Play Time

* SDL

* QT

* Sort / Formatting

* Timer 1 minute

* remove the seconds

removes the seconds from the screen, but in the play_time.txt file it continues to record the seconds for better accuracy, and the screen is cleaner

* fixes the invisible 0

* SDL . . .

* Fix Timer
This commit is contained in:
DanielSvoboda 2024-10-09 07:30:51 -03:00 committed by GitHub
parent 6fe26173dc
commit d4eae28ce2
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
34 changed files with 303 additions and 7 deletions

View file

@ -8,6 +8,7 @@
#include "common/logging/backend.h"
#include "common/logging/log.h"
#ifdef ENABLE_QT_GUI
#include <QtCore>
#include "common/memory_patcher.h"
#endif
#include "common/assert.h"
@ -79,6 +80,17 @@ Emulator::Emulator() {
// Load renderdoc module.
VideoCore::LoadRenderDoc();
// Start the timer (Play Time)
#ifdef ENABLE_QT_GUI
start_time = std::chrono::steady_clock::now();
const auto user_dir = Common::FS::GetUserPath(Common::FS::PathType::UserDir);
QString filePath = QString::fromStdString((user_dir / "play_time.txt").string());
QFile file(filePath);
if (!file.open(QIODevice::ReadWrite | QIODevice::Text)) {
LOG_INFO(Loader, "Error opening or creating play_time.txt");
}
#endif
}
Emulator::~Emulator() {
@ -122,6 +134,14 @@ void Emulator::Run(const std::filesystem::path& file) {
}
#ifdef ENABLE_QT_GUI
MemoryPatcher::g_game_serial = id;
// Timer for 'Play Time'
QTimer* timer = new QTimer();
QObject::connect(timer, &QTimer::timeout, [this, id]() {
UpdatePlayTime(id);
start_time = std::chrono::steady_clock::now();
});
timer->start(60000); // 60000 ms = 1 minute
#endif
title = param_sfo->GetString("TITLE").value_or("Unknown title");
LOG_INFO(Loader, "Game id: {} Title: {}", id, title);
@ -228,6 +248,10 @@ void Emulator::Run(const std::filesystem::path& file) {
window->waitEvent();
}
#ifdef ENABLE_QT_GUI
UpdatePlayTime(id);
#endif
std::exit(0);
}
@ -269,4 +293,74 @@ void Emulator::LoadSystemModules(const std::filesystem::path& file) {
}
}
#ifdef ENABLE_QT_GUI
void Emulator::UpdatePlayTime(const std::string& serial) {
const auto user_dir = Common::FS::GetUserPath(Common::FS::PathType::UserDir);
QString filePath = QString::fromStdString((user_dir / "play_time.txt").string());
QFile file(filePath);
if (!file.open(QIODevice::ReadWrite | QIODevice::Text)) {
LOG_INFO(Loader, "Error opening play_time.txt");
return;
}
auto end_time = std::chrono::steady_clock::now();
auto duration = std::chrono::duration_cast<std::chrono::seconds>(end_time - start_time);
int totalSeconds = duration.count();
QTextStream in(&file);
QStringList lines;
QString content;
while (!in.atEnd()) {
content += in.readLine() + "\n";
}
file.close();
QStringList existingLines = content.split('\n', Qt::SkipEmptyParts);
int accumulatedSeconds = 0;
bool found = false;
for (const QString& line : existingLines) {
QStringList parts = line.split(' ');
if (parts.size() == 2 && parts[0] == QString::fromStdString(serial)) {
QStringList timeParts = parts[1].split(':');
if (timeParts.size() == 3) {
int hours = timeParts[0].toInt();
int minutes = timeParts[1].toInt();
int seconds = timeParts[2].toInt();
accumulatedSeconds = hours * 3600 + minutes * 60 + seconds;
found = true;
break;
}
}
}
accumulatedSeconds += totalSeconds;
int hours = accumulatedSeconds / 3600;
int minutes = (accumulatedSeconds % 3600) / 60;
int seconds = accumulatedSeconds % 60;
QString playTimeSaved = QString::number(hours) + ":" +
QString::number(minutes).rightJustified(2, '0') + ":" +
QString::number(seconds).rightJustified(2, '0');
if (file.open(QIODevice::WriteOnly | QIODevice::Text)) {
QTextStream out(&file);
bool lineUpdated = false;
for (const QString& line : existingLines) {
if (line.startsWith(QString::fromStdString(serial))) {
out << QString::fromStdString(serial) + " " + playTimeSaved + "\n";
lineUpdated = true;
} else {
out << line << "\n";
}
}
if (!lineUpdated) {
out << QString::fromStdString(serial) + " " + playTimeSaved + "\n";
}
}
LOG_INFO(Loader, "Playing time for {}: {}", serial, playTimeSaved.toStdString());
}
#endif
} // namespace Core

View file

@ -26,6 +26,7 @@ public:
~Emulator();
void Run(const std::filesystem::path& file);
void UpdatePlayTime(const std::string& serial);
private:
void LoadSystemModules(const std::filesystem::path& file);
@ -34,6 +35,7 @@ private:
Input::GameController* controller;
Core::Linker* linker;
std::unique_ptr<Frontend::WindowSDL> window;
std::chrono::steady_clock::time_point start_time;
};
} // namespace Core

View file

@ -60,6 +60,9 @@ public:
if (auto app_ver = psf.GetString("APP_VER"); app_ver.has_value()) {
game.version = *app_ver;
}
if (const auto play_time = psf.GetString("PLAY_TIME"); play_time.has_value()) {
game.play_time = *play_time;
}
}
return game;
}

View file

@ -24,16 +24,17 @@ GameListFrame::GameListFrame(std::shared_ptr<GameInfoClass> game_info_get, QWidg
this->horizontalHeader()->setSortIndicatorShown(true);
this->horizontalHeader()->setStretchLastSection(true);
this->setContextMenuPolicy(Qt::CustomContextMenu);
this->setColumnCount(8);
this->setColumnCount(9);
this->setColumnWidth(1, 300); // Name
this->setColumnWidth(2, 120); // Serial
this->setColumnWidth(3, 90); // Region
this->setColumnWidth(4, 90); // Firmware
this->setColumnWidth(5, 90); // Size
this->setColumnWidth(6, 90); // Version
this->setColumnWidth(7, 100); // Play Time
QStringList headers;
headers << tr("Icon") << tr("Name") << tr("Serial") << tr("Region") << tr("Firmware")
<< tr("Size") << tr("Version") << tr("Path");
<< tr("Size") << tr("Version") << tr("Play Time") << tr("Path");
this->setHorizontalHeaderLabels(headers);
this->horizontalHeader()->setSortIndicatorShown(true);
this->horizontalHeader()->setSectionResizeMode(0, QHeaderView::ResizeToContents);
@ -100,9 +101,37 @@ void GameListFrame::PopulateGameList() {
SetTableItem(i, 4, QString::fromStdString(m_game_info->m_games[i].fw));
SetTableItem(i, 5, QString::fromStdString(m_game_info->m_games[i].size));
SetTableItem(i, 6, QString::fromStdString(m_game_info->m_games[i].version));
QString playTime = GetPlayTime(m_game_info->m_games[i].serial);
if (playTime.isEmpty()) {
m_game_info->m_games[i].play_time = "0:00:00";
SetTableItem(i, 7, "0");
} else {
QStringList timeParts = playTime.split(':');
int hours = timeParts[0].toInt();
int minutes = timeParts[1].toInt();
int seconds = timeParts[2].toInt();
QString formattedPlayTime;
if (hours > 0) {
formattedPlayTime += QString("%1h ").arg(hours);
}
if (minutes > 0) {
formattedPlayTime += QString("%1m ").arg(minutes);
}
formattedPlayTime = formattedPlayTime.trimmed();
m_game_info->m_games[i].play_time = playTime.toStdString();
if (formattedPlayTime.isEmpty()) {
SetTableItem(i, 7, "0");
} else {
SetTableItem(i, 7, formattedPlayTime);
}
}
QString path;
Common::FS::PathToQString(path, m_game_info->m_games[i].path);
SetTableItem(i, 7, path);
SetTableItem(i, 8, path);
}
}
@ -171,7 +200,7 @@ void GameListFrame::ResizeIcons(int iconSize) {
this->setItem(index, 0, iconItem);
index++;
}
this->horizontalHeader()->setSectionResizeMode(7, QHeaderView::ResizeToContents);
this->horizontalHeader()->setSectionResizeMode(8, QHeaderView::ResizeToContents);
}
void GameListFrame::SetTableItem(int row, int column, QString itemStr) {
@ -224,3 +253,33 @@ void GameListFrame::SetRegionFlag(int row, int column, QString itemStr) {
this->setItem(row, column, item);
this->setCellWidget(row, column, widget);
}
QString GameListFrame::GetPlayTime(const std::string& serial) {
QString playTime;
const auto user_dir = Common::FS::GetUserPath(Common::FS::PathType::UserDir);
QString filePath = QString::fromStdString((user_dir / "play_time.txt").string());
QFile file(filePath);
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
return playTime;
}
while (!file.atEnd()) {
QByteArray line = file.readLine();
QString lineStr = QString::fromUtf8(line).trimmed();
QStringList parts = lineStr.split(' ');
if (parts.size() >= 2) {
QString fileSerial = parts[0];
QString time = parts[1];
if (fileSerial == QString::fromStdString(serial)) {
playTime = time;
break;
}
}
}
file.close();
return playTime;
}

View file

@ -29,6 +29,7 @@ public Q_SLOTS:
private:
void SetTableItem(int row, int column, QString itemStr);
void SetRegionFlag(int row, int column, QString itemStr);
QString GetPlayTime(const std::string& serial);
QList<QAction*> m_columnActs;
GameInfoClass* game_inf_get = nullptr;
bool ListSortedAsc = true;
@ -68,6 +69,8 @@ public:
case 6:
return a.version < b.version;
case 7:
return a.play_time < b.play_time;
case 8:
return a.path < b.path;
default:
return false;
@ -89,9 +92,11 @@ public:
case 6:
return a.version > b.version;
case 7:
return a.play_time > b.play_time;
case 8:
return a.path > b.path;
default:
return false;
}
}
};
};

View file

@ -19,6 +19,8 @@ struct GameInfo {
std::string version = "Unknown";
std::string region = "Unknown";
std::string fw = "Unknown";
std::string play_time = "Unknown";
};
class GameListUtils {

View file

@ -58,6 +58,7 @@ bool MainWindow::Init() {
this->show();
// load game list
LoadGameLists();
// Check for update
CheckUpdateMain(true);
auto end = std::chrono::steady_clock::now();

View file

@ -12,7 +12,7 @@
<x>0</x>
<y>0</y>
<width>854</width>
<height>570</height>
<height>605</height>
</rect>
</property>
<property name="sizePolicy">
@ -71,7 +71,7 @@
</sizepolicy>
</property>
<property name="currentIndex">
<number>1</number>
<number>0</number>
</property>
<widget class="QWidget" name="generalTab">
<attribute name="title">

View file

@ -1111,6 +1111,11 @@
<source>Path</source>
<translation>مسار</translation>
</message>
<message>
<location filename="../game_list_frame.cpp" line="38"/>
<source>Play Time</source>
<translation>وقت اللعب</translation>
</message>
</context>
<context>
<name>CheckUpdate</name>

View file

@ -1111,6 +1111,11 @@
<source>Path</source>
<translation>Sti</translation>
</message>
<message>
<location filename="../game_list_frame.cpp" line="38"/>
<source>Play Time</source>
<translation>Spilletid</translation>
</message>
</context>
<context>
<name>CheckUpdate</name>

View file

@ -1111,6 +1111,11 @@
<source>Path</source>
<translation>Pfad</translation>
</message>
<message>
<location filename="../game_list_frame.cpp" line="38"/>
<source>Play Time</source>
<translation>Spielzeit</translation>
</message>
</context>
<context>
<name>CheckUpdate</name>

View file

@ -1111,6 +1111,11 @@
<source>Path</source>
<translation>Διαδρομή</translation>
</message>
<message>
<location filename="../game_list_frame.cpp" line="38"/>
<source>Play Time</source>
<translation>Χρόνος παιχνιδιού</translation>
</message>
</context>
<context>
<name>CheckUpdate</name>

View file

@ -1146,6 +1146,11 @@
<source>Path</source>
<translation>Path</translation>
</message>
<message>
<location filename="../game_list_frame.cpp" line="38"/>
<source>Play Time</source>
<translation>Play Time</translation>
</message>
</context>
<context>
<name>CheckUpdate</name>

View file

@ -1111,6 +1111,11 @@
<source>Path</source>
<translation>Ruta</translation>
</message>
<message>
<location filename="../game_list_frame.cpp" line="38"/>
<source>Play Time</source>
<translation>Tiempo de Juego</translation>
</message>
</context>
<context>
<name>CheckUpdate</name>

View file

@ -1111,6 +1111,11 @@
<source>Path</source>
<translation>مسیر</translation>
</message>
<message>
<location filename="../game_list_frame.cpp" line="38"/>
<source>Play Time</source>
<translation>زمان بازی</translation>
</message>
</context>
<context>
<name>CheckUpdate</name>

View file

@ -1111,6 +1111,11 @@
<source>Path</source>
<translation>Polku</translation>
</message>
<message>
<location filename="../game_list_frame.cpp" line="38"/>
<source>Play Time</source>
<translation>Peliaika</translation>
</message>
</context>
<context>
<name>CheckUpdate</name>

View file

@ -1111,6 +1111,11 @@
<source>Path</source>
<translation>Répertoire</translation>
</message>
<message>
<location filename="../game_list_frame.cpp" line="38"/>
<source>Play Time</source>
<translation>Temps de jeu</translation>
</message>
</context>
<context>
<name>CheckUpdate</name>

View file

@ -1111,6 +1111,11 @@
<source>Path</source>
<translation>Útvonal</translation>
</message>
<message>
<location filename="../game_list_frame.cpp" line="38"/>
<source>Play Time</source>
<translation>Játékidő</translation>
</message>
</context>
<context>
<name>CheckUpdate</name>

View file

@ -1111,6 +1111,11 @@
<source>Path</source>
<translation>Jalur</translation>
</message>
<message>
<location filename="../game_list_frame.cpp" line="38"/>
<source>Play Time</source>
<translation>Waktu Bermain</translation>
</message>
</context>
<context>
<name>CheckUpdate</name>

View file

@ -1111,6 +1111,11 @@
<source>Path</source>
<translation>Percorso</translation>
</message>
<message>
<location filename="../game_list_frame.cpp" line="38"/>
<source>Play Time</source>
<translation>Tempo di Gioco</translation>
</message>
</context>
<context>
<name>CheckUpdate</name>

View file

@ -1111,6 +1111,11 @@
<source>Path</source>
<translation></translation>
</message>
<message>
<location filename="../game_list_frame.cpp" line="38"/>
<source>Play Time</source>
<translation></translation>
</message>
</context>
<context>
<name>CheckUpdate</name>

View file

@ -1111,6 +1111,11 @@
<source>Path</source>
<translation>Path</translation>
</message>
<message>
<location filename="../game_list_frame.cpp" line="38"/>
<source>Play Time</source>
<translation>Play Time</translation>
</message>
</context>
<context>
<name>CheckUpdate</name>

View file

@ -1111,6 +1111,11 @@
<source>Path</source>
<translation>Kelias</translation>
</message>
<message>
<location filename="../game_list_frame.cpp" line="38"/>
<source>Play Time</source>
<translation>Žaidimo laikas</translation>
</message>
</context>
<context>
<name>CheckUpdate</name>

View file

@ -1111,6 +1111,11 @@
<source>Path</source>
<translation>Sti</translation>
</message>
<message>
<location filename="../game_list_frame.cpp" line="38"/>
<source>Play Time</source>
<translation>Spilletid</translation>
</message>
</context>
<context>
<name>CheckUpdate</name>

View file

@ -1111,6 +1111,11 @@
<source>Path</source>
<translation>Pad</translation>
</message>
<message>
<location filename="../game_list_frame.cpp" line="38"/>
<source>Play Time</source>
<translation>Speeltijd</translation>
</message>
</context>
<context>
<name>CheckUpdate</name>

View file

@ -1111,6 +1111,11 @@
<source>Path</source>
<translation>Ścieżka</translation>
</message>
<message>
<location filename="../game_list_frame.cpp" line="38"/>
<source>Play Time</source>
<translation>Czas gry</translation>
</message>
</context>
<context>
<name>CheckUpdate</name>

View file

@ -1111,6 +1111,11 @@
<source>Path</source>
<translation>Diretório</translation>
</message>
<message>
<location filename="../game_list_frame.cpp" line="38"/>
<source>Play Time</source>
<translation>Horas Jogadas</translation>
</message>
</context>
<context>
<name>CheckUpdate</name>

View file

@ -1111,6 +1111,11 @@
<source>Path</source>
<translation>Drum</translation>
</message>
<message>
<location filename="../game_list_frame.cpp" line="38"/>
<source>Play Time</source>
<translation>Timp de Joacă</translation>
</message>
</context>
<context>
<name>CheckUpdate</name>

View file

@ -1111,6 +1111,11 @@
<source>Path</source>
<translation>Путь</translation>
</message>
<message>
<location filename="../game_list_frame.cpp" line="38"/>
<source>Play Time</source>
<translation>Время Игры</translation>
</message>
</context>
<context>
<name>CheckUpdate</name>

View file

@ -1111,6 +1111,11 @@
<source>Path</source>
<translation>Shtegu</translation>
</message>
<message>
<location filename="../game_list_frame.cpp" line="38"/>
<source>Play Time</source>
<translation>Kohë Lojë</translation>
</message>
</context>
<context>
<name>CheckUpdate</name>

View file

@ -1111,6 +1111,11 @@
<source>Path</source>
<translation>Yol</translation>
</message>
<message>
<location filename="../game_list_frame.cpp" line="38"/>
<source>Play Time</source>
<translation>Oynama Süresi</translation>
</message>
</context>
<context>
<name>CheckUpdate</name>

View file

@ -1111,6 +1111,11 @@
<source>Path</source>
<translation>Đưng dẫn</translation>
</message>
<message>
<location filename="../game_list_frame.cpp" line="38"/>
<source>Play Time</source>
<translation>Thời gian chơi</translation>
</message>
</context>
<context>
<name>CheckUpdate</name>

View file

@ -1111,6 +1111,11 @@
<source>Path</source>
<translation></translation>
</message>
<message>
<location filename="../game_list_frame.cpp" line="38"/>
<source>Play Time</source>
<translation></translation>
</message>
</context>
<context>
<name>CheckUpdate</name>

View file

@ -1111,6 +1111,11 @@
<source>Path</source>
<translation></translation>
</message>
<message>
<location filename="../game_list_frame.cpp" line="38"/>
<source>Play Time</source>
<translation></translation>
</message>
</context>
<context>
<name>CheckUpdate</name>