1
0
Fork 0
forked from eden-emu/eden

Compare commits

...

3 commits

11 changed files with 250 additions and 137 deletions

View file

@ -13,6 +13,9 @@
#include "core/hle/service/acc/profile_manager.h"
#include "play_time_manager.h"
#include <fmt/format.h>
#include <algorithm>
namespace PlayTime {
namespace {
@ -164,4 +167,37 @@ void PlayTimeManager::ResetProgramPlayTime(u64 program_id) {
Save();
}
std::string PlayTimeManager::GetReadablePlayTime(u64 time_seconds) {
if (time_seconds == 0) {
return {};
}
const auto time_minutes = std::max(static_cast<double>(time_seconds) / 60.0, 1.0);
const auto time_hours = static_cast<double>(time_seconds) / 3600.0;
const bool is_minutes = time_minutes < 60.0;
if (is_minutes) {
return fmt::format("{:.0f} m", time_minutes);
} else {
const bool has_remainder = time_seconds % 60 != 0;
if (has_remainder) {
return fmt::format("{:.1f} h", time_hours);
} else {
return fmt::format("{:.0f} h", time_hours);
}
}
}
std::string PlayTimeManager::GetPlayTimeHours(u64 time_seconds) {
return fmt::format("{}", time_seconds / 3600);
}
std::string PlayTimeManager::GetPlayTimeMinutes(u64 time_seconds) {
return fmt::format("{}", (time_seconds % 3600) / 60);
}
std::string PlayTimeManager::GetPlayTimeSeconds(u64 time_seconds) {
return fmt::format("{}", time_seconds % 60);
}
} // namespace PlayTime

View file

@ -38,6 +38,11 @@ public:
void Start();
void Stop();
static std::string GetReadablePlayTime(u64 time_seconds);
static std::string GetPlayTimeHours(u64 time_seconds);
static std::string GetPlayTimeMinutes(u64 time_seconds);
static std::string GetPlayTimeSeconds(u64 time_seconds);
private:
void AutoTimestamp(std::stop_token stop_token);
void Save();

View file

@ -27,9 +27,6 @@ add_library(qt_common STATIC
qt_rom_util.h qt_rom_util.cpp
qt_applet_util.h qt_applet_util.cpp
qt_progress_dialog.h qt_progress_dialog.cpp
qt_playtime_manager.cpp
qt_playtime_manager.h
)
create_target_directory_groups(qt_common)

View file

@ -1,42 +0,0 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#include "qt_playtime_manager.h"
namespace QtCommon::PlayTimeManager {
QString ReadablePlayTime(qulonglong time_seconds) {
if (time_seconds == 0) {
return {};
}
const auto time_minutes = std::max(static_cast<double>(time_seconds) / 60, 1.0);
const auto time_hours = static_cast<double>(time_seconds) / 3600;
const bool is_minutes = time_minutes < 60;
const char* unit = is_minutes ? "m" : "h";
const auto value = is_minutes ? time_minutes : time_hours;
return QStringLiteral("%L1 %2")
.arg(value, 0, 'f', !is_minutes && time_seconds % 60 != 0)
.arg(QString::fromUtf8(unit));
}
QString GetPlayTimeUnit(qulonglong time_seconds, TimeUnit unit) {
switch (unit) {
case TimeUnit::Hours: {
const qulonglong hours = time_seconds / 3600;
return QString::number(hours);
}
case TimeUnit::Minutes: {
const qulonglong minutes = (time_seconds % 3600) / 60;
return QString::number(minutes);
}
case TimeUnit::Seconds: {
const qulonglong seconds = time_seconds % 60;
return QString::number(seconds);
}
default:
return QStringLiteral("0");
}
}
} // namespace QtCommon::PlayTimeManager

View file

@ -1,20 +0,0 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#include <QString>
namespace QtCommon::PlayTimeManager {
enum class TimeUnit {
Hours,
Minutes,
Seconds
};
// Converts a length of time in seconds into a readable format
QString ReadablePlayTime(qulonglong time_seconds);
// Returns play time hours/minutes/seconds as a string
QString GetPlayTimeUnit(qulonglong time_seconds, TimeUnit unit);
} // namespace QtCommon::PlayTimeManager

View file

@ -201,6 +201,8 @@ add_executable(yuzu
precompiled_headers.h
startup_checks.cpp
startup_checks.h
set_play_time_dialog.cpp
set_play_time_dialog.h
util/clickable_label.cpp
util/clickable_label.h
util/controller_navigation.cpp

View file

@ -21,7 +21,7 @@
#include "common/common_types.h"
#include "common/logging/log.h"
#include "common/string_util.h"
#include "qt_common/qt_playtime_manager.h"
#include "frontend_common/play_time_manager.h"
#include "qt_common/uisettings.h"
#include "yuzu/util/util.h"
@ -241,7 +241,7 @@ public:
void setData(const QVariant& value, int role) override {
qulonglong time_seconds = value.toULongLong();
GameListItem::setData(QtCommon::PlayTimeManager::ReadablePlayTime(time_seconds), Qt::DisplayRole);
GameListItem::setData(QString::fromStdString(PlayTime::PlayTimeManager::GetReadablePlayTime(time_seconds)), Qt::DisplayRole);
GameListItem::setData(value, PlayTimeRole);
}

View file

@ -15,6 +15,8 @@
#include <memory>
#include <thread>
#include "set_play_time_dialog.h"
#ifdef __APPLE__
#include <unistd.h> // for chdir
#endif
@ -2637,84 +2639,18 @@ void GMainWindow::OnGameListRemoveFile(u64 program_id, QtCommon::Game::GameListR
}
void GMainWindow::OnGameListSetPlayTime(u64 program_id) {
QDialog dialog(this);
dialog.setWindowTitle(tr("Set Play Time Data"));
dialog.setModal(true);
auto* layout = new QVBoxLayout(&dialog);
auto* input_layout = new QHBoxLayout();
auto* hours_edit = new QLineEdit(&dialog);
auto* minutes_edit = new QLineEdit(&dialog);
auto* seconds_edit = new QLineEdit(&dialog);
hours_edit->setValidator(new QIntValidator(0, 9999, hours_edit));
minutes_edit->setValidator(new QIntValidator(0, 59, minutes_edit));
seconds_edit->setValidator(new QIntValidator(0, 59, seconds_edit));
using QtCommon::PlayTimeManager::TimeUnit;
const u64 current_play_time = play_time_manager->GetPlayTime(program_id);
auto getTimeUnit = [current_play_time](TimeUnit unit) {
return QtCommon::PlayTimeManager::GetPlayTimeUnit(current_play_time, unit);
};
hours_edit->setText(getTimeUnit(TimeUnit::Hours));
minutes_edit->setText(getTimeUnit(TimeUnit::Minutes));
seconds_edit->setText(getTimeUnit(TimeUnit::Seconds));
SetPlayTimeDialog dialog(this, current_play_time);
input_layout->addWidget(new QLabel(tr("Hours:"), &dialog));
input_layout->addWidget(hours_edit);
input_layout->addWidget(new QLabel(tr("Minutes:"), &dialog));
input_layout->addWidget(minutes_edit);
input_layout->addWidget(new QLabel(tr("Seconds:"), &dialog));
input_layout->addWidget(seconds_edit);
layout->addLayout(input_layout);
auto* error_label = new QLabel(&dialog);
error_label->setStyleSheet(QStringLiteral("QLabel { color : red; }"));
error_label->setVisible(false);
layout->addWidget(error_label);
auto* button_box = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, &dialog);
layout->addWidget(button_box);
connect(button_box, &QDialogButtonBox::accepted, [&]() {
const int hours = hours_edit->text().toInt();
const int minutes = minutes_edit->text().toInt();
const int seconds = seconds_edit->text().toInt();
if (hours < 0 || hours > 9999) {
error_label->setText(tr("Hours must be between 0 and 9999."));
error_label->setVisible(true);
return;
}
if (minutes < 0 || minutes > 59) {
error_label->setText(tr("Minutes must be between 0 and 59."));
error_label->setVisible(true);
return;
}
if (seconds < 0 || seconds > 59) {
error_label->setText(tr("Seconds must be between 0 and 59."));
error_label->setVisible(true);
return;
}
u64 total_seconds = static_cast<u64>(hours) * 3600 + static_cast<u64>(minutes) * 60 + static_cast<u64>(seconds);
if (dialog.exec() == QDialog::Accepted) {
const u64 total_seconds = dialog.GetTotalSeconds();
play_time_manager->SetPlayTime(program_id, total_seconds);
game_list->PopulateAsync(UISettings::values.game_dirs);
dialog.accept();
});
connect(button_box, &QDialogButtonBox::rejected, &dialog, &QDialog::reject);
dialog.exec();
}
}
void GMainWindow::OnGameListRemovePlayTimeData(u64 program_id) {
if (QMessageBox::question(this, tr("Remove Play Time Data"), tr("Reset play time?"),
QMessageBox::Yes | QMessageBox::No,

View file

@ -0,0 +1,49 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#include "yuzu/set_play_time_dialog.h"
#include "frontend_common/play_time_manager.h"
#include "ui_set_play_time_dialog.h"
SetPlayTimeDialog::SetPlayTimeDialog(QWidget* parent, u64 current_play_time)
: QDialog(parent), ui{std::make_unique<Ui::SetPlayTimeDialog>()} {
ui->setupUi(this);
ui->hoursSpinBox->setValue(
QString::fromStdString(PlayTime::PlayTimeManager::GetPlayTimeHours(current_play_time)).toInt());
ui->minutesSpinBox->setValue(
QString::fromStdString(PlayTime::PlayTimeManager::GetPlayTimeMinutes(current_play_time)).toInt());
ui->secondsSpinBox->setValue(
QString::fromStdString(PlayTime::PlayTimeManager::GetPlayTimeSeconds(current_play_time)).toInt());
connect(ui->hoursSpinBox, QOverload<int>::of(&QSpinBox::valueChanged), this,
&SetPlayTimeDialog::OnValueChanged);
connect(ui->minutesSpinBox, QOverload<int>::of(&QSpinBox::valueChanged), this,
&SetPlayTimeDialog::OnValueChanged);
connect(ui->secondsSpinBox, QOverload<int>::of(&QSpinBox::valueChanged), this,
&SetPlayTimeDialog::OnValueChanged);
}
SetPlayTimeDialog::~SetPlayTimeDialog() = default;
u64 SetPlayTimeDialog::GetTotalSeconds() const {
const u64 hours = static_cast<u64>(ui->hoursSpinBox->value());
const u64 minutes = static_cast<u64>(ui->minutesSpinBox->value());
const u64 seconds = static_cast<u64>(ui->secondsSpinBox->value());
return hours * 3600 + minutes * 60 + seconds;
}
void SetPlayTimeDialog::OnValueChanged() {
if (ui->errorLabel->isVisible()) {
ui->errorLabel->setVisible(false);
}
const u64 total_seconds = GetTotalSeconds();
constexpr u64 max_reasonable_time = 9999ULL * 3600;
if (total_seconds > max_reasonable_time) {
ui->errorLabel->setText(tr("Total play time reached maximum."));
ui->errorLabel->setVisible(true);
}
}

View file

@ -0,0 +1,27 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#pragma once
#include <QDialog>
#include <memory>
#include "common/common_types.h"
namespace Ui {
class SetPlayTimeDialog;
}
class SetPlayTimeDialog : public QDialog {
Q_OBJECT
public:
explicit SetPlayTimeDialog(QWidget* parent, u64 current_play_time);
~SetPlayTimeDialog() override;
u64 GetTotalSeconds() const;
private:
void OnValueChanged();
std::unique_ptr<Ui::SetPlayTimeDialog> ui;
};

View file

@ -0,0 +1,123 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>SetPlayTimeDialog</class>
<widget class="QDialog" name="SetPlayTimeDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>150</height>
</rect>
</property>
<property name="windowTitle">
<string>Set Play Time Data</string>
</property>
<property name="modal">
<bool>true</bool>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QHBoxLayout" name="inputLayout">
<item>
<widget class="QLabel" name="labelHours">
<property name="text">
<string>Hours:</string>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="hoursSpinBox">
<property name="maximum">
<number>9999</number>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="labelMinutes">
<property name="text">
<string>Minutes:</string>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="minutesSpinBox">
<property name="maximum">
<number>59</number>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="labelSeconds">
<property name="text">
<string>Seconds:</string>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="secondsSpinBox">
<property name="maximum">
<number>59</number>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QLabel" name="errorLabel">
<property name="styleSheet">
<string notr="true">QLabel { color : red; }</string>
</property>
<property name="text">
<string/>
</property>
<property name="visible">
<bool>false</bool>
</property>
</widget>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>SetPlayTimeDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>199</x>
<y>129</y>
</hint>
<hint type="destinationlabel">
<x>199</x>
<y>74</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>SetPlayTimeDialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>199</x>
<y>129</y>
</hint>
<hint type="destinationlabel">
<x>199</x>
<y>74</y>
</hint>
</hints>
</connection>
</connections>
</ui>