mirror of
https://git.eden-emu.dev/eden-emu/eden
synced 2026-04-10 09:48:58 +02:00
[ui, docs] add custom play time formatting
Signed-off-by: codeman4033 <codeman4033@eden-emu.dev>
This commit is contained in:
parent
b673dad40d
commit
af64395c6a
13 changed files with 483 additions and 184 deletions
167
docs/user/CustomPlayTime.md
Normal file
167
docs/user/CustomPlayTime.md
Normal file
|
|
@ -0,0 +1,167 @@
|
|||
# Custom Play Time Syntax
|
||||
|
||||
This document describes the formatting syntax used to display custom playtime values in the emulator.
|
||||
|
||||
## Overview
|
||||
|
||||
Playtime is internally stored as a total number of seconds. This formatting system allows users to control how that value is displayed by using tokens inside a format string.
|
||||
|
||||
Example:
|
||||
|
||||
```
|
||||
{H:02}:{M:02}:{S:02}
|
||||
```
|
||||
|
||||
Output:
|
||||
|
||||
```
|
||||
02:03:04
|
||||
```
|
||||
|
||||
## Tokens
|
||||
|
||||
The following tokens can be used in format strings.
|
||||
|
||||
| Token | Description |
|
||||
| ----- | ------------------------ |
|
||||
| `{d}` | Total days |
|
||||
| `{h}` | Total hours |
|
||||
| `{H}` | Hours component (0–23) |
|
||||
| `{m}` | Total minutes |
|
||||
| `{M}` | Minutes component (0–59) |
|
||||
| `{s}` | Total seconds |
|
||||
| `{S}` | Seconds component (0–59) |
|
||||
|
||||
## Padding
|
||||
|
||||
Tokens may optionally include zero-padding using the syntax `:NN`, where `NN` is the minimum width.
|
||||
|
||||
Example:
|
||||
|
||||
```
|
||||
{H:02}:{M:02}:{S:02}
|
||||
```
|
||||
|
||||
This ensures each component is displayed with at least two digits.
|
||||
|
||||
Example output:
|
||||
|
||||
```
|
||||
02:03:04
|
||||
```
|
||||
|
||||
## Conditional Sections
|
||||
|
||||
Conditional sections allow parts of the format string to appear only when a specific time unit is non-zero. This is useful for hiding units such as `0h`.
|
||||
|
||||
Conditional sections use the following syntax:
|
||||
|
||||
```
|
||||
[unit] ... [/unit]
|
||||
```
|
||||
|
||||
Where `unit` is one of the following:
|
||||
|
||||
| Unit | Condition |
|
||||
| ---- | ------------------------------ |
|
||||
| `d` | Display section if days > 0 |
|
||||
| `h` | Display section if hours > 0 |
|
||||
| `m` | Display section if minutes > 0 |
|
||||
|
||||
Example:
|
||||
|
||||
```
|
||||
[h]{H}h [/h][m]{M}m [/m]{S}s
|
||||
```
|
||||
|
||||
Possible outputs:
|
||||
|
||||
```
|
||||
1h 3m 4s
|
||||
3m 4s
|
||||
4s
|
||||
```
|
||||
|
||||
Conditional sections may contain both tokens and literal text.
|
||||
|
||||
## Escaping Braces
|
||||
|
||||
To include literal braces in the output, they must be escaped using double braces.
|
||||
|
||||
| Input | Output |
|
||||
| ----- | ------ |
|
||||
| `{{` | `{` |
|
||||
| `}}` | `}` |
|
||||
|
||||
Example:
|
||||
|
||||
```
|
||||
Playtime: {{ {H}:{M}:{S} }}
|
||||
```
|
||||
|
||||
Output:
|
||||
|
||||
```
|
||||
Playtime: { 2:3:4 }
|
||||
```
|
||||
|
||||
## Literal Text
|
||||
|
||||
Any text outside of tokens or conditional sections is copied directly into the output.
|
||||
|
||||
Example:
|
||||
|
||||
```
|
||||
{h}h {M}m {S}s
|
||||
```
|
||||
|
||||
Output:
|
||||
|
||||
```
|
||||
26h 3m 4s
|
||||
```
|
||||
|
||||
## Examples
|
||||
|
||||
### Clock Format
|
||||
|
||||
```
|
||||
{H:02}:{M:02}:{S:02}
|
||||
```
|
||||
|
||||
Example output:
|
||||
|
||||
```
|
||||
02:03:04
|
||||
```
|
||||
|
||||
### Human Readable Format
|
||||
|
||||
```
|
||||
{h} hours, {M} minutes, {S} seconds
|
||||
```
|
||||
|
||||
Example output:
|
||||
|
||||
```
|
||||
26 hours, 3 minutes, 4 seconds
|
||||
```
|
||||
|
||||
### Compact Format
|
||||
|
||||
```
|
||||
[h]{H}h [/h][m]{M}m [/m][s]{S}s
|
||||
```
|
||||
|
||||
Example output:
|
||||
|
||||
```
|
||||
3m 4s
|
||||
```
|
||||
|
||||
## Notes
|
||||
|
||||
* Playtime values are derived from the total number of elapsed seconds.
|
||||
* Component tokens (`H`, `M`, `S`) wrap within their normal ranges.
|
||||
* Total tokens (`h`, `m`, `s`) represent the full accumulated value for that unit.
|
||||
* This is based on the [fmt syntax](https://fmt.dev/12.0/syntax/). Almost everything there is also supported here.
|
||||
|
|
@ -9,7 +9,7 @@ A copy of this handbook is [available online](https://git.eden-emu.dev/eden-emu/
|
|||
## Basics
|
||||
|
||||
- **[The Basics](Basics.md)**
|
||||
- **[Quickstart](./QuickStart.md)**
|
||||
- **[Quickstart](QuickStart.md)**
|
||||
- **[Settings](./Settings.md)**
|
||||
- **[Controllers](./Controllers.md)**
|
||||
- **[Controller profiles](./Controllers.md#configuring-controller-profiles)**
|
||||
|
|
@ -26,6 +26,7 @@ A copy of this handbook is [available online](https://git.eden-emu.dev/eden-emu/
|
|||
- **[Installing Atmosphere Mods](./InstallingAtmosphereMods.md)**
|
||||
- **[Installing Updates & DLCs](./InstallingUpdatesDLC.md)**
|
||||
- **[Alter Date & Time](./AlterDateTime.md)**
|
||||
- **[Custom Play Time Syntax](./CustomPlayTime.md)**
|
||||
|
||||
## 3rd-party Integration
|
||||
|
||||
|
|
|
|||
|
|
@ -166,21 +166,4 @@ void PlayTimeManager::ResetProgramPlayTime(u64 program_id) {
|
|||
Save();
|
||||
}
|
||||
|
||||
std::string PlayTimeManager::GetReadablePlayTime(u64 t) {
|
||||
return t > 0 ? fmt::format("{:02}:{:02}:{:02}", t / 3600, (t / 60) % 60, t % 60)
|
||||
: std::string{};
|
||||
}
|
||||
|
||||
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
|
||||
|
|
|
|||
|
|
@ -38,11 +38,6 @@ 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();
|
||||
|
|
|
|||
|
|
@ -373,6 +373,10 @@ std::unique_ptr<TranslationMap> InitializeTranslations(QObject* parent) {
|
|||
// Ui Multiplayer
|
||||
|
||||
// Ui Games list
|
||||
INSERT(UISettings, use_custom_play_time_format, tr("Use custom play time format"),
|
||||
QString());
|
||||
INSERT(UISettings, custom_play_time_format, tr("Custom play time format"),
|
||||
QString());
|
||||
|
||||
#undef INSERT
|
||||
|
||||
|
|
|
|||
|
|
@ -233,6 +233,8 @@ struct Values {
|
|||
|
||||
// Play time
|
||||
Setting<bool> show_play_time{linkage, true, "show_play_time", Category::UiGameList};
|
||||
Setting<bool> use_custom_play_time_format{linkage, false, "use_custom_play_time_format", Category::UiGameList};
|
||||
Setting<std::string> custom_play_time_format{linkage, "", "use_custom_play_time_format", Category::UiGameList};
|
||||
|
||||
// misc
|
||||
Setting<bool> show_fw_warning{linkage, true, "show_fw_warning", Category::Miscellaneous};
|
||||
|
|
|
|||
|
|
@ -16,7 +16,10 @@
|
|||
#include <QFileDialog>
|
||||
#include <QString>
|
||||
#include <QToolButton>
|
||||
#include <QPushButton>
|
||||
#include <QVariant>
|
||||
#include <QDesktopServices>
|
||||
#include <QUrl>
|
||||
|
||||
#include "common/common_types.h"
|
||||
#include "common/fs/path_util.h"
|
||||
|
|
@ -103,7 +106,7 @@ ConfigureUi::ConfigureUi(Core::System& system_, QWidget* parent)
|
|||
InitializeIconSizeComboBox();
|
||||
InitializeRowComboBoxes();
|
||||
|
||||
PopulateResolutionComboBox(ui->screenshot_height, this);
|
||||
PopulateResolutionComboBox(ui->screenshot_size_combobox, this);
|
||||
|
||||
SetConfiguration();
|
||||
|
||||
|
|
@ -142,9 +145,14 @@ ConfigureUi::ConfigureUi(Core::System& system_, QWidget* parent)
|
|||
}
|
||||
});
|
||||
|
||||
connect(ui->screenshot_height, &QComboBox::currentTextChanged, [this]() { UpdateWidthText(); });
|
||||
connect(ui->screenshot_size_combobox, &QComboBox::currentTextChanged, [this]() { UpdateWidthText(); });
|
||||
|
||||
UpdateWidthText();
|
||||
|
||||
connect(ui->show_play_time, &QCheckBox::STATE_CHANGED, [this]() { UpdateCustomPlaytimeGroupBox(); });
|
||||
connect(ui->use_custom_play_time_format, &QCheckBox::STATE_CHANGED, [this]() { UpdateCustomPlaytimeGroupBox(); });
|
||||
UpdateCustomPlaytimeGroupBox();
|
||||
|
||||
}
|
||||
|
||||
ConfigureUi::~ConfigureUi() = default;
|
||||
|
|
@ -161,11 +169,14 @@ void ConfigureUi::ApplyConfiguration() {
|
|||
UISettings::values.row_1_text_id = ui->row_1_text_combobox->currentData().toUInt();
|
||||
UISettings::values.row_2_text_id = ui->row_2_text_combobox->currentData().toUInt();
|
||||
|
||||
UISettings::values.use_custom_play_time_format = ui->use_custom_play_time_format->isChecked();
|
||||
UISettings::values.custom_play_time_format = ui->custom_play_time_edit->text().toStdString();
|
||||
|
||||
UISettings::values.enable_screenshot_save_as = ui->enable_screenshot_save_as->isChecked();
|
||||
Common::FS::SetEdenPath(Common::FS::EdenPath::ScreenshotsDir,
|
||||
ui->screenshot_path_edit->text().toStdString());
|
||||
|
||||
const u32 height = ScreenshotDimensionToInt(ui->screenshot_height->currentText());
|
||||
const u32 height = ScreenshotDimensionToInt(ui->screenshot_size_combobox->currentText());
|
||||
UISettings::values.screenshot_height.SetValue(height);
|
||||
|
||||
RequestGameListUpdate();
|
||||
|
|
@ -189,6 +200,13 @@ void ConfigureUi::SetConfiguration() {
|
|||
ui->folder_icon_size_combobox->setCurrentIndex(
|
||||
ui->folder_icon_size_combobox->findData(UISettings::values.folder_icon_size.GetValue()));
|
||||
|
||||
ui->use_custom_play_time_format->setChecked(
|
||||
UISettings::values.use_custom_play_time_format.GetValue());
|
||||
ui->custom_play_time_edit->setText(QString::fromStdString(
|
||||
UISettings::values.custom_play_time_format.GetValue()));
|
||||
|
||||
UpdateCustomPlaytimeGroupBox();
|
||||
|
||||
ui->enable_screenshot_save_as->setChecked(
|
||||
UISettings::values.enable_screenshot_save_as.GetValue());
|
||||
ui->screenshot_path_edit->setText(QString::fromStdString(
|
||||
|
|
@ -196,9 +214,9 @@ void ConfigureUi::SetConfiguration() {
|
|||
|
||||
const auto height = UISettings::values.screenshot_height.GetValue();
|
||||
if (height == 0) {
|
||||
ui->screenshot_height->setCurrentIndex(0);
|
||||
ui->screenshot_size_combobox->setCurrentIndex(0);
|
||||
} else {
|
||||
ui->screenshot_height->setCurrentText(QStringLiteral("%1").arg(height));
|
||||
ui->screenshot_size_combobox->setCurrentText(QStringLiteral("%1").arg(height));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -303,7 +321,7 @@ void ConfigureUi::OnLanguageChanged(int index) {
|
|||
}
|
||||
|
||||
void ConfigureUi::UpdateWidthText() {
|
||||
const u32 height = ScreenshotDimensionToInt(ui->screenshot_height->currentText());
|
||||
const u32 height = ScreenshotDimensionToInt(ui->screenshot_size_combobox->currentText());
|
||||
const u32 width = UISettings::CalculateWidth(height, ratio);
|
||||
if (height == 0) {
|
||||
const auto up_factor = GetUpFactor(resolution_setting);
|
||||
|
|
@ -311,16 +329,27 @@ void ConfigureUi::UpdateWidthText() {
|
|||
const u32 width_docked = UISettings::CalculateWidth(height_docked, ratio);
|
||||
const u32 height_undocked = Layout::ScreenUndocked::Height * up_factor;
|
||||
const u32 width_undocked = UISettings::CalculateWidth(height_undocked, ratio);
|
||||
ui->screenshot_width->setText(tr("Auto (%1 x %2, %3 x %4)", "Screenshot width value")
|
||||
ui->screenshot_size_label->setText(tr("Auto (%1 x %2, %3 x %4)", "Screenshot width value")
|
||||
.arg(width_undocked)
|
||||
.arg(height_undocked)
|
||||
.arg(width_docked)
|
||||
.arg(height_docked));
|
||||
} else {
|
||||
ui->screenshot_width->setText(QStringLiteral("%1 x").arg(width));
|
||||
ui->screenshot_size_label->setText(QStringLiteral("%1 x").arg(width));
|
||||
}
|
||||
}
|
||||
|
||||
void ConfigureUi::UpdateCustomPlaytimeGroupBox() {
|
||||
bool showPlayTime = ui->show_play_time->isChecked();
|
||||
bool useCustomPlayTime = ui->use_custom_play_time_format->isChecked();
|
||||
bool enableCheckbox = showPlayTime;
|
||||
bool enableTextBox = showPlayTime && useCustomPlayTime;
|
||||
ui->use_custom_play_time_format->setEnabled(enableCheckbox);
|
||||
ui->custom_play_time_edit->setEnabled(enableTextBox);
|
||||
ui->custom_play_time_label->setEnabled(enableTextBox);
|
||||
ui->custom_play_time_help->setEnabled(enableTextBox);
|
||||
}
|
||||
|
||||
void ConfigureUi::UpdateScreenshotInfo(Settings::AspectRatio ratio_,
|
||||
Settings::ResolutionSetup resolution_setting_) {
|
||||
ratio = ratio_;
|
||||
|
|
|
|||
|
|
@ -1,3 +1,6 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: 2016 Citra Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
|
|
@ -50,6 +53,8 @@ private:
|
|||
|
||||
void UpdateWidthText();
|
||||
|
||||
void UpdateCustomPlaytimeGroupBox();
|
||||
|
||||
std::unique_ptr<Ui::ConfigureUi> ui;
|
||||
|
||||
Settings::AspectRatio ratio;
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>363</width>
|
||||
<height>613</height>
|
||||
<height>693</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
|
|
@ -18,50 +18,46 @@
|
|||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="general_groupBox">
|
||||
<widget class="QGroupBox" name="general_group_box">
|
||||
<property name="title">
|
||||
<string>General</string>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_7">
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<widget class="QLabel" name="label_change_language_info">
|
||||
<property name="text">
|
||||
<string>Note: Changing language will apply your configuration.</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="language_qhbox_layout">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_change_language_info">
|
||||
<widget class="QLabel" name="language_label">
|
||||
<property name="text">
|
||||
<string>Note: Changing language will apply your configuration.</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
<string>Interface language:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<widget class="QLabel" name="language_label">
|
||||
<property name="text">
|
||||
<string>Interface language:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="language_combobox"/>
|
||||
</item>
|
||||
</layout>
|
||||
<widget class="QComboBox" name="language_combobox"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="theme_qhbox_layout">
|
||||
<item>
|
||||
<widget class="QLabel" name="theme_label">
|
||||
<property name="text">
|
||||
<string>Theme:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||
<item>
|
||||
<widget class="QLabel" name="theme_label">
|
||||
<property name="text">
|
||||
<string>Theme:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="theme_combobox"/>
|
||||
</item>
|
||||
</layout>
|
||||
<widget class="QComboBox" name="theme_combobox"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
|
|
@ -69,89 +65,88 @@
|
|||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="GameListGroupBox">
|
||||
<widget class="QGroupBox" name="game_list_group_box">
|
||||
<property name="title">
|
||||
<string>Game List</string>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="GameListHorizontalLayout">
|
||||
<property name="flat">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="GeneralVerticalLayout">
|
||||
<widget class="QCheckBox" name="show_compat">
|
||||
<property name="text">
|
||||
<string>Show Compatibility List</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="show_add_ons">
|
||||
<property name="text">
|
||||
<string>Show Add-Ons Column</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="show_size">
|
||||
<property name="text">
|
||||
<string>Show Size Column</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="show_types">
|
||||
<property name="text">
|
||||
<string>Show File Types Column</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="show_play_time">
|
||||
<property name="text">
|
||||
<string>Show Play Time Column</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="folder_icon_size_qhbox_layout">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="show_compat">
|
||||
<widget class="QLabel" name="folder_icon_size_label">
|
||||
<property name="text">
|
||||
<string>Show Compatibility List</string>
|
||||
<string>Folder Icon Size:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="show_add_ons">
|
||||
<widget class="QComboBox" name="folder_icon_size_combobox"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="row_1_qhbox_layout">
|
||||
<item>
|
||||
<widget class="QLabel" name="row_1_label">
|
||||
<property name="text">
|
||||
<string>Show Add-Ons Column</string>
|
||||
<string>Row 1 Text:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="show_size">
|
||||
<widget class="QComboBox" name="row_1_text_combobox"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="row_2_qhbox_layout">
|
||||
<item>
|
||||
<widget class="QLabel" name="row_2_label">
|
||||
<property name="text">
|
||||
<string>Show Size Column</string>
|
||||
<string>Row 2 Text:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="show_types">
|
||||
<property name="text">
|
||||
<string>Show File Types Column</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="show_play_time">
|
||||
<property name="text">
|
||||
<string>Show Play Time Column</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="folder_icon_size_qhbox_layout_2">
|
||||
<item>
|
||||
<widget class="QLabel" name="folder_icon_size_label">
|
||||
<property name="text">
|
||||
<string>Folder Icon Size:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="folder_icon_size_combobox"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="row_1_qhbox_layout">
|
||||
<item>
|
||||
<widget class="QLabel" name="row_1_label">
|
||||
<property name="text">
|
||||
<string>Row 1 Text:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="row_1_text_combobox"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="row_2_qhbox_layout">
|
||||
<item>
|
||||
<widget class="QLabel" name="row_2_label">
|
||||
<property name="text">
|
||||
<string>Row 2 Text:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="row_2_text_combobox"/>
|
||||
</item>
|
||||
</layout>
|
||||
<widget class="QComboBox" name="row_2_text_combobox"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
|
|
@ -159,75 +154,101 @@
|
|||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="screenshots_GroupBox">
|
||||
<widget class="QGroupBox" name="play_time_group_box">
|
||||
<property name="title">
|
||||
<string>Screenshots</string>
|
||||
<string>Custom Play Time Format</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_4">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_6">
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<widget class="QCheckBox" name="use_custom_play_time_format">
|
||||
<property name="text">
|
||||
<string>Use Custom Play Time Format</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="custom_play_time_qhbox_layout">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="enable_screenshot_save_as">
|
||||
<widget class="QLabel" name="custom_play_time_label">
|
||||
<property name="text">
|
||||
<string>Ask Where To Save Screenshots (Windows Only)</string>
|
||||
<string>Custom Play Time Format:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
||||
<widget class="QLineEdit" name="custom_play_time_edit"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="screenshots_group_box">
|
||||
<property name="title">
|
||||
<string>Screenshots</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="enable_screenshot_save_as">
|
||||
<property name="text">
|
||||
<string>Ask Where To Save Screenshots (Windows Only)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="screenshot_path_layout">
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Screenshots Path: </string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="screenshot_path_edit"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="screenshot_path_button">
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<property name="spacing">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="0" column="1">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_5">
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<widget class="QLabel" name="screenshot_size_label">
|
||||
<property name="text">
|
||||
<string>Screenshots Path: </string>
|
||||
<string>TextLabel</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignmentFlag::AlignRight|Qt::AlignmentFlag::AlignTrailing|Qt::AlignmentFlag::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="screenshot_path_edit"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="screenshot_path_button">
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
<widget class="QComboBox" name="screenshot_size_combobox">
|
||||
<property name="editable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<property name="spacing">
|
||||
<number>6</number>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>Resolution:</string>
|
||||
</property>
|
||||
<item row="0" column="1">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_5">
|
||||
<item>
|
||||
<widget class="QLabel" name="screenshot_width">
|
||||
<property name="text">
|
||||
<string>TextLabel</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignmentFlag::AlignRight|Qt::AlignmentFlag::AlignTrailing|Qt::AlignmentFlag::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="screenshot_height">
|
||||
<property name="editable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>Resolution:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
|
|
|
|||
|
|
@ -86,8 +86,7 @@ public:
|
|||
|
||||
const auto readable_play_time =
|
||||
play_time > 0 ? QObject::tr("Play Time: %1")
|
||||
.arg(QString::fromStdString(
|
||||
PlayTime::PlayTimeManager::GetReadablePlayTime(play_time)))
|
||||
.arg(QString::fromStdString(GetReadablePlayTime(play_time)))
|
||||
: QObject::tr("Never Played");
|
||||
|
||||
const auto enabled_update = [patch_versions]() -> QString {
|
||||
|
|
@ -274,9 +273,8 @@ public:
|
|||
|
||||
void setData(const QVariant& value, int role) override {
|
||||
qulonglong time_seconds = value.toULongLong();
|
||||
GameListItem::setData(
|
||||
QString::fromStdString(PlayTime::PlayTimeManager::GetReadablePlayTime(time_seconds)),
|
||||
Qt::DisplayRole);
|
||||
GameListItem::setData(QString::fromStdString(GetReadablePlayTime(time_seconds)),
|
||||
Qt::DisplayRole);
|
||||
GameListItem::setData(value, PlayTimeRole);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4,19 +4,20 @@
|
|||
#include "frontend_common/play_time_manager.h"
|
||||
#include "ui_set_play_time_dialog.h"
|
||||
#include "yuzu/set_play_time_dialog.h"
|
||||
#include "yuzu/util/util.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))
|
||||
QString::fromStdString(GetPlayTimeHours(current_play_time))
|
||||
.toInt());
|
||||
ui->minutesSpinBox->setValue(
|
||||
QString::fromStdString(PlayTime::PlayTimeManager::GetPlayTimeMinutes(current_play_time))
|
||||
QString::fromStdString(GetPlayTimeMinutes(current_play_time))
|
||||
.toInt());
|
||||
ui->secondsSpinBox->setValue(
|
||||
QString::fromStdString(PlayTime::PlayTimeManager::GetPlayTimeSeconds(current_play_time))
|
||||
QString::fromStdString(GetPlayTimeSeconds(current_play_time))
|
||||
.toInt());
|
||||
|
||||
connect(ui->hoursSpinBox, QOverload<int>::of(&QSpinBox::valueChanged), this,
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@
|
|||
#include "core/frontend/applets/profile_select.h"
|
||||
#include "core/hle/service/acc/profile_manager.h"
|
||||
#include "frontend_common/data_manager.h"
|
||||
#include "qt_common/config/uisettings.h"
|
||||
#include "qt_common/qt_common.h"
|
||||
#include "yuzu/util/util.h"
|
||||
|
||||
|
|
@ -148,6 +149,7 @@ bool SaveIconToFile(const std::filesystem::path& icon_path, const QImage& image)
|
|||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
const std::optional<Common::UUID> GetProfileID() {
|
||||
// if there's only a single profile, the user probably wants to use that... right?
|
||||
const auto& profiles = QtCommon::system->GetProfileManager().FindExistingProfileUUIDs();
|
||||
|
|
@ -185,6 +187,7 @@ const std::optional<Common::UUID> GetProfileID() {
|
|||
|
||||
return uuid;
|
||||
}
|
||||
|
||||
std::string GetProfileIDString() {
|
||||
const auto uuid = GetProfileID();
|
||||
if (!uuid)
|
||||
|
|
@ -194,3 +197,88 @@ std::string GetProfileIDString() {
|
|||
|
||||
return fmt::format("{:016X}{:016X}", user_id[1], user_id[0]);
|
||||
}
|
||||
|
||||
void eraseBetweenStrings(std::string& str, const std::string& start_str,
|
||||
const std::string& end_str) {
|
||||
size_t start_pos = std::string::npos;
|
||||
size_t end_pos = std::string::npos;
|
||||
|
||||
while ((start_pos = str.find(start_str)) != std::string::npos) {
|
||||
end_pos = str.find(end_str, start_pos + start_str.length());
|
||||
|
||||
if (end_pos != std::string::npos) {
|
||||
size_t erase_length = end_pos + end_str.length() - start_pos;
|
||||
str.erase(start_pos, erase_length);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void eraseAll(std::string& str, const std::string& sub_str) {
|
||||
size_t pos = std::string::npos;
|
||||
size_t len = sub_str.length();
|
||||
while ((pos = str.find(sub_str)) != std::string::npos) {
|
||||
str.erase(pos, len);
|
||||
}
|
||||
}
|
||||
|
||||
std::string GetReadablePlayTime(u64 total_seconds) {
|
||||
if (total_seconds <= 0) {
|
||||
return std::string{};
|
||||
}
|
||||
|
||||
if (!UISettings::values.use_custom_play_time_format.GetValue()) {
|
||||
return fmt::format("{:02}:{:02}:{:02}", total_seconds / 3600, (total_seconds % 3600) / 60,
|
||||
total_seconds % 60);
|
||||
}
|
||||
|
||||
u64 total_days = total_seconds / 86400;
|
||||
u64 total_hours = total_seconds / 3600;
|
||||
u64 total_minutes = total_seconds / 60;
|
||||
|
||||
std::string format = UISettings::values.custom_play_time_format.GetValue();
|
||||
|
||||
if (total_days <= 0) {
|
||||
eraseBetweenStrings(format, "[d]", "[/d]");
|
||||
} else {
|
||||
eraseAll(format, "[d]");
|
||||
eraseAll(format, "[/d]");
|
||||
}
|
||||
|
||||
if (total_hours <= 0) {
|
||||
eraseBetweenStrings(format, "[h]", "[/h]");
|
||||
} else {
|
||||
eraseAll(format, "[h]");
|
||||
eraseAll(format, "[/h]");
|
||||
}
|
||||
|
||||
if (total_minutes <= 0) {
|
||||
eraseBetweenStrings(format, "[m]", "[/m]");
|
||||
} else {
|
||||
eraseAll(format, "[m]");
|
||||
eraseAll(format, "[/m]");
|
||||
}
|
||||
|
||||
return fmt::format(fmt::runtime(format),
|
||||
fmt::arg("d", total_days),
|
||||
fmt::arg("h", total_hours),
|
||||
fmt::arg("m", total_minutes),
|
||||
fmt::arg("s", total_seconds),
|
||||
fmt::arg("H", total_hours % 24),
|
||||
fmt::arg("M", total_minutes % 60),
|
||||
fmt::arg("S", total_seconds % 60)
|
||||
);
|
||||
}
|
||||
|
||||
std::string GetPlayTimeHours(u64 total_seconds) {
|
||||
return fmt::format("{}", total_seconds / 3600);
|
||||
}
|
||||
|
||||
std::string GetPlayTimeMinutes(u64 total_seconds) {
|
||||
return fmt::format("{}", (total_seconds % 3600) / 60);
|
||||
}
|
||||
|
||||
std::string GetPlayTimeSeconds(u64 total_seconds) {
|
||||
return fmt::format("{}", total_seconds % 60);
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: 2015 Citra Emulator Project
|
||||
|
|
@ -43,3 +43,8 @@ const std::optional<Common::UUID> GetProfileID();
|
|||
* @return A string representation of the selected profile, or an empty string if none were seleeced
|
||||
*/
|
||||
std::string GetProfileIDString();
|
||||
|
||||
std::string GetReadablePlayTime(u64 time_seconds);
|
||||
std::string GetPlayTimeHours(u64 time_seconds);
|
||||
std::string GetPlayTimeMinutes(u64 time_seconds);
|
||||
std::string GetPlayTimeSeconds(u64 time_seconds);
|
||||
Loading…
Add table
Add a link
Reference in a new issue