Compare commits

...

4 commits

Author SHA1 Message Date
crueter
8678cb06eb
[meta] clang-format literally all of the Qt code (#3706)
Some checks failed
tx-src / sources (push) Has been cancelled
Check Strings / check-strings (push) Has been cancelled
I'm tired of dealing with this tbh

Signed-off-by: crueter <crueter@eden-emu.dev>
Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/3706
Reviewed-by: Lizzie <lizzie@eden-emu.dev>
2026-03-10 06:51:08 +01:00
crueter
769edbfea3
[video_core] Revert "Simplify TextureCache GC and remove redundant code" (#3652) (#3704)
regr. Steam Deck

Please, for the love of God, stop saying "YOLO good to merge" after
testers report performance regressions (and promptly get brushed to the
side). Seriously, what the hell?

This reverts commit f8ea09fa0f.

Signed-off-by: crueter <crueter@eden-emu.dev>
Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/3704
Reviewed-by: Lizzie <lizzie@eden-emu.dev>
Reviewed-by: DraVee <chimera@dravee.dev>
2026-03-10 05:44:51 +01:00
crueter
0ff1d215c8
[desktop] Port some QtCommon changes from QML branch (#3703)
- Linker now resolves implementation differences
- Remove unneeded ifdefs
- Better abstractions overall

Signed-off-by: crueter <crueter@eden-emu.dev>
Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/3703
Reviewed-by: Lizzie <lizzie@eden-emu.dev>
Reviewed-by: CamilleLaVey <camillelavey99@gmail.com>
2026-03-10 05:37:45 +01:00
crueter
07e3a2aa46
[settings] Disable fastmem on Linux systems with non-4kb page sizes (#3669)
Asahi, etc

Signed-off-by: crueter <crueter@eden-emu.dev>
Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/3669
Reviewed-by: Lizzie <lizzie@eden-emu.dev>
Reviewed-by: CamilleLaVey <camillelavey99@gmail.com>
2026-03-10 05:36:12 +01:00
121 changed files with 1962 additions and 2082 deletions

View file

@ -115,7 +115,7 @@ for file in $FILES; do
*.cmake|*.sh|*CMakeLists.txt)
begin="#"
;;
*.kt*|*.cpp|*.h)
*.kt*|*.cpp|*.h|*.qml)
begin="//"
;;
*)
@ -193,7 +193,7 @@ if [ "$UPDATE" = "true" ]; then
begin="#"
shell=true
;;
*.kt*|*.cpp|*.h)
*)
begin="//"
shell="false"
;;

View file

@ -242,7 +242,6 @@ if (YUZU_CMD)
endif()
if (ENABLE_QT)
add_definitions(-DYUZU_QT_WIDGETS)
add_subdirectory(qt_common)
add_subdirectory(yuzu)
endif()

View file

@ -27,6 +27,10 @@
#include "common/settings.h"
#include "common/time_zone.h"
#if defined(__linux__ ) && defined(ARCHITECTURE_arm64)
#include <unistd.h>
#endif
namespace Settings {
// Clang 14 and earlier have errors when explicitly instantiating these classes
@ -178,7 +182,11 @@ bool IsFastmemEnabled() {
return bool(values.cpuopt_fastmem);
else if (values.cpu_accuracy.GetValue() == CpuAccuracy::Unsafe)
return bool(values.cpuopt_unsafe_host_mmu);
#if !defined(__APPLE__) && !defined(__linux__) && !defined(__ANDROID__) && !defined(_WIN32)
#if defined(__linux__) && defined(ARCHITECTURE_arm64)
// Only 4kb systems support host MMU right now
// TODO: Support this
return getpagesize() == 4096;
#elif !defined(__APPLE__) && !defined(__ANDROID__) && !defined(_WIN32) && !defined(__linux__)
return false;
#else
return true;

View file

@ -1,6 +1,8 @@
# SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
# SPDX-License-Identifier: GPL-3.0-or-later
set(CMAKE_AUTOMOC ON)
add_library(qt_common STATIC
qt_common.h
qt_common.cpp
@ -26,7 +28,7 @@ add_library(qt_common STATIC
util/mod.h util/mod.cpp
abstract/frontend.h abstract/frontend.cpp
abstract/qt_progress_dialog.h abstract/qt_progress_dialog.cpp
abstract/progress.h abstract/progress.cpp
qt_string_lookup.h
qt_compat.h
@ -93,3 +95,5 @@ if (UNIX AND NOT APPLE)
target_link_libraries(qt_common PRIVATE Qt6::GuiPrivate)
endif()
endif()
create_target_directory_groups(qt_common)

View file

@ -1,75 +1,27 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#include <QLineEdit>
#include "frontend.h"
#include "qt_common/qt_common.h"
#ifdef YUZU_QT_WIDGETS
#include <QFileDialog>
#endif
#include <QAbstractButton>
#include <QInputDialog>
namespace QtCommon::Frontend {
StandardButton ShowMessage(Icon icon, const QString& title, const QString& text,
StandardButtons buttons, QObject* parent) {
#ifdef YUZU_QT_WIDGETS
QMessageBox* box = new QMessageBox(icon, title, text, buttons, (QWidget*)parent);
return static_cast<QMessageBox::StandardButton>(box->exec());
#endif
// TODO(crueter): If Qt Widgets is disabled...
// need a way to reference icon/buttons too
}
const QString GetOpenFileName(const QString& title, const QString& dir, const QString& filter,
QString* selectedFilter, Options options) {
#ifdef YUZU_QT_WIDGETS
return QFileDialog::getOpenFileName(rootObject, title, dir, filter, selectedFilter, options);
#endif
QString* selectedFilter) {
return QFileDialog::getOpenFileName(rootObject, title, dir, filter, selectedFilter);
}
const QStringList GetOpenFileNames(const QString& title, const QString& dir, const QString& filter,
QString* selectedFilter, Options options) {
#ifdef YUZU_QT_WIDGETS
return QFileDialog::getOpenFileNames(rootObject, title, dir, filter, selectedFilter, options);
#endif
QString* selectedFilter) {
return QFileDialog::getOpenFileNames(rootObject, title, dir, filter, selectedFilter);
}
const QString GetSaveFileName(const QString& title, const QString& dir, const QString& filter,
QString* selectedFilter, Options options) {
#ifdef YUZU_QT_WIDGETS
return QFileDialog::getSaveFileName(rootObject, title, dir, filter, selectedFilter, options);
#endif
QString* selectedFilter) {
return QFileDialog::getSaveFileName(rootObject, title, dir, filter, selectedFilter);
}
const QString GetExistingDirectory(const QString& caption, const QString& dir, Options options) {
#ifdef YUZU_QT_WIDGETS
return QFileDialog::getExistingDirectory(rootObject, caption, dir, options);
#endif
}
int Choice(const QString& title, const QString& caption, const QStringList& options) {
QMessageBox box(rootObject);
box.setText(caption);
box.setWindowTitle(title);
for (const QString& opt : options) {
box.addButton(opt, QMessageBox::AcceptRole);
}
box.addButton(QMessageBox::Cancel);
box.exec();
auto button = box.clickedButton();
return options.indexOf(button->text());
}
const QString GetTextInput(const QString& title, const QString& caption,
const QString& defaultText) {
return QInputDialog::getText(rootObject, title, caption, QLineEdit::Normal, defaultText);
const QString GetExistingDirectory(const QString& caption, const QString& dir) {
return QFileDialog::getExistingDirectory(rootObject, caption, dir);
}
} // namespace QtCommon::Frontend

View file

@ -7,11 +7,7 @@
#include <QGuiApplication>
#include "qt_common/qt_common.h"
#ifdef YUZU_QT_WIDGETS
#include <QFileDialog>
#include <QWidget>
#include <QMessageBox>
#endif
/**
* manages common functionality e.g. message boxes and such for Qt/QML
@ -20,30 +16,9 @@ namespace QtCommon::Frontend {
Q_NAMESPACE
#ifdef YUZU_QT_WIDGETS
using Options = QFileDialog::Options;
using Option = QFileDialog::Option;
using StandardButton = QMessageBox::StandardButton;
using StandardButtons = QMessageBox::StandardButtons;
using Icon = QMessageBox::Icon;
#else
enum Option {
ShowDirsOnly = 0x00000001,
DontResolveSymlinks = 0x00000002,
DontConfirmOverwrite = 0x00000004,
DontUseNativeDialog = 0x00000008,
ReadOnly = 0x00000010,
HideNameFilterDetails = 0x00000020,
DontUseCustomDirectoryIcons = 0x00000040
};
Q_ENUM_NS(Option)
Q_DECLARE_FLAGS(Options, Option)
Q_FLAG_NS(Options)
enum StandardButton {
// keep this in sync with QDialogButtonBox::StandardButton and QPlatformDialogHelper::StandardButton
// keep this in sync with QDialogButtonBox::StandardButton and
// QPlatformDialogHelper::StandardButton
NoButton = 0x00000000,
Ok = 0x00000400,
Save = 0x00000800,
@ -83,7 +58,7 @@ typedef StandardButton Button;
Q_DECLARE_FLAGS(StandardButtons, StandardButton)
Q_FLAG_NS(StandardButtons)
enum Icon {
enum class Icon {
// keep this in sync with QMessageDialogOptions::StandardIcon
NoIcon = 0,
Information = 1,
@ -93,29 +68,26 @@ enum Icon {
};
Q_ENUM_NS(Icon)
#endif
// TODO(crueter) widgets-less impl, choices et al.
StandardButton ShowMessage(Icon icon,
const QString &title,
const QString &text,
StandardButton ShowMessage(Icon icon, const QString& title, const QString& text,
StandardButtons buttons = StandardButton::NoButton,
QObject *parent = nullptr);
QObject* parent = nullptr);
#define UTIL_OVERRIDES(level) \
inline StandardButton level(QObject *parent, \
const QString &title, \
const QString &text, \
StandardButtons buttons = StandardButton::Ok) \
{ \
inline StandardButton level(QObject* parent, const QString& title, const QString& text, \
StandardButtons buttons) { \
return ShowMessage(Icon::level, title, text, buttons, parent); \
} \
inline StandardButton level(const QString title, \
const QString &text, \
StandardButtons buttons \
= StandardButton::Ok) \
{ \
inline StandardButton level(QObject* parent, const QString& title, const QString& text, \
int buttons = StandardButton::Ok) { \
return ShowMessage(Icon::level, title, text, StandardButtons(buttons), parent); \
} \
inline StandardButton level(const QString title, const QString& text, \
StandardButtons buttons) { \
return ShowMessage(Icon::level, title, text, buttons, rootObject); \
} \
inline StandardButton level(const QString& title, const QString& text, \
int buttons = StandardButton::Ok) { \
return ShowMessage(Icon::level, title, text, StandardButtons(buttons), rootObject); \
}
UTIL_OVERRIDES(Information)
@ -123,27 +95,17 @@ UTIL_OVERRIDES(Warning)
UTIL_OVERRIDES(Critical)
UTIL_OVERRIDES(Question)
const QString GetOpenFileName(const QString &title,
const QString &dir,
const QString &filter,
QString *selectedFilter = nullptr,
Options options = Options());
const QString GetOpenFileName(const QString& title, const QString& dir, const QString& filter,
QString* selectedFilter = nullptr);
const QStringList GetOpenFileNames(const QString &title,
const QString &dir,
const QString &filter,
QString *selectedFilter = nullptr,
Options options = Options());
const QStringList GetOpenFileNames(const QString& title, const QString& dir, const QString& filter,
QString* selectedFilter = nullptr);
const QString GetSaveFileName(const QString &title,
const QString &dir,
const QString &filter,
QString *selectedFilter = nullptr,
Options options = Options());
const QString GetSaveFileName(const QString& title, const QString& dir, const QString& filter,
QString* selectedFilter = nullptr);
const QString GetExistingDirectory(const QString &caption = QString(),
const QString &dir = QString(),
Options options = Option::ShowDirsOnly);
const QString GetExistingDirectory(const QString& caption = QString(),
const QString& dir = QString());
int Choice(const QString& title = QString(), const QString& caption = QString(),
const QStringList& options = {});

View file

@ -0,0 +1,12 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#include "progress.h"
namespace QtCommon::Frontend {
QtProgressDialog::QtProgressDialog(const QString&, const QString&, int, int, QObject* parent,
Qt::WindowFlags)
: QObject(parent) {}
} // namespace QtCommon::Frontend

View file

@ -0,0 +1,45 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#pragma once
#include <memory>
#include <QObject>
namespace QtCommon::Frontend {
class QtProgressDialog : public QObject {
Q_OBJECT
public:
QtProgressDialog(const QString& labelText, const QString& cancelButtonText, int minimum,
int maximum, QObject* parent = nullptr, Qt::WindowFlags f = Qt::WindowFlags());
virtual ~QtProgressDialog() = default;
virtual bool wasCanceled() const = 0;
virtual void setWindowModality(Qt::WindowModality modality) = 0;
virtual void setMinimumDuration(int durationMs) = 0;
virtual void setAutoClose(bool autoClose) = 0;
virtual void setAutoReset(bool autoReset) = 0;
public slots:
virtual void setTitle(QString title) = 0;
virtual void setLabelText(QString text) = 0;
virtual void setMinimum(int min) = 0;
virtual void setMaximum(int max) = 0;
virtual void setValue(int value) = 0;
virtual bool close() = 0;
virtual void show() = 0;
};
std::unique_ptr<QtProgressDialog> newProgressDialog(const QString& labelText,
const QString& cancelButtonText, int minimum,
int maximum,
Qt::WindowFlags f = Qt::WindowFlags());
QtProgressDialog* newProgressDialogPtr(const QString& labelText, const QString& cancelButtonText,
int minimum, int maximum,
Qt::WindowFlags f = Qt::WindowFlags());
} // namespace QtCommon::Frontend

View file

@ -1,4 +0,0 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#include "qt_progress_dialog.h"

View file

@ -1,47 +0,0 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#ifndef QT_PROGRESS_DIALOG_H
#define QT_PROGRESS_DIALOG_H
#include <QWindow>
#ifdef YUZU_QT_WIDGETS
#include <QProgressDialog>
#endif
namespace QtCommon::Frontend {
#ifdef YUZU_QT_WIDGETS
using QtProgressDialog = QProgressDialog;
// TODO(crueter): QML impl
#else
class QtProgressDialog
{
public:
QtProgressDialog(const QString &labelText,
const QString &cancelButtonText,
int minimum,
int maximum,
QObject *parent = nullptr,
Qt::WindowFlags f = Qt::WindowFlags());
bool wasCanceled() const;
void setWindowModality(Qt::WindowModality modality);
void setMinimumDuration(int durationMs);
void setAutoClose(bool autoClose);
void setAutoReset(bool autoReset);
public slots:
void setLabelText(QString &text);
void setRange(int min, int max);
void setValue(int progress);
bool close();
void show();
};
#endif // YUZU_QT_WIDGETS
}
#endif // QT_PROGRESS_DIALOG_H

View file

@ -319,7 +319,7 @@ void QtConfig::ReadUIGamelistValues() {
}
void QtConfig::ReadUILayoutValues() {
BeginGroup(Settings::TranslateCategory(Settings::Category::UiGameList));
BeginGroup(Settings::TranslateCategory(Settings::Category::UiLayout));
ReadCategory(Settings::Category::UiLayout);
@ -578,10 +578,10 @@ void QtConfig::SaveMultiplayerValues() {
}
std::vector<Settings::BasicSetting*>& QtConfig::FindRelevantList(Settings::Category category) {
auto& map = Settings::values.linkage.by_category;
if (map.contains(category)) {
return Settings::values.linkage.by_category[category];
}
auto& list = Settings::values.linkage.by_category[category];
if (!list.empty())
return list;
return UISettings::values.linkage.by_category[category];
}

View file

@ -9,20 +9,19 @@
#include "shared_translation.h"
#include <map>
#include <memory>
#include <utility>
#include <QCoreApplication>
#include "common/settings.h"
#include "common/settings_enums.h"
#include "common/settings_setting.h"
#include "common/time_zone.h"
#include "qt_common/config/uisettings.h"
#include <map>
#include <memory>
#include <utility>
namespace ConfigurationShared {
std::unique_ptr<TranslationMap> InitializeTranslations(QObject* parent)
{
std::unique_ptr<TranslationMap> InitializeTranslations(QObject* parent) {
std::unique_ptr<TranslationMap> translations = std::make_unique<TranslationMap>();
const auto& tr = [parent](const char* text) -> QString { return parent->tr(text); };
@ -47,10 +46,9 @@ std::unique_ptr<TranslationMap> InitializeTranslations(QObject* parent)
INSERT(Settings, login_share_applet_mode, tr("Login share"), QString());
INSERT(Settings, wifi_web_auth_applet_mode, tr("Wifi web auth"), QString());
INSERT(Settings, my_page_applet_mode, tr("My page"), QString());
INSERT(Settings,
enable_overlay,
tr("Enable Overlay Applet"),
tr("Enables Horizon\'s built-in overlay applet. Press and hold the home button for 1 second to show it."));
INSERT(Settings, enable_overlay, tr("Enable Overlay Applet"),
tr("Enables Horizon\'s built-in overlay applet. Press and hold the home button for 1 "
"second to show it."));
// Audio
INSERT(Settings, sink_id, tr("Output Engine:"), QString());
@ -62,23 +60,16 @@ std::unique_ptr<TranslationMap> InitializeTranslations(QObject* parent)
INSERT(UISettings, mute_when_in_background, tr("Mute audio when in background"), QString());
// Core
INSERT(
Settings,
use_multi_core,
tr("Multicore CPU Emulation"),
INSERT(Settings, use_multi_core, tr("Multicore CPU Emulation"),
tr("This option increases CPU emulation thread use from 1 to the maximum of 4.\n"
"This is mainly a debug option and shouldn't be disabled."));
INSERT(
Settings,
memory_layout_mode,
tr("Memory Layout"),
tr("Increases the amount of emulated RAM.\nDoesn't affect performance/stability but may allow HD texture "
INSERT(Settings, memory_layout_mode, tr("Memory Layout"),
tr("Increases the amount of emulated RAM.\nDoesn't affect performance/stability but may "
"allow HD texture "
"mods to load."));
INSERT(Settings, use_speed_limit, QString(), QString());
INSERT(Settings, current_speed_mode, QString(), QString());
INSERT(Settings,
speed_limit,
tr("Limit Speed Percent"),
INSERT(Settings, speed_limit, tr("Limit Speed Percent"),
tr("Controls the game's maximum rendering speed, but it's up to each game if it runs "
"faster or not.\n200% for a 30 FPS game is 60 FPS, and for a "
"60 FPS game it will be 120 FPS.\nDisabling it means unlocking the framerate to the "
@ -91,166 +82,123 @@ std::unique_ptr<TranslationMap> InitializeTranslations(QObject* parent)
tr("When the Slow Speed hotkey is pressed, the speed will be limited to this "
"percentage."));
INSERT(Settings,
sync_core_speed,
tr("Synchronize Core Speed"),
INSERT(Settings, sync_core_speed, tr("Synchronize Core Speed"),
tr("Synchronizes CPU core speed with the game's maximum rendering speed to boost FPS "
"without affecting game speed (animations, physics, etc.).\n"
"Can help reduce stuttering at lower framerates."));
// Cpu
INSERT(Settings,
cpu_accuracy,
tr("Accuracy:"),
INSERT(Settings, cpu_accuracy, tr("Accuracy:"),
tr("Change the accuracy of the emulated CPU (for debugging only)."));
INSERT(Settings, cpu_backend, tr("Backend:"), QString());
INSERT(Settings,
fast_cpu_time,
tr("CPU Overclock"),
tr("Overclocks the emulated CPU to remove some FPS limiters. Weaker CPUs may see reduced performance, "
"and certain games may behave improperly.\nUse Boost (1700MHz) to run at the Switch's highest native "
INSERT(Settings, fast_cpu_time, tr("CPU Overclock"),
tr("Overclocks the emulated CPU to remove some FPS limiters. Weaker CPUs may see "
"reduced performance, "
"and certain games may behave improperly.\nUse Boost (1700MHz) to run at the "
"Switch's highest native "
"clock, or Fast (2000MHz) to run at 2x clock."));
INSERT(Settings, use_custom_cpu_ticks, QString(), QString());
INSERT(Settings,
cpu_ticks,
tr("Custom CPU Ticks"),
INSERT(Settings, cpu_ticks, tr("Custom CPU Ticks"),
tr("Set a custom value of CPU ticks. Higher values can increase performance, but may "
"cause deadlocks. A range of 77-21000 is recommended."));
INSERT(Settings, cpu_backend, tr("Backend:"), QString());
INSERT(Settings, vtable_bouncing,
tr("Virtual Table Bouncing"),
tr("Bounces (by emulating a 0-valued return) any functions that triggers a prefetch abort"));
INSERT(Settings, vtable_bouncing, tr("Virtual Table Bouncing"),
tr("Bounces (by emulating a 0-valued return) any functions that triggers a prefetch "
"abort"));
// Cpu Debug
// Cpu Unsafe
INSERT(Settings, cpuopt_unsafe_host_mmu, tr("Enable Host MMU Emulation (fastmem)"),
tr("This optimization speeds up memory accesses by the guest program.\nEnabling it causes guest memory reads/writes to be done directly into memory and make use of Host's MMU.\nDisabling this forces all memory accesses to use Software MMU Emulation."));
INSERT(
Settings,
cpuopt_unsafe_unfuse_fma,
Settings, cpuopt_unsafe_host_mmu, tr("Enable Host MMU Emulation (fastmem)"),
tr("This optimization speeds up memory accesses by the guest program.\nEnabling it causes "
"guest memory reads/writes to be done directly into memory and make use of Host's "
"MMU.\nDisabling this forces all memory accesses to use Software MMU Emulation."));
INSERT(
Settings, cpuopt_unsafe_unfuse_fma,
tr("Unfuse FMA (improve performance on CPUs without FMA)"),
tr("This option improves speed by reducing accuracy of fused-multiply-add instructions on "
"CPUs without native FMA support."));
INSERT(
Settings,
cpuopt_unsafe_reduce_fp_error,
tr("Faster FRSQRTE and FRECPE"),
Settings, cpuopt_unsafe_reduce_fp_error, tr("Faster FRSQRTE and FRECPE"),
tr("This option improves the speed of some approximate floating-point functions by using "
"less accurate native approximations."));
INSERT(Settings,
cpuopt_unsafe_ignore_standard_fpcr,
INSERT(Settings, cpuopt_unsafe_ignore_standard_fpcr,
tr("Faster ASIMD instructions (32 bits only)"),
tr("This option improves the speed of 32 bits ASIMD floating-point functions by running "
"with incorrect rounding modes."));
INSERT(Settings,
cpuopt_unsafe_inaccurate_nan,
tr("Inaccurate NaN handling"),
INSERT(Settings, cpuopt_unsafe_inaccurate_nan, tr("Inaccurate NaN handling"),
tr("This option improves speed by removing NaN checking.\nPlease note this also reduces "
"accuracy of certain floating-point instructions."));
INSERT(Settings,
cpuopt_unsafe_fastmem_check,
tr("Disable address space checks"),
INSERT(Settings, cpuopt_unsafe_fastmem_check, tr("Disable address space checks"),
tr("This option improves speed by eliminating a safety check before every memory "
"operation.\nDisabling it may allow arbitrary code execution."));
INSERT(
Settings,
cpuopt_unsafe_ignore_global_monitor,
tr("Ignore global monitor"),
Settings, cpuopt_unsafe_ignore_global_monitor, tr("Ignore global monitor"),
tr("This option improves speed by relying only on the semantics of cmpxchg to ensure "
"safety of exclusive access instructions.\nPlease note this may result in deadlocks and "
"other race conditions."));
// Renderer
INSERT(
Settings,
renderer_backend,
tr("API:"),
INSERT(Settings, renderer_backend, tr("API:"),
tr("Changes the output graphics API.\nVulkan is recommended."));
INSERT(Settings,
vulkan_device,
tr("Device:"),
INSERT(Settings, vulkan_device, tr("Device:"),
tr("This setting selects the GPU to use (Vulkan only)."));
INSERT(Settings,
resolution_setup,
tr("Resolution:"),
INSERT(Settings, resolution_setup, tr("Resolution:"),
tr("Forces to render at a different resolution.\n"
"Higher resolutions require more VRAM and bandwidth.\n"
"Options lower than 1X can cause artifacts."));
INSERT(Settings, scaling_filter, tr("Window Adapting Filter:"), QString());
INSERT(Settings,
fsr_sharpening_slider,
tr("FSR Sharpness:"),
INSERT(Settings, fsr_sharpening_slider, tr("FSR Sharpness:"),
tr("Determines how sharpened the image will look using FSR's dynamic contrast."));
INSERT(Settings,
anti_aliasing,
tr("Anti-Aliasing Method:"),
INSERT(Settings, anti_aliasing, tr("Anti-Aliasing Method:"),
tr("The anti-aliasing method to use.\nSMAA offers the best quality.\nFXAA "
"can produce a more stable picture in lower resolutions."));
INSERT(Settings,
fullscreen_mode,
tr("Fullscreen Mode:"),
INSERT(Settings, fullscreen_mode, tr("Fullscreen Mode:"),
tr("The method used to render the window in fullscreen.\nBorderless offers the best "
"compatibility with the on-screen keyboard that some games request for "
"input.\nExclusive "
"fullscreen may offer better performance and better Freesync/Gsync support."));
INSERT(Settings,
aspect_ratio,
tr("Aspect Ratio:"),
INSERT(Settings, aspect_ratio, tr("Aspect Ratio:"),
tr("Stretches the renderer to fit the specified aspect ratio.\nMost games only support "
"16:9, so modifications are required to get other ratios.\nAlso controls the "
"aspect ratio of captured screenshots."));
INSERT(Settings,
use_disk_shader_cache,
tr("Use persistent pipeline cache"),
INSERT(Settings, use_disk_shader_cache, tr("Use persistent pipeline cache"),
tr("Allows saving shaders to storage for faster loading on following game "
"boots.\nDisabling it is only intended for debugging."));
INSERT(Settings,
optimize_spirv_output,
tr("Optimize SPIRV output"),
INSERT(Settings, optimize_spirv_output, tr("Optimize SPIRV output"),
tr("Runs an additional optimization pass over generated SPIRV shaders.\n"
"Will increase time required for shader compilation.\nMay slightly improve "
"performance.\nThis feature is experimental."));
INSERT(Settings,
nvdec_emulation,
tr("NVDEC emulation:"),
INSERT(Settings, nvdec_emulation, tr("NVDEC emulation:"),
tr("Specifies how videos should be decoded.\nIt can either use the CPU or the GPU for "
"decoding, or perform no decoding at all (black screen on videos).\n"
"In most cases, GPU decoding provides the best performance."));
INSERT(Settings,
accelerate_astc,
tr("ASTC Decoding Method:"),
INSERT(Settings, accelerate_astc, tr("ASTC Decoding Method:"),
tr("This option controls how ASTC textures should be decoded.\n"
"CPU: Use the CPU for decoding.\n"
"GPU: Use the GPU's compute shaders to decode ASTC textures (recommended).\n"
"CPU Asynchronously: Use the CPU to decode ASTC textures on demand. Eliminates"
"ASTC decoding\nstuttering but may present artifacts."));
INSERT(
Settings,
astc_recompression,
tr("ASTC Recompression Method:"),
INSERT(Settings, astc_recompression, tr("ASTC Recompression Method:"),
tr("Most GPUs lack support for ASTC textures and must decompress to an"
"intermediate format: RGBA8.\n"
"BC1/BC3: The intermediate format will be recompressed to BC1 or BC3 format,\n"
" saving VRAM but degrading image quality."));
INSERT(Settings, frame_pacing_mode, tr("Frame Pacing Mode (Vulkan only)"),
tr("Controls how the emulator manages frame pacing to reduce stuttering and make the frame rate smoother and more consistent."));
INSERT(Settings,
vram_usage_mode,
tr("VRAM Usage Mode:"),
tr("Selects whether the emulator should prefer to conserve memory or make maximum usage of available video memory for performance.\nAggressive mode may impact performance of other applications such as recording software."));
INSERT(Settings,
skip_cpu_inner_invalidation,
tr("Skip CPU Inner Invalidation"),
tr("Controls how the emulator manages frame pacing to reduce stuttering and make the "
"frame rate smoother and more consistent."));
INSERT(Settings, vram_usage_mode, tr("VRAM Usage Mode:"),
tr("Selects whether the emulator should prefer to conserve memory or make maximum usage "
"of available video memory for performance.\nAggressive mode may impact performance "
"of other applications such as recording software."));
INSERT(Settings, skip_cpu_inner_invalidation, tr("Skip CPU Inner Invalidation"),
tr("Skips certain cache invalidations during memory updates, reducing CPU usage and "
"improving latency. This may cause soft-crashes."));
INSERT(
Settings,
vsync_mode,
tr("VSync Mode:"),
INSERT(Settings, vsync_mode, tr("VSync Mode:"),
tr("FIFO (VSync) does not drop frames or exhibit tearing but is limited by the screen "
"refresh rate.\nFIFO Relaxed allows tearing as it recovers from a slow down.\n"
"Mailbox can have lower latency than FIFO and does not tear but may drop "
@ -264,103 +212,74 @@ std::unique_ptr<TranslationMap> InitializeTranslations(QObject* parent)
INSERT(Settings, use_asynchronous_gpu_emulation, QString(), QString());
INSERT(Settings, sync_memory_operations, tr("Sync Memory Operations"),
tr("Ensures data consistency between compute and memory operations.\nThis option fixes issues in games, but may degrade performance.\nUnreal Engine 4 games often see the most significant changes thereof."));
INSERT(Settings,
async_presentation,
tr("Enable asynchronous presentation (Vulkan only)"),
tr("Ensures data consistency between compute and memory operations.\nThis option fixes "
"issues in games, but may degrade performance.\nUnreal Engine 4 games often see the "
"most significant changes thereof."));
INSERT(Settings, async_presentation, tr("Enable asynchronous presentation (Vulkan only)"),
tr("Slightly improves performance by moving presentation to a separate CPU thread."));
INSERT(
Settings,
renderer_force_max_clock,
tr("Force maximum clocks (Vulkan only)"),
Settings, renderer_force_max_clock, tr("Force maximum clocks (Vulkan only)"),
tr("Runs work in the background while waiting for graphics commands to keep the GPU from "
"lowering its clock speed."));
INSERT(Settings,
max_anisotropy,
tr("Anisotropic Filtering:"),
tr("Controls the quality of texture rendering at oblique angles.\nSafe to set at 16x on most GPUs."));
INSERT(Settings,
gpu_accuracy,
tr("GPU Mode:"),
tr("Controls the GPU emulation mode.\nMost games render fine with Fast or Balanced modes, but Accurate is still "
INSERT(Settings, max_anisotropy, tr("Anisotropic Filtering:"),
tr("Controls the quality of texture rendering at oblique angles.\nSafe to set at 16x on "
"most GPUs."));
INSERT(Settings, gpu_accuracy, tr("GPU Mode:"),
tr("Controls the GPU emulation mode.\nMost games render fine with Fast or Balanced "
"modes, but Accurate is still "
"required for some.\nParticles tend to only render correctly with Accurate mode."));
INSERT(Settings,
dma_accuracy,
tr("DMA Accuracy:"),
tr("Controls the DMA precision accuracy. Safe precision fixes issues in some games but may degrade performance."));
INSERT(Settings,
use_asynchronous_shaders,
tr("Enable asynchronous shader compilation"),
INSERT(Settings, dma_accuracy, tr("DMA Accuracy:"),
tr("Controls the DMA precision accuracy. Safe precision fixes issues in some games but "
"may degrade performance."));
INSERT(Settings, use_asynchronous_shaders, tr("Enable asynchronous shader compilation"),
tr("May reduce shader stutter."));
INSERT(Settings,
fast_gpu_time,
tr("Fast GPU Time"),
INSERT(Settings, fast_gpu_time, tr("Fast GPU Time"),
tr("Overclocks the emulated GPU to increase dynamic resolution and render "
"distance.\nUse 256 for maximal performance and 512 for maximal graphics fidelity."));
INSERT(Settings,
gpu_unswizzle_enabled,
tr("GPU Unswizzle"),
INSERT(Settings, gpu_unswizzle_enabled, tr("GPU Unswizzle"),
tr("Accelerates BCn 3D texture decoding using GPU compute.\n"
"Disable if experiencing crashes or graphical glitches."));
INSERT(Settings,
gpu_unswizzle_texture_size,
tr("GPU Unswizzle Max Texture Size"),
INSERT(Settings, gpu_unswizzle_texture_size, tr("GPU Unswizzle Max Texture Size"),
tr("Sets the maximum size (MiB) for GPU-based texture unswizzling.\n"
"While the GPU is faster for medium and large textures, the CPU may be more efficient for very small ones.\n"
"While the GPU is faster for medium and large textures, the CPU may be more "
"efficient for very small ones.\n"
"Adjust this to find the balance between GPU acceleration and CPU overhead."));
INSERT(Settings,
gpu_unswizzle_stream_size,
tr("GPU Unswizzle Stream Size"),
INSERT(Settings, gpu_unswizzle_stream_size, tr("GPU Unswizzle Stream Size"),
tr("Sets the maximum amount of texture data (in MiB) processed per frame.\n"
"Higher values can reduce stutter during texture loading but may impact frame consistency."));
INSERT(Settings,
gpu_unswizzle_chunk_size,
tr("GPU Unswizzle Chunk Size"),
"Higher values can reduce stutter during texture loading but may impact frame "
"consistency."));
INSERT(Settings, gpu_unswizzle_chunk_size, tr("GPU Unswizzle Chunk Size"),
tr("Determines the number of depth slices processed in a single dispatch.\n"
"Increasing this can improve throughput on high-end GPUs but may cause TDR or driver timeouts on weaker hardware."));
"Increasing this can improve throughput on high-end GPUs but may cause TDR or driver "
"timeouts on weaker hardware."));
INSERT(Settings,
use_vulkan_driver_pipeline_cache,
tr("Use Vulkan pipeline cache"),
INSERT(Settings, use_vulkan_driver_pipeline_cache, tr("Use Vulkan pipeline cache"),
tr("Enables GPU vendor-specific pipeline cache.\nThis option can improve shader loading "
"time significantly in cases where the Vulkan driver does not store pipeline cache "
"files internally."));
INSERT(
Settings,
enable_compute_pipelines,
tr("Enable Compute Pipelines (Intel Vulkan Only)"),
INSERT(Settings, enable_compute_pipelines, tr("Enable Compute Pipelines (Intel Vulkan Only)"),
tr("Required by some games.\nThis setting only exists for Intel "
"proprietary drivers and may crash if enabled.\nCompute pipelines are always enabled "
"on all other drivers."));
INSERT(
Settings,
use_reactive_flushing,
tr("Enable Reactive Flushing"),
Settings, use_reactive_flushing, tr("Enable Reactive Flushing"),
tr("Uses reactive flushing instead of predictive flushing, allowing more accurate memory "
"syncing."));
INSERT(Settings,
use_video_framerate,
tr("Sync to framerate of video playback"),
INSERT(Settings, use_video_framerate, tr("Sync to framerate of video playback"),
tr("Run the game at normal speed during video playback, even when the framerate is "
"unlocked."));
INSERT(Settings,
barrier_feedback_loops,
tr("Barrier feedback loops"),
INSERT(Settings, barrier_feedback_loops, tr("Barrier feedback loops"),
tr("Improves rendering of transparency effects in specific games."));
INSERT(Settings,
enable_buffer_history,
tr("Enable buffer history"),
tr("Enables access to previous buffer states.\nThis option may improve rendering quality and performance consistency in some games."));
INSERT(Settings,
fix_bloom_effects,
tr("Fix bloom effects"),
tr("Removes bloom in Burnout."));
INSERT(Settings, enable_buffer_history, tr("Enable buffer history"),
tr("Enables access to previous buffer states.\nThis option may improve rendering "
"quality and performance consistency in some games."));
INSERT(Settings, fix_bloom_effects, tr("Fix bloom effects"), tr("Removes bloom in Burnout."));
INSERT(Settings,
rescale_hack,
tr("Enable Legacy Rescale Pass"),
tr("May fix rescale issues in some games by relying on behavior from the previous implementation.\n"
"Legacy behavior workaround that fixes line artifacts on AMD and Intel GPUs, and grey texture flicker on Nvidia GPUs in Luigis Mansion 3."));
INSERT(Settings, rescale_hack, tr("Enable Legacy Rescale Pass"),
tr("May fix rescale issues in some games by relying on behavior from the previous "
"implementation.\n"
"Legacy behavior workaround that fixes line artifacts on AMD and Intel GPUs, and "
"grey texture flicker on Nvidia GPUs in Luigis Mansion 3."));
// Renderer (Extensions)
INSERT(Settings, dyna_state, tr("Extended Dynamic State"),
@ -368,26 +287,19 @@ std::unique_ptr<TranslationMap> InitializeTranslations(QObject* parent)
"Higher states allow for more features and can increase performance, but may cause "
"additional graphical issues."));
INSERT(Settings,
vertex_input_dynamic_state,
tr("Vertex Input Dynamic State"),
INSERT(Settings, vertex_input_dynamic_state, tr("Vertex Input Dynamic State"),
tr("Enables vertex input dynamic state feature for better quality and performance."));
INSERT(Settings,
provoking_vertex,
tr("Provoking Vertex"),
INSERT(Settings, provoking_vertex, tr("Provoking Vertex"),
tr("Improves lighting and vertex handling in some games.\n"
"Only Vulkan 1.0+ devices support this extension."));
INSERT(Settings,
descriptor_indexing,
tr("Descriptor Indexing"),
INSERT(Settings, descriptor_indexing, tr("Descriptor Indexing"),
tr("Improves texture & buffer handling and the Maxwell translation layer.\n"
"Some Vulkan 1.1+ and all 1.2+ devices support this extension."));
INSERT(Settings,
sample_shading,
tr("Sample Shading"),
INSERT(
Settings, sample_shading, tr("Sample Shading"),
tr("Allows the fragment shader to execute per sample in a multi-sampled fragment "
"instead of once per fragment. Improves graphics quality at the cost of performance.\n"
"Higher values improve quality but degrade performance."));
@ -395,32 +307,22 @@ std::unique_ptr<TranslationMap> InitializeTranslations(QObject* parent)
// Renderer (Debug)
// System
INSERT(Settings,
rng_seed,
tr("RNG Seed"),
INSERT(Settings, rng_seed, tr("RNG Seed"),
tr("Controls the seed of the random number generator.\nMainly used for speedrunning."));
INSERT(Settings, rng_seed_enabled, QString(), QString());
INSERT(Settings, device_name, tr("Device Name"), tr("The name of the console."));
INSERT(Settings,
custom_rtc,
tr("Custom RTC Date:"),
INSERT(Settings, custom_rtc, tr("Custom RTC Date:"),
tr("This option allows to change the clock of the console.\n"
"Can be used to manipulate time in games."));
INSERT(Settings, custom_rtc_enabled, QString(), QString());
INSERT(Settings,
custom_rtc_offset,
QStringLiteral(" "),
INSERT(Settings, custom_rtc_offset, QStringLiteral(" "),
tr("The number of seconds from the current unix time"));
INSERT(Settings,
language_index,
tr("Language:"),
INSERT(Settings, language_index, tr("Language:"),
tr("This option can be overridden when region setting is auto-select"));
INSERT(Settings, region_index, tr("Region:"), tr("The region of the console."));
INSERT(Settings, time_zone_index, tr("Time Zone:"), tr("The time zone of the console."));
INSERT(Settings, sound_index, tr("Sound Output Mode:"), QString());
INSERT(Settings,
use_docked_mode,
tr("Console Mode:"),
INSERT(Settings, use_docked_mode, tr("Console Mode:"),
tr("Selects if the console is in Docked or Handheld mode.\nGames will change "
"their resolution, details and supported controllers and depending on this setting.\n"
"Setting to Handheld can help improve performance for low end systems."));
@ -444,31 +346,19 @@ std::unique_ptr<TranslationMap> InitializeTranslations(QObject* parent)
// Ui
// Ui General
INSERT(UISettings,
select_user_on_boot,
tr("Prompt for user profile on boot"),
INSERT(UISettings, select_user_on_boot, tr("Prompt for user profile on boot"),
tr("Useful if multiple people use the same PC."));
INSERT(UISettings,
pause_when_in_background,
tr("Pause when not in focus"),
INSERT(UISettings, pause_when_in_background, tr("Pause when not in focus"),
tr("Pauses emulation when focusing on other windows."));
INSERT(UISettings,
confirm_before_stopping,
tr("Confirm before stopping emulation"),
INSERT(UISettings, confirm_before_stopping, tr("Confirm before stopping emulation"),
tr("Overrides prompts asking to confirm stopping the emulation.\nEnabling "
"it bypasses such prompts and directly exits the emulation."));
INSERT(UISettings,
hide_mouse,
tr("Hide mouse on inactivity"),
INSERT(UISettings, hide_mouse, tr("Hide mouse on inactivity"),
tr("Hides the mouse after 2.5s of inactivity."));
INSERT(UISettings,
controller_applet_disabled,
tr("Disable controller applet"),
INSERT(UISettings, controller_applet_disabled, tr("Disable controller applet"),
tr("Forcibly disables the use of the controller applet in emulated programs.\n"
"When a program attempts to open the controller applet, it is immediately closed."));
INSERT(UISettings,
check_for_updates,
tr("Check for updates"),
INSERT(UISettings, check_for_updates, tr("Check for updates"),
tr("Whether or not to check for updates upon startup."));
// Linux
@ -489,9 +379,9 @@ std::unique_ptr<TranslationMap> InitializeTranslations(QObject* parent)
return translations;
}
std::unique_ptr<ComboboxTranslationMap> ComboboxEnumeration(QObject* parent)
{
std::unique_ptr<ComboboxTranslationMap> translations = std::make_unique<ComboboxTranslationMap>();
std::unique_ptr<ComboboxTranslationMap> ComboboxEnumeration(QObject* parent) {
std::unique_ptr<ComboboxTranslationMap> translations =
std::make_unique<ComboboxTranslationMap>();
const auto& tr = [&](const char* text, const char* context = "") {
return parent->tr(text, context);
};
@ -537,15 +427,15 @@ std::unique_ptr<ComboboxTranslationMap> ComboboxEnumeration(QObject* parent)
PAIR(VramUsageMode, Conservative, tr("Conservative")),
PAIR(VramUsageMode, Aggressive, tr("Aggressive")),
}});
translations->insert({Settings::EnumMetadata<Settings::RendererBackend>::Index(), {
PAIR(RendererBackend, Vulkan, tr("Vulkan")),
translations->insert(
{Settings::EnumMetadata<Settings::RendererBackend>::Index(),
{PAIR(RendererBackend, Vulkan, tr("Vulkan")),
#ifdef HAS_OPENGL
PAIR(RendererBackend, OpenGL_GLSL, tr("OpenGL GLSL")),
PAIR(RendererBackend, OpenGL_GLASM, tr("OpenGL GLASM (Assembly Shaders, NVIDIA Only)")),
PAIR(RendererBackend, OpenGL_SPIRV, tr("OpenGL SPIR-V (Experimental, AMD/Mesa Only)")),
#endif
PAIR(RendererBackend, Null, tr("Null"))
}});
PAIR(RendererBackend, Null, tr("Null"))}});
translations->insert({Settings::EnumMetadata<Settings::GpuAccuracy>::Index(),
{
PAIR(GpuAccuracy, Low, tr("Fast")),

View file

@ -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: Copyright 2024 Torzu Emulator Project
@ -13,8 +13,8 @@
#include <memory>
#include <utility>
#include <vector>
#include <QString>
#include <QObject>
#include <QString>
#include "common/common_types.h"
#include "common/settings_enums.h"
@ -23,7 +23,7 @@ using TranslationMap = std::map<u32, std::pair<QString, QString>>;
using ComboboxTranslations = std::vector<std::pair<u32, QString>>;
using ComboboxTranslationMap = std::map<u32, ComboboxTranslations>;
std::unique_ptr<TranslationMap> InitializeTranslations(QObject *parent);
std::unique_ptr<TranslationMap> InitializeTranslations(QObject* parent);
std::unique_ptr<ComboboxTranslationMap> ComboboxEnumeration(QObject* parent);
@ -39,15 +39,15 @@ static const std::map<Settings::ScalingFilter, QString> scaling_filter_texts_map
{Settings::ScalingFilter::Bilinear,
QStringLiteral(QT_TRANSLATE_NOOP("MainWindow", "Bilinear"))},
{Settings::ScalingFilter::Bicubic, QStringLiteral(QT_TRANSLATE_NOOP("MainWindow", "Bicubic"))},
{Settings::ScalingFilter::ZeroTangent, QStringLiteral(QT_TRANSLATE_NOOP("MainWindow", "Zero-Tangent"))},
{Settings::ScalingFilter::ZeroTangent,
QStringLiteral(QT_TRANSLATE_NOOP("MainWindow", "Zero-Tangent"))},
{Settings::ScalingFilter::BSpline, QStringLiteral(QT_TRANSLATE_NOOP("MainWindow", "B-Spline"))},
{Settings::ScalingFilter::Mitchell, QStringLiteral(QT_TRANSLATE_NOOP("MainWindow", "Mitchell"))},
{Settings::ScalingFilter::Spline1,
QStringLiteral(QT_TRANSLATE_NOOP("MainWindow", "Spline-1"))},
{Settings::ScalingFilter::Mitchell,
QStringLiteral(QT_TRANSLATE_NOOP("MainWindow", "Mitchell"))},
{Settings::ScalingFilter::Spline1, QStringLiteral(QT_TRANSLATE_NOOP("MainWindow", "Spline-1"))},
{Settings::ScalingFilter::Gaussian,
QStringLiteral(QT_TRANSLATE_NOOP("MainWindow", "Gaussian"))},
{Settings::ScalingFilter::Lanczos,
QStringLiteral(QT_TRANSLATE_NOOP("MainWindow", "Lanczos"))},
{Settings::ScalingFilter::Lanczos, QStringLiteral(QT_TRANSLATE_NOOP("MainWindow", "Lanczos"))},
{Settings::ScalingFilter::ScaleForce,
QStringLiteral(QT_TRANSLATE_NOOP("MainWindow", "ScaleForce"))},
{Settings::ScalingFilter::Fsr, QStringLiteral(QT_TRANSLATE_NOOP("MainWindow", "FSR"))},
@ -68,9 +68,12 @@ static const std::map<Settings::GpuAccuracy, QString> gpu_accuracy_texts_map = {
static const std::map<Settings::RendererBackend, QString> renderer_backend_texts_map = {
{Settings::RendererBackend::Vulkan, QStringLiteral(QT_TRANSLATE_NOOP("MainWindow", "Vulkan"))},
{Settings::RendererBackend::OpenGL_GLSL, QStringLiteral(QT_TRANSLATE_NOOP("MainWindow", "OpenGL GLSL"))},
{Settings::RendererBackend::OpenGL_SPIRV, QStringLiteral(QT_TRANSLATE_NOOP("MainWindow", "OpenGL SPIRV"))},
{Settings::RendererBackend::OpenGL_GLASM, QStringLiteral(QT_TRANSLATE_NOOP("MainWindow", "OpenGL GLASM"))},
{Settings::RendererBackend::OpenGL_GLSL,
QStringLiteral(QT_TRANSLATE_NOOP("MainWindow", "OpenGL GLSL"))},
{Settings::RendererBackend::OpenGL_SPIRV,
QStringLiteral(QT_TRANSLATE_NOOP("MainWindow", "OpenGL SPIRV"))},
{Settings::RendererBackend::OpenGL_GLASM,
QStringLiteral(QT_TRANSLATE_NOOP("MainWindow", "OpenGL GLASM"))},
{Settings::RendererBackend::Null, QStringLiteral(QT_TRANSLATE_NOOP("MainWindow", "Null"))},
};

View file

@ -152,7 +152,8 @@ struct Values {
"enable_gamemode", Category::UiGeneral};
#ifdef __unix__
SwitchableSetting<bool> gui_force_x11{linkage, false, "gui_force_x11", Category::UiGeneral};
Setting<bool> gui_hide_backend_warning{linkage, false, "gui_hide_backend_warning", Category::UiGeneral};
Setting<bool> gui_hide_backend_warning{linkage, false, "gui_hide_backend_warning",
Category::UiGeneral};
#endif
// Discord RPC
@ -210,7 +211,8 @@ struct Values {
Setting<u32> folder_icon_size{linkage, 48, "folder_icon_size", Category::UiGameList};
Setting<u8> row_1_text_id{linkage, 3, "row_1_text_id", Category::UiGameList};
Setting<u8> row_2_text_id{linkage, 2, "row_2_text_id", Category::UiGameList};
Setting<Settings::GameListMode> game_list_mode{linkage, Settings::GameListMode::TreeView, "game_list_mode", Category::UiGameList};
Setting<Settings::GameListMode> game_list_mode{linkage, Settings::GameListMode::TreeView,
"game_list_mode", Category::UiGameList};
Setting<bool> show_game_name{linkage, true, "show_game_name", Category::UiGameList};
std::atomic_bool is_game_list_reload_pending{false};

View file

@ -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: 2018 Citra Emulator Project
@ -70,7 +70,9 @@ std::string DiscordImpl::GetGameString(const std::string& title) {
}
static constexpr char DEFAULT_DISCORD_TEXT[] = "Eden is an emulator for the Nintendo Switch";
static constexpr char DEFAULT_DISCORD_IMAGE[] = "https://git.eden-emu.dev/eden-emu/eden/raw/branch/master/dist/qt_themes/default/icons/256x256/eden.png";
static constexpr char DEFAULT_DISCORD_IMAGE[] =
"https://git.eden-emu.dev/eden-emu/eden/raw/branch/master/dist/qt_themes/default/icons/256x256/"
"eden.png";
void DiscordImpl::UpdateGameStatus(bool use_default) {
const std::string url = use_default ? std::string{DEFAULT_DISCORD_IMAGE} : game_url;
@ -120,7 +122,9 @@ void DiscordImpl::Update() {
return;
}
s64 start_time = std::chrono::duration_cast<std::chrono::seconds>(std::chrono::system_clock::now().time_since_epoch()).count();
s64 start_time = std::chrono::duration_cast<std::chrono::seconds>(
std::chrono::system_clock::now().time_since_epoch())
.count();
DiscordRichPresence presence{};
presence.largeImageKey = DEFAULT_DISCORD_IMAGE;
presence.largeImageText = DEFAULT_DISCORD_TEXT;

View file

@ -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: Copyright 2023 yuzu Emulator Project
@ -9,9 +9,9 @@
#ifdef __unix__
#include <gamemode_client.h>
#endif
#include "qt_common/gamemode.h"
#include "common/logging/log.h"
#include "qt_common/config/uisettings.h"
#include "qt_common/gamemode.h"
namespace Common::FeralGamemode {
@ -49,4 +49,4 @@ void Stop() noexcept {
}
}
} // namespace Common::Linux
} // namespace Common::FeralGamemode

View file

@ -1,16 +1,17 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#include "gui_settings.h"
#include "common/fs/fs.h"
#include "common/fs/path_util.h"
#include "gui_settings.h"
namespace FS = Common::FS;
namespace GraphicsBackend {
QString GuiConfigPath() {
return QString::fromStdString(FS::PathToUTF8String(FS::GetEdenPath(FS::EdenPath::ConfigDir) / "gui_config.ini"));
return QString::fromStdString(
FS::PathToUTF8String(FS::GetEdenPath(FS::EdenPath::ConfigDir) / "gui_config.ini"));
}
void SetForceX11(bool state) {

View file

@ -1,21 +1,16 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#include "qt_common.h"
#include "common/fs/fs.h"
#include "common/fs/ryujinx_compat.h"
#include "qt_common.h"
#include <QGuiApplication>
#include <QStringLiteral>
#include "common/logging/log.h"
#include "core/frontend/emu_window.h"
#include "qt_common/abstract/frontend.h"
#include "qt_common/qt_string_lookup.h"
#include <QFile>
#include <QMessageBox>
#include <JlCompress.h>
#if !defined(WIN32) && !defined(__APPLE__)
@ -27,18 +22,13 @@
namespace QtCommon {
#ifdef YUZU_QT_WIDGETS
QWidget* rootObject = nullptr;
#else
QObject* rootObject = nullptr;
#endif
std::unique_ptr<Core::System> system = nullptr;
std::shared_ptr<FileSys::RealVfsFilesystem> vfs = nullptr;
std::unique_ptr<FileSys::ManualContentProvider> provider = nullptr;
Core::Frontend::WindowSystemType GetWindowSystemType()
{
Core::Frontend::WindowSystemType GetWindowSystemType() {
// Determine WSI type based on Qt platform.
QString platform_name = QGuiApplication::platformName();
if (platform_name == QStringLiteral("windows"))
@ -60,8 +50,7 @@ Core::Frontend::WindowSystemType GetWindowSystemType()
return Core::Frontend::WindowSystemType::Windows;
} // namespace Core::Frontend::WindowSystemType
Core::Frontend::EmuWindow::WindowSystemInfo GetWindowSystemInfo(QWindow* window)
{
Core::Frontend::EmuWindow::WindowSystemInfo GetWindowSystemInfo(QWindow* window) {
Core::Frontend::EmuWindow::WindowSystemInfo wsi;
wsi.type = GetWindowSystemType();
@ -69,8 +58,8 @@ Core::Frontend::EmuWindow::WindowSystemInfo GetWindowSystemInfo(QWindow* window)
// Our Win32 Qt external doesn't have the private API.
wsi.render_surface = reinterpret_cast<void*>(window->winId());
#elif defined(__APPLE__)
id layer = reinterpret_cast<id (*) (id, SEL)>(
objc_msgSend)(reinterpret_cast<id>(window->winId()), sel_registerName("layer"));
id layer = reinterpret_cast<id (*)(id, SEL)>(objc_msgSend)(
reinterpret_cast<id>(window->winId()), sel_registerName("layer"));
// In Qt 6, the layer of the NSView might be a QContainerLayer.
// MoltenVK needs a CAMetalLayer. We search for it in sublayers.
@ -78,15 +67,20 @@ Core::Frontend::EmuWindow::WindowSystemInfo GetWindowSystemInfo(QWindow* window)
id metal_layer = nullptr;
if (layer) {
if (reinterpret_cast<bool (*) (id, SEL, Class)>(objc_msgSend)(layer, sel_registerName("isKindOfClass:"), metal_layer_class)) {
if (reinterpret_cast<bool (*)(id, SEL, Class)>(objc_msgSend)(
layer, sel_registerName("isKindOfClass:"), metal_layer_class)) {
metal_layer = layer;
} else {
id sublayers = reinterpret_cast<id (*) (id, SEL)>(objc_msgSend)(layer, sel_registerName("sublayers"));
id sublayers = reinterpret_cast<id (*)(id, SEL)>(objc_msgSend)(
layer, sel_registerName("sublayers"));
if (sublayers) {
unsigned long count = reinterpret_cast<unsigned long (*) (id, SEL)>(objc_msgSend)(sublayers, sel_registerName("count"));
unsigned long count = reinterpret_cast<unsigned long (*)(id, SEL)>(objc_msgSend)(
sublayers, sel_registerName("count"));
for (unsigned long i = 0; i < count; ++i) {
id sublayer = reinterpret_cast<id (*) (id, SEL, unsigned long)>(objc_msgSend)(sublayers, sel_registerName("objectAtIndex:"), i);
if (reinterpret_cast<bool (*) (id, SEL, Class)>(objc_msgSend)(sublayer, sel_registerName("isKindOfClass:"), metal_layer_class)) {
id sublayer = reinterpret_cast<id (*)(id, SEL, unsigned long)>(objc_msgSend)(
sublayers, sel_registerName("objectAtIndex:"), i);
if (reinterpret_cast<bool (*)(id, SEL, Class)>(objc_msgSend)(
sublayer, sel_registerName("isKindOfClass:"), metal_layer_class)) {
metal_layer = sublayer;
break;
}
@ -108,30 +102,22 @@ Core::Frontend::EmuWindow::WindowSystemInfo GetWindowSystemInfo(QWindow* window)
return wsi;
}
const QString tr(const char* str)
{
const QString tr(const char* str) {
return QGuiApplication::tr(str);
}
const QString tr(const std::string& str)
{
const QString tr(const std::string& str) {
return QGuiApplication::tr(str.c_str());
}
#ifdef YUZU_QT_WIDGETS
void Init(QWidget* root)
#else
void Init(QObject* root)
#endif
{
void Init(QWidget* root) {
system = std::make_unique<Core::System>();
rootObject = root;
vfs = std::make_unique<FileSys::RealVfsFilesystem>();
provider = std::make_unique<FileSys::ManualContentProvider>();
}
std::filesystem::path GetEdenCommand()
{
std::filesystem::path GetEdenCommand() {
std::filesystem::path command;
// TODO: flatpak?

View file

@ -1,24 +1,20 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#ifndef QT_COMMON_H
#define QT_COMMON_H
#include <memory>
#include <QWindow>
#include <core/frontend/emu_window.h>
#include "core/core.h"
#include "core/file_sys/registered_cache.h"
#include <core/frontend/emu_window.h>
#include <memory>
#include <core/file_sys/vfs/vfs_real.h>
namespace QtCommon {
#ifdef YUZU_QT_WIDGETS
extern QWidget *rootObject;
#else
extern QObject *rootObject;
#endif
extern QWidget* rootObject;
extern std::unique_ptr<Core::System> system;
extern std::shared_ptr<FileSys::RealVfsFilesystem> vfs;
@ -28,16 +24,12 @@ typedef std::function<bool(std::size_t, std::size_t)> QtProgressCallback;
Core::Frontend::WindowSystemType GetWindowSystemType();
Core::Frontend::EmuWindow::WindowSystemInfo GetWindowSystemInfo(QWindow *window);
Core::Frontend::EmuWindow::WindowSystemInfo GetWindowSystemInfo(QWindow* window);
#ifdef YUZU_QT_WIDGETS
void Init(QWidget *root);
#else
void Init(QObject *root);
#endif
void Init(QWidget* root);
const QString tr(const char *str);
const QString tr(const std::string &str);
const QString tr(const char* str);
const QString tr(const std::string& str);
std::filesystem::path GetEdenCommand();
} // namespace QtCommon

View file

@ -11,8 +11,9 @@
/// Small helper to look up enums.
/// res = the result code
/// base = the base matching value in the StringKey table
#define LOOKUP_ENUM(res, base) QtCommon::StringLookup::Lookup( \
QtCommon::StringLookup::StringKey((int) res + (int) QtCommon::StringLookup::base))
#define LOOKUP_ENUM(res, base) \
QtCommon::StringLookup::Lookup( \
QtCommon::StringLookup::StringKey((int)res + (int)QtCommon::StringLookup::base))
namespace QtCommon::StringLookup {
@ -111,15 +112,13 @@ static const constexpr frozen::map<StringKey, frozen::string, 29> strings = {
QT_TR_NOOP("Would you like to migrate your data for use in Eden?\n"
"Select the corresponding button to migrate data from that emulator.\n"
"This may take a while.")},
{MigrationTooltipClearShader,
QT_TR_NOOP("Clearing shader cache is recommended for all "
{MigrationTooltipClearShader, QT_TR_NOOP("Clearing shader cache is recommended for all "
"users.\nDo not uncheck unless you know what "
"you're doing.")},
{MigrationTooltipKeepOld,
QT_TR_NOOP("Keeps the old data directory. This is recommended if you aren't\n"
"space-constrained and want to keep separate data for the old emulator.")},
{MigrationTooltipClearOld,
QT_TR_NOOP("Deletes the old data directory.\nThis is recommended on "
{MigrationTooltipClearOld, QT_TR_NOOP("Deletes the old data directory.\nThis is recommended on "
"devices with space constraints.")},
{MigrationTooltipLinkOld,
QT_TR_NOOP("Creates a filesystem link between the old directory and Eden directory.\n"
@ -135,8 +134,7 @@ static const constexpr frozen::map<StringKey, frozen::string, 29> strings = {
{RyujinxNoSaveId, QT_TR_NOOP("Title %1 not found in Ryujinx title database.")},
};
static inline const QString Lookup(StringKey key)
{
static inline const QString Lookup(StringKey key) {
return QObject::tr(strings.at(key).data());
}

View file

@ -1,11 +1,9 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#ifndef QT_APPLET_UTIL_H
#define QT_APPLET_UTIL_H
// TODO
namespace QtCommon::Applets {
}
namespace QtCommon::Applets {}
#endif // QT_APPLET_UTIL_H

View file

@ -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
#include "compress.h"
@ -10,11 +10,8 @@
/** This is a modified version of JlCompress **/
namespace QtCommon::Compress {
bool compressDir(QString fileCompressed,
QString dir,
const Options &options,
QtCommon::QtProgressCallback callback)
{
bool compressDir(QString fileCompressed, QString dir, const Options& options,
QtCommon::QtProgressCallback callback) {
// Create zip
QuaZip zip(fileCompressed);
QDir().mkpath(QFileInfo(fileCompressed).absolutePath());
@ -26,8 +23,7 @@ bool compressDir(QString fileCompressed,
// See how big the overall fs structure is
// good approx. of total progress
// TODO(crueter): QDirListing impl... or fs::recursive_dir_iterator
QDirIterator iter(dir,
QDir::NoDotAndDotDot | QDir::Hidden | QDir::Files,
QDirIterator iter(dir, QDir::NoDotAndDotDot | QDir::Hidden | QDir::Files,
QDirIterator::Subdirectories);
std::size_t total = 0;
@ -54,14 +50,8 @@ bool compressDir(QString fileCompressed,
return true;
}
bool compressSubDir(QuaZip *zip,
QString dir,
QString origDir,
const Options &options,
std::size_t total,
std::size_t &progress,
QtProgressCallback callback)
{
bool compressSubDir(QuaZip* zip, QString dir, QString origDir, const Options& options,
std::size_t total, std::size_t& progress, QtProgressCallback callback) {
// zip: object where to add the file
// dir: current real directory
// origDir: original real directory
@ -69,22 +59,20 @@ bool compressSubDir(QuaZip *zip,
if (!zip)
return false;
if (zip->getMode() != QuaZip::mdCreate && zip->getMode() != QuaZip::mdAppend
&& zip->getMode() != QuaZip::mdAdd)
if (zip->getMode() != QuaZip::mdCreate && zip->getMode() != QuaZip::mdAppend &&
zip->getMode() != QuaZip::mdAdd)
return false;
QDir directory(dir);
if (!directory.exists())
return false;
QDir origDirectory(origDir);
if (dir != origDir) {
QuaZipFile dirZipFile(zip);
std::unique_ptr<QuaZipNewInfo> qzni;
qzni = std::make_unique<QuaZipNewInfo>(origDirectory.relativeFilePath(dir)
+ QLatin1String("/"),
dir);
qzni = std::make_unique<QuaZipNewInfo>(
origDirectory.relativeFilePath(dir) + QLatin1String("/"), dir);
if (!dirZipFile.open(QIODevice::WriteOnly, *qzni, nullptr, 0, 0)) {
return false;
}
@ -92,18 +80,18 @@ bool compressSubDir(QuaZip *zip,
}
// For each subfolder
QFileInfoList subfiles = directory.entryInfoList(QDir::AllDirs | QDir::NoDotAndDotDot
| QDir::Hidden | QDir::Dirs);
for (const auto &file : std::as_const(subfiles)) {
if (!compressSubDir(
zip, file.absoluteFilePath(), origDir, options, total, progress, callback)) {
QFileInfoList subfiles =
directory.entryInfoList(QDir::AllDirs | QDir::NoDotAndDotDot | QDir::Hidden | QDir::Dirs);
for (const auto& file : std::as_const(subfiles)) {
if (!compressSubDir(zip, file.absoluteFilePath(), origDir, options, total, progress,
callback)) {
return false;
}
}
// For each file in directory
QFileInfoList files = directory.entryInfoList(QDir::Hidden | QDir::Files);
for (const auto &file : std::as_const(files)) {
for (const auto& file : std::as_const(files)) {
// If it's not a file or it's the compressed file being created
if (!file.isFile() || file.absoluteFilePath() == zip->getZipName())
continue;
@ -112,7 +100,8 @@ bool compressSubDir(QuaZip *zip,
QString filename = origDirectory.relativeFilePath(file.absoluteFilePath());
// Compress the file
if (!compressFile(zip, file.absoluteFilePath(), filename, options, total, progress, callback)) {
if (!compressFile(zip, file.absoluteFilePath(), filename, options, total, progress,
callback)) {
return false;
}
}
@ -120,40 +109,26 @@ bool compressSubDir(QuaZip *zip,
return true;
}
bool compressFile(QuaZip *zip,
QString fileName,
QString fileDest,
const Options &options,
std::size_t total,
std::size_t &progress,
QtCommon::QtProgressCallback callback)
{
bool compressFile(QuaZip* zip, QString fileName, QString fileDest, const Options& options,
std::size_t total, std::size_t& progress, QtCommon::QtProgressCallback callback) {
// zip: object where to add the file
// fileName: real file name
// fileDest: file name inside the zip object
if (!zip)
return false;
if (zip->getMode() != QuaZip::mdCreate && zip->getMode() != QuaZip::mdAppend
&& zip->getMode() != QuaZip::mdAdd)
if (zip->getMode() != QuaZip::mdCreate && zip->getMode() != QuaZip::mdAppend &&
zip->getMode() != QuaZip::mdAdd)
return false;
QuaZipFile outFile(zip);
if (options.getDateTime().isNull()) {
if (!outFile.open(QIODevice::WriteOnly,
QuaZipNewInfo(fileDest, fileName),
nullptr,
0,
options.getCompressionMethod(),
options.getCompressionLevel()))
if (!outFile.open(QIODevice::WriteOnly, QuaZipNewInfo(fileDest, fileName), nullptr, 0,
options.getCompressionMethod(), options.getCompressionLevel()))
return false;
} else {
if (!outFile.open(QIODevice::WriteOnly,
QuaZipNewInfo(fileDest, fileName),
nullptr,
0,
options.getCompressionMethod(),
options.getCompressionLevel()))
if (!outFile.open(QIODevice::WriteOnly, QuaZipNewInfo(fileDest, fileName), nullptr, 0,
options.getCompressionMethod(), options.getCompressionLevel()))
return false;
}
@ -171,7 +146,8 @@ bool compressFile(QuaZip *zip,
if (!inFile.open(QIODevice::ReadOnly)) {
return false;
}
if (!copyData(inFile, outFile, total, progress, callback) || outFile.getZipError() != UNZ_OK) {
if (!copyData(inFile, outFile, total, progress, callback) ||
outFile.getZipError() != UNZ_OK) {
return false;
}
inFile.close();
@ -181,12 +157,8 @@ bool compressFile(QuaZip *zip,
return outFile.getZipError() == UNZ_OK;
}
bool copyData(QIODevice &inFile,
QIODevice &outFile,
std::size_t total,
std::size_t &progress,
QtProgressCallback callback)
{
bool copyData(QIODevice& inFile, QIODevice& outFile, std::size_t total, std::size_t& progress,
QtProgressCallback callback) {
while (!inFile.atEnd()) {
char buf[4096];
qint64 readLen = inFile.read(buf, 4096);
@ -203,15 +175,13 @@ bool copyData(QIODevice &inFile,
return true;
}
QStringList extractDir(QString fileCompressed, QString dir, QtCommon::QtProgressCallback callback)
{
QStringList extractDir(QString fileCompressed, QString dir, QtCommon::QtProgressCallback callback) {
// Open zip
QuaZip zip(fileCompressed);
return extractDir(zip, dir, callback);
}
QStringList extractDir(QuaZip &zip, const QString &dir, QtCommon::QtProgressCallback callback)
{
QStringList extractDir(QuaZip& zip, const QString& dir, QtCommon::QtProgressCallback callback) {
if (!zip.open(QuaZip::mdUnzip)) {
return QStringList();
}
@ -226,7 +196,7 @@ QStringList extractDir(QuaZip &zip, const QString &dir, QtCommon::QtProgressCall
}
std::size_t total = 0;
for (const QuaZipFileInfo64 &info : zip.getFileInfoList64()) {
for (const QuaZipFileInfo64& info : zip.getFileInfoList64()) {
total += info.uncompressedSize;
}
@ -256,13 +226,8 @@ QStringList extractDir(QuaZip &zip, const QString &dir, QtCommon::QtProgressCall
return extracted;
}
bool extractFile(QuaZip *zip,
QString fileName,
QString fileDest,
std::size_t total,
std::size_t &progress,
QtCommon::QtProgressCallback callback)
{
bool extractFile(QuaZip* zip, QString fileName, QString fileDest, std::size_t total,
std::size_t& progress, QtCommon::QtProgressCallback callback) {
// zip: object where to add the file
// filename: real file name
// fileincompress: file name of the compressed file
@ -334,8 +299,7 @@ bool extractFile(QuaZip *zip,
return true;
}
bool removeFile(QStringList listFile)
{
bool removeFile(QStringList listFile) {
bool ret = true;
// For each file
for (int i = 0; i < listFile.count(); i++) {

View file

@ -1,13 +1,13 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#pragma once
#include <QDir>
#include <QString>
#include "qt_common/qt_common.h"
#include <quazip.h>
#include <zlib.h>
#include "qt_common/qt_common.h"
/** This is a modified version of JlCompress **/
namespace QtCommon::Compress {
@ -27,8 +27,7 @@ public:
* A higher value of level indicates a smaller size of the compressed file,
* although it also implies more time consumed during the compression process.
*/
enum CompressionStrategy
{
enum CompressionStrategy {
/// Storage without compression
Storage = 0x00, // Z_NO_COMPRESSION 0
/// The fastest compression speed
@ -41,23 +40,24 @@ public:
Better = 0x87,
/// The best compression ratio
Best = 0x89, // Z_BEST_COMPRESSION 9
/// The default compression strategy, according to the open function of quazipfile.h,
/// the value of method is Z_DEFLATED, and the value of level is Z_DEFAULT_COMPRESSION -1 (equals lvl 6)
/// The default compression strategy, according to the open function of
/// quazipfile.h, the value of method is Z_DEFLATED, and the value of level is
/// Z_DEFAULT_COMPRESSION -1 (equals lvl 6)
Default = 0xff
};
public:
explicit Options(const CompressionStrategy& strategy)
: m_compressionStrategy(strategy) {}
explicit Options(const CompressionStrategy& strategy) : m_compressionStrategy(strategy) {}
explicit Options(const QDateTime& dateTime = QDateTime(), const CompressionStrategy& strategy = Default)
explicit Options(const QDateTime& dateTime = QDateTime(),
const CompressionStrategy& strategy = Default)
: m_dateTime(dateTime), m_compressionStrategy(strategy) {}
QDateTime getDateTime() const {
return m_dateTime;
}
void setDateTime(const QDateTime &dateTime) {
void setDateTime(const QDateTime& dateTime) {
m_dateTime = dateTime;
}
@ -70,10 +70,11 @@ public:
}
int getCompressionLevel() const {
return m_compressionStrategy != Default ? m_compressionStrategy & 0x0f : Z_DEFAULT_COMPRESSION;
return m_compressionStrategy != Default ? m_compressionStrategy & 0x0f
: Z_DEFAULT_COMPRESSION;
}
void setCompressionStrategy(const CompressionStrategy &strategy) {
void setCompressionStrategy(const CompressionStrategy& strategy) {
m_compressionStrategy = strategy;
}
@ -89,34 +90,21 @@ private:
* @param fileCompressed Destination file
* @param dir The directory to compress
* @param options Compression level, etc
* @param callback Callback that takes in two std::size_t (total, progress) and returns false if the current operation should be cancelled.
* @param callback Callback that takes in two std::size_t (total, progress) and returns false
* if the current operation should be cancelled.
*/
bool compressDir(QString fileCompressed,
QString dir,
const Options& options = Options(),
bool compressDir(QString fileCompressed, QString dir, const Options& options = Options(),
QtCommon::QtProgressCallback callback = {});
// Internal //
bool compressSubDir(QuaZip *zip,
QString dir,
QString origDir,
const Options &options,
std::size_t total,
std::size_t &progress,
bool compressSubDir(QuaZip* zip, QString dir, QString origDir, const Options& options,
std::size_t total, std::size_t& progress,
QtCommon::QtProgressCallback callback);
bool compressFile(QuaZip *zip,
QString fileName,
QString fileDest,
const Options &options,
std::size_t total,
std::size_t &progress,
QtCommon::QtProgressCallback callback);
bool compressFile(QuaZip* zip, QString fileName, QString fileDest, const Options& options,
std::size_t total, std::size_t& progress, QtCommon::QtProgressCallback callback);
bool copyData(QIODevice &inFile,
QIODevice &outFile,
std::size_t total,
std::size_t &progress,
bool copyData(QIODevice& inFile, QIODevice& outFile, std::size_t total, std::size_t& progress,
QtCommon::QtProgressCallback callback);
// Extract //
@ -125,20 +113,18 @@ bool copyData(QIODevice &inFile,
* @brief Extract a zip file and report its progress.
* @param fileCompressed Compressed file
* @param dir The directory to push the results to
* @param callback Callback that takes in two std::size_t (total, progress) and returns false if the current operation should be cancelled.
* @param callback Callback that takes in two std::size_t (total, progress) and returns false
* if the current operation should be cancelled.
*/
QStringList extractDir(QString fileCompressed, QString dir, QtCommon::QtProgressCallback callback = {});
QStringList extractDir(QString fileCompressed, QString dir,
QtCommon::QtProgressCallback callback = {});
// Internal //
QStringList extractDir(QuaZip &zip, const QString &dir, QtCommon::QtProgressCallback callback);
QStringList extractDir(QuaZip& zip, const QString& dir, QtCommon::QtProgressCallback callback);
bool extractFile(QuaZip *zip,
QString fileName,
QString fileDest,
std::size_t total,
std::size_t &progress,
QtCommon::QtProgressCallback callback);
bool extractFile(QuaZip* zip, QString fileName, QString fileDest, std::size_t total,
std::size_t& progress, QtCommon::QtProgressCallback callback);
bool removeFile(QStringList listFile);
}
} // namespace QtCommon::Compress

View file

@ -12,63 +12,54 @@
#include "compress.h"
#include "qt_common/abstract/frontend.h"
#include "qt_common/abstract/qt_progress_dialog.h"
#include "qt_common/abstract/progress.h"
#include "qt_common/qt_common.h"
#include <JlCompress.h>
#include <QFuture>
#include <QFutureWatcher>
#include <QtConcurrentRun>
#include <JlCompress.h>
namespace QtCommon::Content {
bool CheckGameFirmware(u64 program_id, QObject* parent)
{
if (FirmwareManager::GameRequiresFirmware(program_id)
&& !FirmwareManager::CheckFirmwarePresence(*system)) {
auto result = QtCommon::Frontend::ShowMessage(
QMessageBox::Warning,
bool CheckGameFirmware(u64 program_id) {
if (FirmwareManager::GameRequiresFirmware(program_id) &&
!FirmwareManager::CheckFirmwarePresence(*system)) {
auto result = QtCommon::Frontend::Warning(
tr("Game Requires Firmware"),
tr("The game you are trying to launch requires firmware to boot or to get past the "
"opening menu. Please <a href='https://yuzu-mirror.github.io/help/quickstart'>"
"dump and install firmware</a>, or press \"OK\" to launch anyways."),
QMessageBox::Ok | QMessageBox::Cancel,
parent);
QtCommon::Frontend::Ok | QtCommon::Frontend::Cancel);
return result == QMessageBox::Ok;
return result == QtCommon::Frontend::Ok;
}
return true;
}
void InstallFirmware(const QString& location, bool recursive)
{
QtCommon::Frontend::QtProgressDialog progress(tr("Installing Firmware..."),
tr("Cancel"),
0,
100,
rootObject);
progress.setWindowModality(Qt::WindowModal);
progress.setMinimumDuration(100);
progress.setAutoClose(false);
progress.setAutoReset(false);
progress.show();
void InstallFirmware(const QString& location, bool recursive) {
// Initialize a progress dialog.
auto progress =
QtCommon::Frontend::newProgressDialog(tr("Installing Firmware..."), tr("Cancel"), 0, 100);
progress->show();
QGuiApplication::processEvents();
// Declare progress callback.
auto callback = [&](size_t total_size, size_t processed_size) {
progress.setValue(static_cast<int>((processed_size * 100) / total_size));
return progress.wasCanceled();
QGuiApplication::processEvents();
progress->setValue(static_cast<int>((processed_size * 100) / total_size));
return progress->wasCanceled();
};
QString failedTitle = tr("Firmware Install Failed");
QString successTitle = tr("Firmware Install Succeeded");
QMessageBox::Icon icon;
QtCommon::Frontend::Icon icon;
FirmwareInstallResult result;
const auto ShowMessage = [&]() {
QtCommon::Frontend::ShowMessage(icon,
failedTitle,
GetFirmwareInstallResultString(result));
QtCommon::Frontend::ShowMessage(icon, failedTitle, GetFirmwareInstallResultString(result));
};
LOG_INFO(Frontend, "Installing firmware from {}", location.toStdString());
@ -93,28 +84,26 @@ void InstallFirmware(const QString& location, bool recursive)
callback(100, 10);
if (recursive) {
Common::FS::IterateDirEntriesRecursively(firmware_source_path,
dir_callback,
Common::FS::IterateDirEntriesRecursively(firmware_source_path, dir_callback,
Common::FS::DirEntryFilter::File);
} else {
Common::FS::IterateDirEntries(firmware_source_path,
dir_callback,
Common::FS::IterateDirEntries(firmware_source_path, dir_callback,
Common::FS::DirEntryFilter::File);
}
if (out.size() <= 0) {
result = FirmwareInstallResult::NoNCAs;
icon = QMessageBox::Warning;
icon = QtCommon::Frontend::Icon::Warning;
ShowMessage();
return;
}
// Locate and erase the content of nand/system/Content/registered/*.nca, if any.
auto sysnand_content_vdir = system->GetFileSystemController().GetSystemNANDContentDirectory();
if (sysnand_content_vdir->IsWritable()
&& !sysnand_content_vdir->CleanSubdirectoryRecursive("registered")) {
if (sysnand_content_vdir->IsWritable() &&
!sysnand_content_vdir->CleanSubdirectoryRecursive("registered")) {
result = FirmwareInstallResult::FailedDelete;
icon = QMessageBox::Critical;
icon = QtCommon::Frontend::Icon::Critical;
ShowMessage();
return;
}
@ -130,22 +119,20 @@ void InstallFirmware(const QString& location, bool recursive)
int i = 0;
for (const auto& firmware_src_path : out) {
i++;
auto firmware_src_vfile = vfs->OpenFile(firmware_src_path.generic_string(),
FileSys::OpenMode::Read);
auto firmware_dst_vfile = firmware_vdir->CreateFileRelative(
firmware_src_path.filename().string());
auto firmware_src_vfile =
vfs->OpenFile(firmware_src_path.generic_string(), FileSys::OpenMode::Read);
auto firmware_dst_vfile =
firmware_vdir->CreateFileRelative(firmware_src_path.filename().string());
if (!VfsRawCopy(firmware_src_vfile, firmware_dst_vfile)) {
LOG_ERROR(Frontend,
"Failed to copy firmware file {} to {} in registered folder!",
firmware_src_path.generic_string(),
firmware_src_path.filename().string());
LOG_ERROR(Frontend, "Failed to copy firmware file {} to {} in registered folder!",
firmware_src_path.generic_string(), firmware_src_path.filename().string());
success = false;
}
if (callback(100, 20 + static_cast<int>(((i) / static_cast<float>(out.size())) * 70.0))) {
result = FirmwareInstallResult::FailedCorrupted;
icon = QMessageBox::Warning;
icon = QtCommon::Frontend::Icon::Warning;
ShowMessage();
return;
}
@ -153,7 +140,7 @@ void InstallFirmware(const QString& location, bool recursive)
if (!success) {
result = FirmwareInstallResult::FailedCopy;
icon = QMessageBox::Critical;
icon = QtCommon::Frontend::Icon::Critical;
ShowMessage();
return;
}
@ -162,39 +149,37 @@ void InstallFirmware(const QString& location, bool recursive)
system->GetFileSystemController().CreateFactories(*vfs);
auto VerifyFirmwareCallback = [&](size_t total_size, size_t processed_size) {
progress.setValue(90 + static_cast<int>((processed_size * 10) / total_size));
return progress.wasCanceled();
QGuiApplication::processEvents();
progress->setValue(90 + static_cast<int>((processed_size * 10) / total_size));
return progress->wasCanceled();
};
auto results = ContentManager::VerifyInstalledContents(*QtCommon::system,
*QtCommon::provider,
VerifyFirmwareCallback,
true);
auto results = ContentManager::VerifyInstalledContents(*QtCommon::system, *QtCommon::provider,
VerifyFirmwareCallback, true);
if (results.size() > 0) {
const auto failed_names = QString::fromStdString(
fmt::format("{}", fmt::join(results, "\n")));
progress.close();
const auto failed_names =
QString::fromStdString(fmt::format("{}", fmt::join(results, "\n")));
progress->close();
QtCommon::Frontend::Critical(
tr("Firmware integrity verification failed!"),
tr("Verification failed for the following files:\n\n%1").arg(failed_names));
return;
}
progress.close();
progress->close();
QGuiApplication::processEvents();
const auto pair = FirmwareManager::GetFirmwareVersion(*system);
const auto firmware_data = pair.first;
const std::string display_version(firmware_data.display_version.data());
result = FirmwareInstallResult::Success;
QtCommon::Frontend::Information(successTitle,
GetFirmwareInstallResultString(result).arg(
QtCommon::Frontend::Information(successTitle, GetFirmwareInstallResultString(result).arg(
QString::fromStdString(display_version)));
}
QString UnzipFirmwareToTmp(const QString& location)
{
QString UnzipFirmwareToTmp(const QString& location) {
namespace fs = std::filesystem;
fs::path tmp{fs::temp_directory_path()};
@ -219,59 +204,47 @@ QString UnzipFirmwareToTmp(const QString& location)
}
// Content //
void VerifyGameContents(const std::string& game_path)
{
QtCommon::Frontend::QtProgressDialog progress(tr("Verifying integrity..."),
tr("Cancel"),
0,
100,
rootObject);
progress.setWindowModality(Qt::WindowModal);
progress.setMinimumDuration(100);
progress.setAutoClose(false);
progress.setAutoReset(false);
void VerifyGameContents(const std::string& game_path) {
auto progress =
QtCommon::Frontend::newProgressDialog(tr("Verifying integrity..."), tr("Cancel"), 0, 100);
progress->show();
QGuiApplication::processEvents();
const auto callback = [&](size_t total_size, size_t processed_size) {
progress.setValue(static_cast<int>((processed_size * 100) / total_size));
return progress.wasCanceled();
QGuiApplication::processEvents();
progress->setValue(static_cast<int>((processed_size * 100) / total_size));
return progress->wasCanceled();
};
const auto result = ContentManager::VerifyGameContents(*system, game_path, callback);
switch (result) {
case ContentManager::GameVerificationResult::Success:
QtCommon::Frontend::Information(rootObject,
tr("Integrity verification succeeded!"),
QtCommon::Frontend::Information(rootObject, tr("Integrity verification succeeded!"),
tr("The operation completed successfully."));
break;
case ContentManager::GameVerificationResult::Failed:
QtCommon::Frontend::Critical(rootObject,
tr("Integrity verification failed!"),
QtCommon::Frontend::Critical(rootObject, tr("Integrity verification failed!"),
tr("File contents may be corrupt or missing."));
break;
case ContentManager::GameVerificationResult::NotImplemented:
QtCommon::Frontend::Warning(
rootObject,
tr("Integrity verification couldn't be performed"),
rootObject, tr("Integrity verification couldn't be performed"),
tr("Firmware installation cancelled, firmware may be in a bad state or corrupted. "
"File contents could not be checked for validity."));
}
}
void InstallKeys()
{
const QString key_source_location
= QtCommon::Frontend::GetOpenFileName(tr("Select Dumped Keys Location"),
{},
QStringLiteral("Decryption Keys (*.keys)"),
{},
QtCommon::Frontend::Option::ReadOnly);
void InstallKeys() {
const QString key_source_location = QtCommon::Frontend::GetOpenFileName(
tr("Select Dumped Keys Location"), {}, QStringLiteral("Decryption Keys (*.keys)"), {});
if (key_source_location.isEmpty())
return;
FirmwareManager::KeyInstallResult result
= FirmwareManager::InstallKeys(key_source_location.toStdString(), "keys");
FirmwareManager::KeyInstallResult result =
FirmwareManager::InstallKeys(key_source_location.toStdString(), "keys");
system->GetFileSystemController().CreateFactories(*QtCommon::vfs);
@ -286,46 +259,42 @@ void InstallKeys()
}
}
void VerifyInstalledContents()
{
void VerifyInstalledContents() {
// Initialize a progress dialog.
QtCommon::Frontend::QtProgressDialog progress(tr("Verifying integrity..."),
tr("Cancel"),
0,
100,
rootObject);
progress.setWindowModality(Qt::WindowModal);
progress.setMinimumDuration(100);
progress.setAutoClose(false);
progress.setAutoReset(false);
auto progress =
QtCommon::Frontend::newProgressDialog(tr("Verifying integrity..."), tr("Cancel"), 0, 100);
progress->show();
QGuiApplication::processEvents();
// Declare progress callback.
auto QtProgressCallback = [&](size_t total_size, size_t processed_size) {
progress.setValue(static_cast<int>((processed_size * 100) / total_size));
return progress.wasCanceled();
QGuiApplication::processEvents();
progress->setValue(static_cast<int>((processed_size * 100) / total_size));
return progress->wasCanceled();
};
const std::vector<std::string> result
= ContentManager::VerifyInstalledContents(*QtCommon::system,
*QtCommon::provider,
QtProgressCallback);
progress.close();
const std::vector<std::string> result = ContentManager::VerifyInstalledContents(
*QtCommon::system, *QtCommon::provider, QtProgressCallback);
progress->close();
if (result.empty()) {
QtCommon::Frontend::Information(tr("Integrity verification succeeded!"),
tr("The operation completed successfully."));
} else {
const auto failed_names = QString::fromStdString(fmt::format("{}", fmt::join(result, "\n")));
const auto failed_names =
QString::fromStdString(fmt::format("{}", fmt::join(result, "\n")));
QtCommon::Frontend::Critical(
tr("Integrity verification failed!"),
tr("Verification failed for the following files:\n\n%1").arg(failed_names));
}
}
void FixProfiles()
{
void FixProfiles() {
// Reset user save files after config is initialized and migration is done.
// Doing it at init time causes profiles to read from the wrong place entirely if NAND dir is not default
// Doing it at init time causes profiles to read from the wrong place entirely if NAND dir is
// not default
// TODO: better solution
system->GetProfileManager().ResetUserSaveFile();
std::vector<std::string> orphaned = system->GetProfileManager().FindOrphanedProfiles();
@ -365,79 +334,66 @@ void FixProfiles()
"%2<br><br>"
"Click \"OK\" to open your save folder and fix up your profiles.<br>"
"Hint: copy the contents of the largest or last-modified folder elsewhere, "
"delete all orphaned profiles, and move your copied contents to the good profile.<br><br>"
"Still confused? See the <a href='https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/user/Orphaned.md'>help page</a>.<br>")
"delete all orphaned profiles, and move your copied contents to the good "
"profile.<br><br>"
"Still confused? See the <a "
"href='https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/user/"
"Orphaned.md'>help page</a>.<br>")
.arg(qorphaned, qgood));
QtCommon::Game::OpenSaveFolder();
}
void ClearDataDir(FrontendCommon::DataManager::DataDir dir, const std::string& user_id)
{
auto result = QtCommon::Frontend::Warning(tr("Really clear data?"),
tr("Important data may be lost!"),
QMessageBox::Yes | QMessageBox::No);
void ClearDataDir(FrontendCommon::DataManager::DataDir dir, const std::string& user_id) {
using namespace QtCommon::Frontend;
auto result = Warning(tr("Really clear data?"), tr("Important data may be lost!"), Yes | No);
if (result != QMessageBox::Yes)
if (result != Yes)
return;
result = QtCommon::Frontend::Warning(
tr("Are you REALLY sure?"),
result = Warning(tr("Are you REALLY sure?"),
tr("Once deleted, your data will NOT come back!\n"
"Only do this if you're 100% sure you want to delete this data."),
QMessageBox::Yes | QMessageBox::No);
Yes | No);
if (result != QMessageBox::Yes)
if (result != Yes)
return;
QtCommon::Frontend::QtProgressDialog dialog(tr("Clearing..."), QString(), 0, 0);
dialog.show();
auto dialog = newProgressDialog(tr("Clearing..."), QString(), 0, 0);
dialog->show();
FrontendCommon::DataManager::ClearDir(dir, user_id);
dialog.close();
dialog->close();
}
void ExportDataDir(FrontendCommon::DataManager::DataDir data_dir,
const std::string& user_id,
const QString& name,
std::function<void()> callback)
{
void ExportDataDir(FrontendCommon::DataManager::DataDir data_dir, const std::string& user_id,
const QString& name, std::function<void()> callback) {
using namespace QtCommon::Frontend;
const std::string dir = FrontendCommon::DataManager::GetDataDirString(data_dir, user_id);
const QString zip_dump_location = GetSaveFileName(tr("Select Export Location"),
tr("%1.zip").arg(name),
tr("Zipped Archives (*.zip)"));
const QString zip_dump_location = GetSaveFileName(
tr("Select Export Location"), tr("%1.zip").arg(name), tr("Zipped Archives (*.zip)"));
if (zip_dump_location.isEmpty())
return;
QtProgressDialog* progress = new QtProgressDialog(
tr("Exporting data. This may take a while..."), tr("Cancel"), 0, 100, rootObject);
auto progress = QtCommon::Frontend::newProgressDialogPtr(
tr("Exporting data. This may take a while..."), tr("Cancel"), 0, 100);
progress->setWindowTitle(tr("Exporting"));
progress->setWindowModality(Qt::WindowModal);
progress->setMinimumDuration(100);
progress->setAutoClose(false);
progress->setAutoReset(false);
progress->setTitle(tr("Exporting"));
progress->show();
QGuiApplication::processEvents();
auto progress_callback = [=](size_t total_size, size_t processed_size) {
QMetaObject::invokeMethod(progress,
"setValue",
Qt::DirectConnection,
QMetaObject::invokeMethod(
progress, "setValue", Qt::DirectConnection,
Q_ARG(int, static_cast<int>((processed_size * 100) / total_size)));
return !progress->wasCanceled();
};
QFuture<bool> future = QtConcurrent::run([=]() {
return QtCommon::Compress::compressDir(zip_dump_location,
QString::fromStdString(dir),
QtCommon::Compress::Options(),
progress_callback);
return QtCommon::Compress::compressDir(zip_dump_location, QString::fromStdString(dir),
QtCommon::Compress::Options(), progress_callback);
});
QFutureWatcher<bool>* watcher = new QFutureWatcher<bool>(rootObject);
@ -464,42 +420,32 @@ void ExportDataDir(FrontendCommon::DataManager::DataDir data_dir,
watcher->setFuture(future);
}
void ImportDataDir(FrontendCommon::DataManager::DataDir data_dir,
const std::string& user_id,
std::function<void()> callback)
{
void ImportDataDir(FrontendCommon::DataManager::DataDir data_dir, const std::string& user_id,
std::function<void()> callback) {
const std::string dir = FrontendCommon::DataManager::GetDataDirString(data_dir, user_id);
using namespace QtCommon::Frontend;
const QString zip_dump_location = GetOpenFileName(tr("Select Import Location"),
{},
tr("Zipped Archives (*.zip)"));
const QString zip_dump_location =
GetOpenFileName(tr("Select Import Location"), {}, tr("Zipped Archives (*.zip)"));
if (zip_dump_location.isEmpty())
return;
StandardButton button = Warning(
tr("Import Warning"),
StandardButton button =
Warning(tr("Import Warning"),
tr("All previous data in this directory will be deleted. Are you sure you wish to "
"proceed?"),
StandardButton::Yes | StandardButton::No);
if (button != QMessageBox::Yes)
if (button != QtCommon::Frontend::Yes)
return;
QtProgressDialog* progress = new QtProgressDialog(
tr("Importing data. This may take a while..."), tr("Cancel"), 0, 100, rootObject);
QtProgressDialog* progress =
newProgressDialogPtr(tr("Importing data. This may take a while..."), tr("Cancel"), 0, 100);
progress->setWindowTitle(tr("Importing"));
progress->setWindowModality(Qt::WindowModal);
progress->setMinimumDuration(100);
progress->setAutoClose(false);
progress->setAutoReset(false);
progress->setTitle(tr("Importing"));
progress->show();
progress->setValue(0);
QGuiApplication::processEvents();
// to prevent GUI mangling we have to run this in a thread as well
QFuture<bool> delete_future = QtConcurrent::run([=]() {
@ -512,17 +458,14 @@ void ImportDataDir(FrontendCommon::DataManager::DataDir data_dir,
QObject::connect(delete_watcher, &QFutureWatcher<bool>::finished, rootObject, [=]() {
auto progress_callback = [=](size_t total_size, size_t processed_size) {
QMetaObject::invokeMethod(progress,
"setValue",
Qt::DirectConnection,
Q_ARG(int,
static_cast<int>((processed_size * 100) / total_size)));
QMetaObject::invokeMethod(
progress, "setValue", Qt::DirectConnection,
Q_ARG(int, static_cast<int>((processed_size * 100) / total_size)));
return !progress->wasCanceled();
};
QFuture<bool> future = QtConcurrent::run([=]() {
return !QtCommon::Compress::extractDir(zip_dump_location,
QString::fromStdString(dir),
return !QtCommon::Compress::extractDir(zip_dump_location, QString::fromStdString(dir),
progress_callback)
.empty();
});
@ -553,4 +496,5 @@ void ImportDataDir(FrontendCommon::DataManager::DataDir data_dir,
});
}
// TODO(crueter): Port InstallFirmware et al. from QML Branch
} // namespace QtCommon::Content

View file

@ -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
#ifndef QT_CONTENT_UTIL_H
@ -13,7 +13,7 @@
namespace QtCommon::Content {
//
bool CheckGameFirmware(u64 program_id, QObject *parent);
bool CheckGameFirmware(u64 program_id);
enum class FirmwareInstallResult {
Success,
@ -23,8 +23,7 @@ enum class FirmwareInstallResult {
FailedCorrupted,
};
inline const QString GetFirmwareInstallResultString(FirmwareInstallResult result)
{
inline const QString GetFirmwareInstallResultString(FirmwareInstallResult result) {
return LOOKUP_ENUM(result, FwInstallSuccess);
}
@ -33,30 +32,29 @@ inline const QString GetFirmwareInstallResultString(FirmwareInstallResult result
* \param result The result code.
* \return A string representation of the passed result code.
*/
inline const QString GetKeyInstallResultString(FirmwareManager::KeyInstallResult result)
{
inline const QString GetKeyInstallResultString(FirmwareManager::KeyInstallResult result) {
return LOOKUP_ENUM(result, KeyInstallSuccess);
}
void InstallFirmware(const QString &location, bool recursive);
void InstallFirmware(const QString& location, bool recursive);
QString UnzipFirmwareToTmp(const QString &location);
QString UnzipFirmwareToTmp(const QString& location);
// Keys //
void InstallKeys();
// Content //
void VerifyGameContents(const std::string &game_path);
void VerifyGameContents(const std::string& game_path);
void VerifyInstalledContents();
void ClearDataDir(FrontendCommon::DataManager::DataDir dir, const std::string &user_id = "");
void ExportDataDir(FrontendCommon::DataManager::DataDir dir,
const std::string &user_id = "",
const QString &name = QStringLiteral("export"),
void ClearDataDir(FrontendCommon::DataManager::DataDir dir, const std::string& user_id = "");
void ExportDataDir(FrontendCommon::DataManager::DataDir dir, const std::string& user_id = "",
const QString& name = QStringLiteral("export"),
std::function<void()> callback = {});
void ImportDataDir(FrontendCommon::DataManager::DataDir dir, const std::string& user_id = "",
std::function<void()> callback = {});
void ImportDataDir(FrontendCommon::DataManager::DataDir dir, const std::string &user_id = "", std::function<void()> callback = {});
// Profiles //
void FixProfiles();
}
} // namespace QtCommon::Content
#endif // QT_CONTENT_UTIL_H

View file

@ -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
#include <algorithm>
@ -13,8 +13,7 @@ namespace fs = std::filesystem;
namespace QtCommon::FS {
void LinkRyujinx(std::filesystem::path &from, std::filesystem::path &to)
{
void LinkRyujinx(std::filesystem::path& from, std::filesystem::path& to) {
std::error_code ec;
// "ignore" errors--if the dir fails to be deleted, error handling later will handle it
@ -25,12 +24,12 @@ void LinkRyujinx(std::filesystem::path &from, std::filesystem::path &to)
} else {
QtCommon::Frontend::Critical(
tr("Failed to link save data"),
tr("Could not link directory:\n\t%1\nTo:\n\t%2").arg(QString::fromStdString(from.string()), QString::fromStdString(to.string())));
tr("Could not link directory:\n\t%1\nTo:\n\t%2")
.arg(QString::fromStdString(from.string()), QString::fromStdString(to.string())));
}
}
bool CheckUnlink(const fs::path &eden_dir, const fs::path &ryu_dir)
{
bool CheckUnlink(const fs::path& eden_dir, const fs::path& ryu_dir) {
bool eden_link = Common::FS::IsSymlink(eden_dir);
bool ryu_link = Common::FS::IsSymlink(ryu_dir);
@ -64,7 +63,7 @@ bool CheckUnlink(const fs::path &eden_dir, const fs::path &ryu_dir)
// NB: do NOT use remove_all, as Windows treats this as a remove_all to the target,
// NOT the junction
fs::remove(linked);
} catch (std::exception &e) {
} catch (std::exception& e) {
QtCommon::Frontend::Critical(
tr("Failed to unlink old directory"),
tr("OS returned error: %1").arg(QString::fromStdString(e.what())));
@ -74,7 +73,7 @@ bool CheckUnlink(const fs::path &eden_dir, const fs::path &ryu_dir)
// then COPY the other dir
try {
fs::copy(orig, linked, fs::copy_options::recursive);
} catch (std::exception &e) {
} catch (std::exception& e) {
QtCommon::Frontend::Critical(
tr("Failed to copy save data"),
tr("OS returned error: %1").arg(QString::fromStdString(e.what())));
@ -87,8 +86,7 @@ bool CheckUnlink(const fs::path &eden_dir, const fs::path &ryu_dir)
return true;
}
const fs::path GetRyujinxSavePath(const fs::path &path_hint, const u64 &program_id)
{
const fs::path GetRyujinxSavePath(const fs::path& path_hint, const u64& program_id) {
auto ryu_path = path_hint;
auto kvdb_path = Common::FS::GetKvdbPath(ryu_path);
@ -99,10 +97,13 @@ const fs::path GetRyujinxSavePath(const fs::path &path_hint, const u64 &program_
tr("Could not find Ryujinx installation"),
tr("Could not find a valid Ryujinx installation. This may typically occur if you are "
"using Ryujinx in portable mode.\n\nWould you like to manually select a portable "
"folder to use?"), StandardButton::Yes | StandardButton::No);
"folder to use?"),
StandardButton::Yes | StandardButton::No);
if (res == StandardButton::Yes) {
auto selected_path = GetExistingDirectory(tr("Ryujinx Portable Location"), QDir::homePath()).toStdString();
auto selected_path =
GetExistingDirectory(tr("Ryujinx Portable Location"), QDir::homePath())
.toStdString();
if (selected_path.empty())
return fs::path{};
@ -131,7 +132,7 @@ const fs::path GetRyujinxSavePath(const fs::path &path_hint, const u64 &program_
Common::FS::IMENReadResult res = Common::FS::ReadKvdb(kvdb_path, imens);
if (res == Common::FS::IMENReadResult::Success) {
for (const Common::FS::IMEN &imen : imens) {
for (const Common::FS::IMEN& imen : imens) {
if (imen.title_id == program_id)
return Common::FS::GetRyuSavePath(ryu_path, imen.save_id);
}

View file

@ -1,19 +1,19 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#include "common/common_types.h"
#include <filesystem>
#include <optional>
#include "common/common_types.h"
#pragma once
namespace QtCommon::FS {
void LinkRyujinx(std::filesystem::path &from, std::filesystem::path &to);
const std::filesystem::path GetRyujinxSavePath(const std::filesystem::path &path_hint, const u64 &program_id);
void LinkRyujinx(std::filesystem::path& from, std::filesystem::path& to);
const std::filesystem::path GetRyujinxSavePath(const std::filesystem::path& path_hint,
const u64& program_id);
/// returns FALSE if the dirs are NOT linked
bool CheckUnlink(const std::filesystem::path& eden_dir,
const std::filesystem::path& ryu_dir);
bool CheckUnlink(const std::filesystem::path& eden_dir, const std::filesystem::path& ryu_dir);
} // namespace QtCommon::FS

View file

@ -18,40 +18,34 @@
#include <QUrl>
#ifdef _WIN32
#include "common/scope_exit.h"
#include "common/string_util.h"
#include <shlobj.h>
#include <windows.h>
#include "common/scope_exit.h"
#include "common/string_util.h"
#else
#include "fmt/ostream.h"
#include <fstream>
#include "fmt/ostream.h"
#endif
namespace QtCommon::Game {
bool CreateShortcutLink(const std::filesystem::path& shortcut_path,
const std::string& comment,
bool CreateShortcutLink(const std::filesystem::path& shortcut_path, const std::string& comment,
const std::filesystem::path& icon_path,
const std::filesystem::path& command,
const std::string& arguments,
const std::string& categories,
const std::string& keywords,
const std::string& name)
try {
const std::filesystem::path& command, const std::string& arguments,
const std::string& categories, const std::string& keywords,
const std::string& name) try {
#ifdef _WIN32 // Windows
HRESULT hr = CoInitialize(nullptr);
if (FAILED(hr)) {
LOG_ERROR(Frontend, "CoInitialize failed");
return false;
}
SCOPE_EXIT
{
SCOPE_EXIT {
CoUninitialize();
};
IShellLinkW* ps1 = nullptr;
IPersistFile* persist_file = nullptr;
SCOPE_EXIT
{
SCOPE_EXIT {
if (persist_file != nullptr) {
persist_file->Release();
}
@ -59,10 +53,7 @@ try {
ps1->Release();
}
};
HRESULT hres = CoCreateInstance(CLSID_ShellLink,
nullptr,
CLSCTX_INPROC_SERVER,
IID_IShellLinkW,
HRESULT hres = CoCreateInstance(CLSID_ShellLink, nullptr, CLSCTX_INPROC_SERVER, IID_IShellLinkW,
reinterpret_cast<void**>(&ps1));
if (FAILED(hres)) {
LOG_ERROR(Frontend, "Failed to create IShellLinkW instance");
@ -142,10 +133,8 @@ try {
return false;
}
bool MakeShortcutIcoPath(const u64 program_id,
const std::string_view game_file_name,
std::filesystem::path& out_icon_path)
{
bool MakeShortcutIcoPath(const u64 program_id, const std::string_view game_file_name,
std::filesystem::path& out_icon_path) {
// Get path to Yuzu icons directory & icon extension
std::string ico_extension = "png";
#if defined(_WIN32)
@ -166,46 +155,38 @@ bool MakeShortcutIcoPath(const u64 program_id,
return true;
}
void OpenEdenFolder(const Common::FS::EdenPath& path)
{
void OpenEdenFolder(const Common::FS::EdenPath& path) {
QDesktopServices::openUrl(
QUrl::fromLocalFile(QString::fromStdString(Common::FS::GetEdenPathString(path))));
}
void OpenRootDataFolder()
{
void OpenRootDataFolder() {
OpenEdenFolder(Common::FS::EdenPath::EdenDir);
}
void OpenNANDFolder()
{
void OpenNANDFolder() {
OpenEdenFolder(Common::FS::EdenPath::NANDDir);
}
void OpenSaveFolder()
{
const auto path = Common::FS::GetEdenPath(Common::FS::EdenPath::NANDDir)
/ "user/save/0000000000000000";
void OpenSaveFolder() {
const auto path =
Common::FS::GetEdenPath(Common::FS::EdenPath::NANDDir) / "user/save/0000000000000000";
QDesktopServices::openUrl(QUrl::fromLocalFile(QString::fromStdString(path.string())));
}
void OpenSDMCFolder()
{
void OpenSDMCFolder() {
OpenEdenFolder(Common::FS::EdenPath::SDMCDir);
}
void OpenModFolder()
{
void OpenModFolder() {
OpenEdenFolder(Common::FS::EdenPath::LoadDir);
}
void OpenLogFolder()
{
void OpenLogFolder() {
OpenEdenFolder(Common::FS::EdenPath::LogDir);
}
static QString GetGameListErrorRemoving(QtCommon::Game::InstalledEntryType type)
{
static QString GetGameListErrorRemoving(QtCommon::Game::InstalledEntryType type) {
switch (type) {
case QtCommon::Game::InstalledEntryType::Game:
return tr("Error Removing Contents");
@ -219,10 +200,9 @@ static QString GetGameListErrorRemoving(QtCommon::Game::InstalledEntryType type)
}
// Game Content //
void RemoveBaseContent(u64 program_id, InstalledEntryType type)
{
const auto res = ContentManager::RemoveBaseContent(system->GetFileSystemController(),
program_id);
void RemoveBaseContent(u64 program_id, InstalledEntryType type) {
const auto res =
ContentManager::RemoveBaseContent(system->GetFileSystemController(), program_id);
if (res) {
QtCommon::Frontend::Information(tr("Successfully Removed"),
tr("Successfully removed the installed base game."));
@ -234,8 +214,7 @@ void RemoveBaseContent(u64 program_id, InstalledEntryType type)
}
}
void RemoveUpdateContent(u64 program_id, InstalledEntryType type)
{
void RemoveUpdateContent(u64 program_id, InstalledEntryType type) {
const auto res = ContentManager::RemoveUpdate(system->GetFileSystemController(), program_id);
if (res) {
QtCommon::Frontend::Information(tr("Successfully Removed"),
@ -246,8 +225,7 @@ void RemoveUpdateContent(u64 program_id, InstalledEntryType type)
}
}
void RemoveAddOnContent(u64 program_id, InstalledEntryType type)
{
void RemoveAddOnContent(u64 program_id, InstalledEntryType type) {
const size_t count = ContentManager::RemoveAllDLC(*system, program_id);
if (count == 0) {
QtCommon::Frontend::Warning(GetGameListErrorRemoving(type),
@ -261,8 +239,7 @@ void RemoveAddOnContent(u64 program_id, InstalledEntryType type)
// Global Content //
void RemoveTransferableShaderCache(u64 program_id, GameListRemoveTarget target)
{
void RemoveTransferableShaderCache(u64 program_id, GameListRemoveTarget target) {
const auto target_file_name = [target] {
switch (target) {
case GameListRemoveTarget::GlShaderCache:
@ -291,8 +268,7 @@ void RemoveTransferableShaderCache(u64 program_id, GameListRemoveTarget target)
}
}
void RemoveVulkanDriverPipelineCache(u64 program_id)
{
void RemoveVulkanDriverPipelineCache(u64 program_id) {
static constexpr std::string_view target_file_name = "vulkan_pipelines.bin";
const auto shader_cache_dir = Common::FS::GetEdenPath(Common::FS::EdenPath::ShaderDir);
@ -308,8 +284,7 @@ void RemoveVulkanDriverPipelineCache(u64 program_id)
}
}
void RemoveAllTransferableShaderCaches(u64 program_id)
{
void RemoveAllTransferableShaderCaches(u64 program_id) {
const auto shader_cache_dir = Common::FS::GetEdenPath(Common::FS::EdenPath::ShaderDir);
const auto program_shader_cache_dir = shader_cache_dir / fmt::format("{:016x}", program_id);
@ -329,14 +304,13 @@ void RemoveAllTransferableShaderCaches(u64 program_id)
}
}
void RemoveCustomConfiguration(u64 program_id, const std::string& game_path)
{
void RemoveCustomConfiguration(u64 program_id, const std::string& game_path) {
const auto file_path = std::filesystem::path(Common::FS::ToU8String(game_path));
const auto config_file_name
= program_id == 0 ? Common::FS::PathToUTF8String(file_path.filename()).append(".ini")
const auto config_file_name =
program_id == 0 ? Common::FS::PathToUTF8String(file_path.filename()).append(".ini")
: fmt::format("{:016X}.ini", program_id);
const auto custom_config_file_path = Common::FS::GetEdenPath(Common::FS::EdenPath::ConfigDir)
/ "custom" / config_file_name;
const auto custom_config_file_path =
Common::FS::GetEdenPath(Common::FS::EdenPath::ConfigDir) / "custom" / config_file_name;
if (!Common::FS::Exists(custom_config_file_path)) {
QtCommon::Frontend::Warning(tr("Error Removing Custom Configuration"),
@ -353,20 +327,14 @@ void RemoveCustomConfiguration(u64 program_id, const std::string& game_path)
}
}
void RemoveCacheStorage(u64 program_id)
{
void RemoveCacheStorage(u64 program_id) {
const auto nand_dir = Common::FS::GetEdenPath(Common::FS::EdenPath::NANDDir);
auto vfs_nand_dir = vfs->OpenDirectory(Common::FS::PathToUTF8String(nand_dir),
FileSys::OpenMode::Read);
auto vfs_nand_dir =
vfs->OpenDirectory(Common::FS::PathToUTF8String(nand_dir), FileSys::OpenMode::Read);
const auto cache_storage_path
= FileSys::SaveDataFactory::GetFullPath({},
vfs_nand_dir,
FileSys::SaveDataSpaceId::User,
FileSys::SaveDataType::Cache,
0 /* program_id */,
{},
0);
const auto cache_storage_path = FileSys::SaveDataFactory::GetFullPath(
{}, vfs_nand_dir, FileSys::SaveDataSpaceId::User, FileSys::SaveDataType::Cache,
0 /* program_id */, {}, 0);
const auto path = Common::FS::ConcatPathSafe(nand_dir, cache_storage_path);
@ -400,32 +368,31 @@ void ResetMetadata(bool show_message) {
// Uhhh //
// Messages in pre-defined message boxes for less code spaghetti
inline constexpr bool CreateShortcutMessagesGUI(ShortcutMessages imsg, const QString& game_title)
{
inline constexpr bool CreateShortcutMessagesGUI(ShortcutMessages imsg, const QString& game_title) {
int result = 0;
QMessageBox::StandardButtons buttons;
using namespace QtCommon::Frontend;
int buttons;
switch (imsg) {
case ShortcutMessages::Fullscreen:
buttons = QMessageBox::Yes | QMessageBox::No;
result
= QtCommon::Frontend::Information(tr("Create Shortcut"),
tr("Do you want to launch the game in fullscreen?"),
buttons);
return result == QMessageBox::Yes;
buttons = Yes | No;
result = QtCommon::Frontend::Information(
tr("Create Shortcut"), tr("Do you want to launch the game in fullscreen?"), buttons);
return result == Yes;
case ShortcutMessages::Success:
QtCommon::Frontend::Information(tr("Shortcut Created"),
tr("Successfully created a shortcut to %1").arg(game_title));
QtCommon::Frontend::Information(
tr("Shortcut Created"), tr("Successfully created a shortcut to %1").arg(game_title));
return false;
case ShortcutMessages::Volatile:
buttons = QMessageBox::StandardButton::Ok | QMessageBox::StandardButton::Cancel;
buttons = Ok | Cancel;
result = QtCommon::Frontend::Warning(
tr("Shortcut may be Volatile!"),
tr("This will create a shortcut to the current AppImage. This may "
"not work well if you update. Continue?"),
buttons);
return result == QMessageBox::Ok;
return result == Ok;
default:
buttons = QMessageBox::Ok;
buttons = Ok;
QtCommon::Frontend::Critical(tr("Failed to Create Shortcut"),
tr("Failed to create a shortcut to %1").arg(game_title),
buttons);
@ -433,13 +400,9 @@ inline constexpr bool CreateShortcutMessagesGUI(ShortcutMessages imsg, const QSt
}
}
void CreateShortcut(const std::string& game_path,
const u64 program_id,
const std::string& game_title_,
const ShortcutTarget& target,
std::string arguments_,
const bool needs_title)
{
void CreateShortcut(const std::string& game_path, const u64 program_id,
const std::string& game_title_, const ShortcutTarget& target,
std::string arguments_, const bool needs_title) {
// Get path to Eden executable
std::filesystem::path command = GetEdenCommand();
@ -453,13 +416,11 @@ void CreateShortcut(const std::string& game_path,
return;
}
const FileSys::PatchManager pm{program_id,
QtCommon::system->GetFileSystemController(),
const FileSys::PatchManager pm{program_id, QtCommon::system->GetFileSystemController(),
QtCommon::system->GetContentProvider()};
const auto control = pm.GetControlMetadata();
const auto loader = Loader::GetLoader(*QtCommon::system,
QtCommon::vfs->OpenFile(game_path,
FileSys::OpenMode::Read));
const auto loader = Loader::GetLoader(
*QtCommon::system, QtCommon::vfs->OpenFile(game_path, FileSys::OpenMode::Read));
std::string game_title{game_title_};
@ -490,8 +451,8 @@ void CreateShortcut(const std::string& game_path,
LOG_WARNING(Frontend, "Could not read icon from {:s}", game_path);
}
QImage icon_data = QImage::fromData(icon_image_file.data(),
static_cast<int>(icon_image_file.size()));
QImage icon_data =
QImage::fromData(icon_image_file.data(), static_cast<int>(icon_image_file.size()));
std::filesystem::path out_icon_path;
if (QtCommon::Game::MakeShortcutIcoPath(program_id, game_title, out_icon_path)) {
if (!SaveIconToFile(out_icon_path, icon_data)) {
@ -524,39 +485,32 @@ void CreateShortcut(const std::string& game_path,
const std::string categories = "Game;Emulator;Qt;";
const std::string keywords = "Switch;Nintendo;";
if (QtCommon::Game::CreateShortcutLink(shortcut_path,
comment,
out_icon_path,
command,
arguments,
categories,
keywords,
game_title)) {
if (QtCommon::Game::CreateShortcutLink(shortcut_path, comment, out_icon_path, command,
arguments, categories, keywords, game_title)) {
CreateShortcutMessagesGUI(ShortcutMessages::Success, qgame_title);
return;
}
CreateShortcutMessagesGUI(ShortcutMessages::Failed, qgame_title);
}
// TODO: You want this to be constexpr? Well too bad, clang19 doesn't believe this is a string literal
std::string GetShortcutPath(ShortcutTarget target)
{
// TODO: You want this to be constexpr? Well too bad, clang19 doesn't believe this is a string
// literal
std::string GetShortcutPath(ShortcutTarget target) {
{
std::string shortcut_path{};
if (target == ShortcutTarget::Desktop) {
shortcut_path
= QStandardPaths::writableLocation(QStandardPaths::DesktopLocation).toStdString();
shortcut_path =
QStandardPaths::writableLocation(QStandardPaths::DesktopLocation).toStdString();
} else if (target == ShortcutTarget::Applications) {
shortcut_path
= QStandardPaths::writableLocation(QStandardPaths::ApplicationsLocation).toStdString();
shortcut_path = QStandardPaths::writableLocation(QStandardPaths::ApplicationsLocation)
.toStdString();
}
return shortcut_path;
}
}
void CreateHomeMenuShortcut(ShortcutTarget target)
{
void CreateHomeMenuShortcut(ShortcutTarget target) {
constexpr u64 QLaunchId = static_cast<u64>(Service::AM::AppletProgramId::QLaunch);
auto bis_system = QtCommon::system->GetFileSystemController().GetSystemNANDContents();
if (!bis_system) {

View file

@ -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
#ifndef QT_GAME_UTIL_H
@ -29,27 +29,18 @@ enum class ShortcutTarget {
Applications,
};
enum class ShortcutMessages{
Fullscreen = 0,
Success = 1,
Volatile = 2,
Failed = 3
};
enum class ShortcutMessages { Fullscreen = 0, Success = 1, Volatile = 2, Failed = 3 };
bool CreateShortcutLink(const std::filesystem::path& shortcut_path,
const std::string& comment,
bool CreateShortcutLink(const std::filesystem::path& shortcut_path, const std::string& comment,
const std::filesystem::path& icon_path,
const std::filesystem::path& command,
const std::string& arguments,
const std::string& categories,
const std::string& keywords,
const std::filesystem::path& command, const std::string& arguments,
const std::string& categories, const std::string& keywords,
const std::string& name);
bool MakeShortcutIcoPath(const u64 program_id,
const std::string_view game_file_name,
bool MakeShortcutIcoPath(const u64 program_id, const std::string_view game_file_name,
std::filesystem::path& out_icon_path);
void OpenEdenFolder(const Common::FS::EdenPath &path);
void OpenEdenFolder(const Common::FS::EdenPath& path);
void OpenRootDataFolder();
void OpenNANDFolder();
void OpenSaveFolder();
@ -71,16 +62,13 @@ void RemoveCacheStorage(u64 program_id);
void ResetMetadata(bool show_message = true);
// Shortcuts //
void CreateShortcut(const std::string& game_path,
const u64 program_id,
const std::string& game_title_,
const ShortcutTarget& target,
std::string arguments_,
const bool needs_title);
void CreateShortcut(const std::string& game_path, const u64 program_id,
const std::string& game_title_, const ShortcutTarget& target,
std::string arguments_, const bool needs_title);
std::string GetShortcutPath(ShortcutTarget target);
void CreateHomeMenuShortcut(ShortcutTarget target);
}
} // namespace QtCommon::Game
#endif // QT_GAME_UTIL_H

View file

@ -1,7 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#include "qt_common/util/meta.h"
#include "common/common_types.h"
#include "core/core.h"
#include "core/frontend/applets/cabinet.h"
@ -9,11 +8,11 @@
#include "core/frontend/applets/profile_select.h"
#include "core/frontend/applets/software_keyboard.h"
#include "core/hle/service/am/frontend/applet_web_browser_types.h"
#include "qt_common/util/meta.h"
namespace QtCommon::Meta {
void RegisterMetaTypes()
{
void RegisterMetaTypes() {
// Register integral and floating point types
qRegisterMetaType<u8>("u8");
qRegisterMetaType<u16>("u16");
@ -72,4 +71,4 @@ void RegisterMetaTypes()
qRegisterMetaType<Core::SystemResultStatus>("Core::SystemResultStatus");
}
}
} // namespace QtCommon::Meta

View file

@ -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
#ifndef QT_META_H
@ -11,5 +11,5 @@ namespace QtCommon::Meta {
//
void RegisterMetaTypes();
}
} // namespace QtCommon::Meta
#endif // QT_META_H

View file

@ -43,7 +43,8 @@ QStringList GetModFolders(const QString& root, const QString& fallbackName) {
QString name = QtCommon::Frontend::GetTextInput(
tr("Mod Name"), tr("What should this mod be called?"), default_name);
if (name.isEmpty()) return {};
if (name.isEmpty())
return {};
// if std_path is empty, frontend_common could not determine mod type and/or name.
// so we have to prompt the user and set up the structure ourselves

View file

@ -7,8 +7,8 @@
namespace QtCommon::Mod {
QStringList GetModFolders(const QString &root, const QString &fallbackName);
QStringList GetModFolders(const QString& root, const QString& fallbackName);
const QString ExtractMod(const QString &path);
const QString ExtractMod(const QString& path);
}
} // namespace QtCommon::Mod

View file

@ -1,28 +1,24 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#include "qt_common/util/path.h"
#include <QDesktopServices>
#include <QString>
#include <QUrl>
#include <fmt/format.h>
#include "common/fs/fs.h"
#include "common/fs/path_util.h"
#include "qt_common/abstract/frontend.h"
#include <fmt/format.h>
#include "qt_common/util/path.h"
namespace QtCommon::Path {
bool OpenShaderCache(u64 program_id, QObject *parent)
{
bool OpenShaderCache(u64 program_id, QObject* parent) {
const auto shader_cache_dir = Common::FS::GetEdenPath(Common::FS::EdenPath::ShaderDir);
const auto shader_cache_folder_path{shader_cache_dir / fmt::format("{:016x}", program_id)};
if (!Common::FS::CreateDirs(shader_cache_folder_path)) {
QtCommon::Frontend::ShowMessage(QMessageBox::Warning,
tr("Error Opening Shader Cache"),
QtCommon::Frontend::Warning(tr("Error Opening Shader Cache"),
tr("Failed to create or open shader cache for this title, "
"ensure your app data directory has write permissions."),
QMessageBox::Ok,
parent);
"ensure your app data directory has write permissions."));
}
const auto shader_path_string{Common::FS::PathToUTF8String(shader_cache_folder_path)};
@ -30,4 +26,4 @@ bool OpenShaderCache(u64 program_id, QObject *parent)
return QDesktopServices::openUrl(QUrl::fromLocalFile(qt_shader_cache_path));
}
}
} // namespace QtCommon::Path

View file

@ -1,12 +1,14 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#ifndef QT_PATH_UTIL_H
#define QT_PATH_UTIL_H
#include "common/common_types.h"
#include <QObject>
#include "common/common_types.h"
namespace QtCommon::Path { bool OpenShaderCache(u64 program_id, QObject *parent); }
namespace QtCommon::Path {
bool OpenShaderCache(u64 program_id, QObject* parent);
}
#endif // QT_PATH_UTIL_H

View file

@ -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
#include "qt_common/util/rom.h"
@ -7,13 +7,8 @@
namespace QtCommon::ROM {
bool RomFSRawCopy(size_t total_size,
size_t& read_size,
QtProgressCallback callback,
const FileSys::VirtualDir& src,
const FileSys::VirtualDir& dest,
bool full)
{
bool RomFSRawCopy(size_t total_size, size_t& read_size, QtProgressCallback callback,
const FileSys::VirtualDir& src, const FileSys::VirtualDir& dest, bool full) {
// TODO(crueter)
// if (src == nullptr || dest == nullptr || !src->IsReadable() || !dest->IsWritable())
// return false;
@ -75,4 +70,4 @@ bool RomFSRawCopy(size_t total_size,
return true;
}
}
} // namespace QtCommon::ROM

View file

@ -1,20 +1,16 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#ifndef QT_ROM_UTIL_H
#define QT_ROM_UTIL_H
#include "qt_common/qt_common.h"
#include <cstddef>
#include "qt_common/qt_common.h"
namespace QtCommon::ROM {
bool RomFSRawCopy(size_t total_size,
size_t& read_size,
QtProgressCallback callback,
const FileSys::VirtualDir& src,
const FileSys::VirtualDir& dest,
bool full);
bool RomFSRawCopy(size_t total_size, size_t& read_size, QtProgressCallback callback,
const FileSys::VirtualDir& src, const FileSys::VirtualDir& dest, bool full);
}
#endif // QT_ROM_UTIL_H

View file

@ -70,10 +70,14 @@ TextureCache<P>::TextureCache(Runtime& runtime_, Tegra::MaxwellDeviceMemoryManag
(std::max)((std::min)(device_local_memory - min_vacancy_critical, min_spacing_critical),
DEFAULT_CRITICAL_MEMORY));
minimum_memory = static_cast<u64>((device_local_memory - mem_threshold) / 2);
lowmemorydevice = false;
} else {
expected_memory = DEFAULT_EXPECTED_MEMORY + 512_MiB;
critical_memory = DEFAULT_CRITICAL_MEMORY + 1_GiB;
minimum_memory = 0;
lowmemorydevice = true;
}
const bool gpu_unswizzle_enabled = Settings::values.gpu_unswizzle_enabled.GetValue();
@ -118,46 +122,102 @@ void TextureCache<P>::RunGarbageCollector() {
bool aggressive_mode = false;
u64 ticks_to_destroy = 0;
size_t num_iterations = 0;
const auto Configure = [&](bool allow_aggressive) {
high_priority_mode = total_used_memory >= expected_memory;
aggressive_mode = allow_aggressive && total_used_memory >= critical_memory;
ticks_to_destroy = aggressive_mode ? 10ULL : high_priority_mode ? 25ULL : 50ULL;
num_iterations = aggressive_mode ? 40 : (high_priority_mode ? 20 : 10);
};
const auto Cleanup = [this, &num_iterations, &high_priority_mode, &aggressive_mode](ImageId image_id) {
const auto Cleanup = [this, &num_iterations, &high_priority_mode,
&aggressive_mode](ImageId image_id) {
if (num_iterations == 0) {
return true;
}
--num_iterations;
auto& image = slot_images[image_id];
if (True(image.flags & ImageFlagBits::IsDecoding)) {
// Never delete recently allocated sparse textures (within 3 frames)
const bool is_recently_allocated = image.allocation_tick >= frame_tick - 3;
if (is_recently_allocated && image.info.is_sparse) {
return false;
}
const bool must_download = image.IsSafeDownload() && False(image.flags & ImageFlagBits::BadOverlap);
if (must_download && !image.info.is_sparse) {
if (True(image.flags & ImageFlagBits::IsDecoding)) {
// This image is still being decoded, deleting it will invalidate the slot
// used by the async decoder thread.
return false;
}
// Prioritize large sparse textures for cleanup
const bool is_large_sparse = lowmemorydevice &&
image.info.is_sparse &&
image.guest_size_bytes >= 256_MiB;
if (!aggressive_mode && !is_large_sparse &&
True(image.flags & ImageFlagBits::CostlyLoad)) {
return false;
}
const bool must_download =
image.IsSafeDownload() && False(image.flags & ImageFlagBits::BadOverlap);
if (!high_priority_mode && !is_large_sparse && must_download) {
return false;
}
if (must_download && !is_large_sparse) {
auto map = runtime.DownloadStagingBuffer(image.unswizzled_size_bytes);
const auto copies = FixSmallVectorADL(FullDownloadCopies(image.info));
image.DownloadMemory(map, copies);
runtime.Finish();
SwizzleImage(*gpu_memory, image.gpu_addr, image.info, copies, map.mapped_span, swizzle_data_buffer);
SwizzleImage(*gpu_memory, image.gpu_addr, image.info, copies, map.mapped_span,
swizzle_data_buffer);
}
if (True(image.flags & ImageFlagBits::Tracked)) {
UntrackImage(image, image_id);
}
UnregisterImage(image_id);
DeleteImage(image_id, (frame_tick - image.scale_tick) > 5 || aggressive_mode);
if (aggressive_mode && total_used_memory < critical_memory) {
DeleteImage(image_id, image.scale_tick > frame_tick + 5);
if (total_used_memory < critical_memory) {
if (aggressive_mode) {
// Sink the aggresiveness.
num_iterations >>= 2;
aggressive_mode = false;
return false;
}
if (high_priority_mode && total_used_memory < expected_memory) {
num_iterations >>= 1;
high_priority_mode = false;
}
}
return false;
};
// Aggressively clear massive sparse textures
if (total_used_memory >= expected_memory) {
lru_cache.ForEachItemBelow(frame_tick, [&](ImageId image_id) {
auto& image = slot_images[image_id];
// Only target sparse textures that are old enough
if (lowmemorydevice &&
image.info.is_sparse &&
image.guest_size_bytes >= 256_MiB &&
image.allocation_tick < frame_tick - 3) {
LOG_DEBUG(HW_GPU, "GC targeting old sparse texture at 0x{:X} ({} MiB, age: {} frames)",
image.gpu_addr, image.guest_size_bytes / (1024 * 1024),
frame_tick - image.allocation_tick);
return Cleanup(image_id);
}
return false;
});
}
Configure(false);
lru_cache.ForEachItemBelow(frame_tick - ticks_to_destroy, Cleanup);
// If pressure is still too high, prune aggressively.
if (total_used_memory >= critical_memory) {
Configure(true);
lru_cache.ForEachItemBelow(frame_tick - ticks_to_destroy, Cleanup);
@ -1136,6 +1196,9 @@ void TextureCache<P>::RefreshContents(Image& image, ImageId image_id) {
}
image.flags &= ~ImageFlagBits::CpuModified;
if( lowmemorydevice && image.info.format == PixelFormat::BC1_RGBA_UNORM && MapSizeBytes(image) >= 256_MiB ) {
return;
}
TrackImage(image, image_id);
@ -1556,6 +1619,39 @@ ImageId TextureCache<P>::InsertImage(const ImageInfo& info, GPUVAddr gpu_addr,
}
}
ASSERT_MSG(cpu_addr, "Tried to insert an image to an invalid gpu_addr=0x{:x}", gpu_addr);
// For large sparse textures, aggressively clean up old allocations at same address
if (lowmemorydevice && info.is_sparse && CalculateGuestSizeInBytes(info) >= 256_MiB) {
const auto alloc_it = image_allocs_table.find(gpu_addr);
if (alloc_it != image_allocs_table.end()) {
const ImageAllocId alloc_id = alloc_it->second;
auto& alloc_images = slot_image_allocs[alloc_id].images;
// Collect old images at this address that were created more than 2 frames ago
boost::container::small_vector<ImageId, 4> to_delete;
for (ImageId old_image_id : alloc_images) {
Image& old_image = slot_images[old_image_id];
if (old_image.info.is_sparse &&
old_image.gpu_addr == gpu_addr &&
old_image.allocation_tick < frame_tick - 2) { // Try not to delete fresh textures
to_delete.push_back(old_image_id);
}
}
// Delete old images immediately
for (ImageId old_id : to_delete) {
Image& old_image = slot_images[old_id];
LOG_DEBUG(HW_GPU, "Immediately deleting old sparse texture at 0x{:X} ({} MiB)",
gpu_addr, old_image.guest_size_bytes / (1024 * 1024));
if (True(old_image.flags & ImageFlagBits::Tracked)) {
UntrackImage(old_image, old_id);
}
UnregisterImage(old_id);
DeleteImage(old_id, true);
}
}
}
const ImageId image_id = JoinImages(info, gpu_addr, *cpu_addr);
const Image& image = slot_images[image_id];
// Using "image.gpu_addr" instead of "gpu_addr" is important because it might be different
@ -1571,6 +1667,27 @@ template <class P>
ImageId TextureCache<P>::JoinImages(const ImageInfo& info, GPUVAddr gpu_addr, DAddr cpu_addr) {
ImageInfo new_info = info;
const size_t size_bytes = CalculateGuestSizeInBytes(new_info);
// Proactive cleanup for large sparse texture allocations
if (lowmemorydevice && new_info.is_sparse && size_bytes >= 256_MiB) {
const u64 estimated_alloc_size = size_bytes;
if (total_used_memory + estimated_alloc_size >= critical_memory) {
LOG_DEBUG(HW_GPU, "Large sparse texture allocation ({} MiB) - running aggressive GC. "
"Current memory: {} MiB, Critical: {} MiB",
size_bytes / (1024 * 1024),
total_used_memory / (1024 * 1024),
critical_memory / (1024 * 1024));
RunGarbageCollector();
// If still over threshold after GC, try one more aggressive pass
if (total_used_memory + estimated_alloc_size >= critical_memory) {
LOG_DEBUG(HW_GPU, "Still critically low on memory, running second GC pass");
RunGarbageCollector();
}
}
}
const bool broken_views = runtime.HasBrokenTextureViewFormats();
const bool native_bgr = runtime.HasNativeBgr();
join_overlap_ids.clear();

View file

@ -478,6 +478,7 @@ private:
u64 minimum_memory;
u64 expected_memory;
u64 critical_memory;
bool lowmemorydevice = false;
size_t gpu_unswizzle_maxsize = 0;
size_t swizzle_chunk_size = 0;
u32 swizzle_slices_per_batch = 0;

View file

@ -244,6 +244,7 @@ add_executable(yuzu
configuration/addon/mod_select_dialog.h configuration/addon/mod_select_dialog.cpp configuration/addon/mod_select_dialog.ui
render/performance_overlay.h render/performance_overlay.cpp render/performance_overlay.ui
libqt_common.h libqt_common.cpp
)
set_target_properties(yuzu PROPERTIES OUTPUT_NAME "eden")

View file

@ -1,29 +1,24 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "yuzu/about_dialog.h"
#include <QIcon>
#include <fmt/ranges.h>
#include "common/scm_rev.h"
#include "ui_aboutdialog.h"
#include <fmt/ranges.h>
#include "yuzu/about_dialog.h"
AboutDialog::AboutDialog(QWidget* parent)
: QDialog(parent)
, ui{std::make_unique<Ui::AboutDialog>()}
{
: QDialog(parent), ui{std::make_unique<Ui::AboutDialog>()} {
static const std::string build_id = std::string{Common::g_build_id};
static const std::string yuzu_build = fmt::format("{} | {} | {}",
std::string{Common::g_build_name},
std::string{Common::g_build_version},
std::string{Common::g_compiler_id}
);
static const std::string yuzu_build =
fmt::format("{} | {} | {}", std::string{Common::g_build_name},
std::string{Common::g_build_version}, std::string{Common::g_compiler_id});
const auto override_build = fmt::format(fmt::runtime(
std::string(Common::g_title_bar_format_idle)),
build_id);
const auto override_build =
fmt::format(fmt::runtime(std::string(Common::g_title_bar_format_idle)), build_id);
const auto yuzu_build_version = override_build.empty() ? yuzu_build : override_build;
ui->setupUi(this);

View file

@ -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: Copyright 2020 yuzu Emulator Project
@ -17,8 +17,8 @@
#include "hid_core/hid_core.h"
#include "hid_core/hid_types.h"
#include "hid_core/resources/npad/npad.h"
#include "ui_qt_controller.h"
#include "qt_common/qt_compat.h"
#include "ui_qt_controller.h"
#include "yuzu/applets/qt_controller.h"
#include "yuzu/configuration/configure_input.h"
#include "yuzu/configuration/configure_input_profile_dialog.h"
@ -188,7 +188,8 @@ QtControllerSelectorDialog::QtControllerSelectorDialog(
CheckIfParametersMet();
});
connect(connected_controller_checkboxes[i], &QCheckBox::STATE_CHANGED, [this, i](int state) {
connect(connected_controller_checkboxes[i], &QCheckBox::STATE_CHANGED,
[this, i](int state) {
player_groupboxes[i]->setChecked(state == Qt::Checked);
UpdateControllerIcon(i);
UpdateControllerState(i);

View file

@ -1499,14 +1499,14 @@ void QtSoftwareKeyboardDialog::StartInputThread() {
input_interpreter->PollInput();
HandleButtonPressedOnce<
Core::HID::NpadButton::A, Core::HID::NpadButton::B, Core::HID::NpadButton::X,
Core::HID::NpadButton::Y, Core::HID::NpadButton::StickL, Core::HID::NpadButton::StickR,
Core::HID::NpadButton::L, Core::HID::NpadButton::R, Core::HID::NpadButton::Plus,
Core::HID::NpadButton::Left, Core::HID::NpadButton::Up, Core::HID::NpadButton::Right,
Core::HID::NpadButton::Down, Core::HID::NpadButton::StickLLeft,
Core::HID::NpadButton::StickLUp, Core::HID::NpadButton::StickLRight,
Core::HID::NpadButton::StickLDown, Core::HID::NpadButton::StickRLeft,
Core::HID::NpadButton::StickRUp, Core::HID::NpadButton::StickRRight,
Core::HID::NpadButton::StickRDown>();
Core::HID::NpadButton::Y, Core::HID::NpadButton::StickL,
Core::HID::NpadButton::StickR, Core::HID::NpadButton::L, Core::HID::NpadButton::R,
Core::HID::NpadButton::Plus, Core::HID::NpadButton::Left, Core::HID::NpadButton::Up,
Core::HID::NpadButton::Right, Core::HID::NpadButton::Down,
Core::HID::NpadButton::StickLLeft, Core::HID::NpadButton::StickLUp,
Core::HID::NpadButton::StickLRight, Core::HID::NpadButton::StickLDown,
Core::HID::NpadButton::StickRLeft, Core::HID::NpadButton::StickRUp,
Core::HID::NpadButton::StickRRight, Core::HID::NpadButton::StickRDown>();
HandleButtonHold<Core::HID::NpadButton::B, Core::HID::NpadButton::L,
Core::HID::NpadButton::R, Core::HID::NpadButton::Left,
Core::HID::NpadButton::Up, Core::HID::NpadButton::Right,

View file

@ -63,8 +63,8 @@ QtNXWebEngineView::QtNXWebEngineView(QWidget* parent, Core::System& system,
: QWebEngineView(parent), input_subsystem{input_subsystem_},
url_interceptor(std::make_unique<UrlRequestInterceptor>()),
input_interpreter(std::make_unique<InputInterpreter>(system)),
default_profile{QWebEngineProfile::defaultProfile()}, global_settings{
default_profile->settings()} {
default_profile{QWebEngineProfile::defaultProfile()},
global_settings{default_profile->settings()} {
default_profile->setPersistentStoragePath(QString::fromStdString(Common::FS::PathToUTF8String(
Common::FS::GetEdenPath(Common::FS::EdenPath::EdenDir) / "qtwebengine")));
@ -299,21 +299,21 @@ void QtNXWebEngineView::StartInputThread() {
while (!stoken.stop_requested()) {
input_interpreter->PollInput();
HandleWindowFooterButtonPressedOnce<Core::HID::NpadButton::A, Core::HID::NpadButton::B,
Core::HID::NpadButton::X, Core::HID::NpadButton::Y,
Core::HID::NpadButton::L, Core::HID::NpadButton::R>();
HandleWindowFooterButtonPressedOnce<
Core::HID::NpadButton::A, Core::HID::NpadButton::B, Core::HID::NpadButton::X,
Core::HID::NpadButton::Y, Core::HID::NpadButton::L, Core::HID::NpadButton::R>();
HandleWindowKeyButtonPressedOnce<
Core::HID::NpadButton::Left, Core::HID::NpadButton::Up, Core::HID::NpadButton::Right,
Core::HID::NpadButton::Down, Core::HID::NpadButton::StickLLeft,
Core::HID::NpadButton::StickLUp, Core::HID::NpadButton::StickLRight,
Core::HID::NpadButton::StickLDown>();
Core::HID::NpadButton::Left, Core::HID::NpadButton::Up,
Core::HID::NpadButton::Right, Core::HID::NpadButton::Down,
Core::HID::NpadButton::StickLLeft, Core::HID::NpadButton::StickLUp,
Core::HID::NpadButton::StickLRight, Core::HID::NpadButton::StickLDown>();
HandleWindowKeyButtonHold<
Core::HID::NpadButton::Left, Core::HID::NpadButton::Up, Core::HID::NpadButton::Right,
Core::HID::NpadButton::Down, Core::HID::NpadButton::StickLLeft,
Core::HID::NpadButton::StickLUp, Core::HID::NpadButton::StickLRight,
Core::HID::NpadButton::StickLDown>();
Core::HID::NpadButton::Left, Core::HID::NpadButton::Up,
Core::HID::NpadButton::Right, Core::HID::NpadButton::Down,
Core::HID::NpadButton::StickLLeft, Core::HID::NpadButton::StickLUp,
Core::HID::NpadButton::StickLRight, Core::HID::NpadButton::StickLDown>();
std::this_thread::sleep_for(std::chrono::milliseconds(50));
}

View file

@ -169,7 +169,8 @@ private:
std::unique_ptr<InputInterpreter> input_interpreter;
std::jthread input_thread;
std::atomic<bool> finished{};
Service::AM::Frontend::WebExitReason exit_reason{Service::AM::Frontend::WebExitReason::EndButtonPressed};
Service::AM::Frontend::WebExitReason exit_reason{
Service::AM::Frontend::WebExitReason::EndButtonPressed};
std::string last_url{"http://localhost/"};
bool is_local{};
QWebEngineProfile* default_profile;

View file

@ -54,12 +54,12 @@
#include "input_common/drivers/tas_input.h"
#include "input_common/drivers/touch_screen.h"
#include "input_common/main.h"
#include "qt_common/qt_common.h"
#include "video_core/gpu.h"
#include "video_core/rasterizer_interface.h"
#include "video_core/renderer_base.h"
#include "yuzu/bootmanager.h"
#include "yuzu/main_window.h"
#include "qt_common/qt_common.h"
class QObject;
class QPaintEngine;
@ -282,8 +282,8 @@ struct NullRenderWidget : public RenderWidget {
GRenderWindow::GRenderWindow(MainWindow* parent, EmuThread* emu_thread_,
std::shared_ptr<InputCommon::InputSubsystem> input_subsystem_,
Core::System& system_)
: QWidget(parent),
emu_thread(emu_thread_), input_subsystem{std::move(input_subsystem_)}, system{system_} {
: QWidget(parent), emu_thread(emu_thread_), input_subsystem{std::move(input_subsystem_)},
system{system_} {
setWindowTitle(QStringLiteral("Eden %1 | %2-%3")
.arg(QString::fromUtf8(Common::g_build_name),
QString::fromUtf8(Common::g_scm_branch),
@ -887,13 +887,14 @@ void GRenderWindow::resizeEvent(QResizeEvent* event) {
std::unique_ptr<Core::Frontend::GraphicsContext> GRenderWindow::CreateSharedContext() const {
#ifdef HAS_OPENGL
if (Settings::values.renderer_backend.GetValue() == Settings::RendererBackend::OpenGL_GLSL
|| Settings::values.renderer_backend.GetValue() == Settings::RendererBackend::OpenGL_GLASM
|| Settings::values.renderer_backend.GetValue() == Settings::RendererBackend::OpenGL_SPIRV) {
if (Settings::values.renderer_backend.GetValue() == Settings::RendererBackend::OpenGL_GLSL ||
Settings::values.renderer_backend.GetValue() == Settings::RendererBackend::OpenGL_GLASM ||
Settings::values.renderer_backend.GetValue() == Settings::RendererBackend::OpenGL_SPIRV) {
auto c = static_cast<OpenGLSharedContext*>(main_context.get());
// Bind the shared contexts to the main surface in case the backend wants to take over
// presentation
return std::make_unique<OpenGLSharedContext>(c->GetShareContext(), child_widget->windowHandle());
return std::make_unique<OpenGLSharedContext>(c->GetShareContext(),
child_widget->windowHandle());
}
#endif
return std::make_unique<DummyContext>();
@ -940,9 +941,9 @@ bool GRenderWindow::InitRenderTarget() {
OnFramebufferSizeChanged();
BackupGeometry();
if (Settings::values.renderer_backend.GetValue() == Settings::RendererBackend::OpenGL_GLSL
|| Settings::values.renderer_backend.GetValue() == Settings::RendererBackend::OpenGL_GLASM
|| Settings::values.renderer_backend.GetValue() == Settings::RendererBackend::OpenGL_SPIRV)
if (Settings::values.renderer_backend.GetValue() == Settings::RendererBackend::OpenGL_GLSL ||
Settings::values.renderer_backend.GetValue() == Settings::RendererBackend::OpenGL_GLASM ||
Settings::values.renderer_backend.GetValue() == Settings::RendererBackend::OpenGL_SPIRV)
return LoadOpenGL();
return true;
}
@ -1050,7 +1051,8 @@ bool GRenderWindow::LoadOpenGL() {
}
// Display various warnings (but not fatal errors) for missing OpenGL extensions or lack of
// OpenGL 4.6 support
const QString renderer = QString::fromUtf8(reinterpret_cast<const char*>(glGetString(GL_RENDERER)));
const QString renderer =
QString::fromUtf8(reinterpret_cast<const char*>(glGetString(GL_RENDERER)));
if (!GLAD_GL_VERSION_4_6) {
QMessageBox::warning(this, tr("Error while initializing OpenGL 4.6!"),
tr("Your GPU may not support OpenGL 4.6, or you do not have the "
@ -1064,7 +1066,8 @@ bool GRenderWindow::LoadOpenGL() {
tr("Your GPU may not support one or more required OpenGL extensions. Please ensure you "
"have the latest graphics driver.<br><br>GL Renderer:<br>%1<br><br>Unsupported "
"extensions:<br>%2")
.arg(renderer).arg(missing_ext.join(QStringLiteral("<br>"))));
.arg(renderer)
.arg(missing_ext.join(QStringLiteral("<br>"))));
// Non fatal
}
return true;

View file

@ -43,7 +43,8 @@ ModSelectDialog::ModSelectDialog(const QStringList& mods, QWidget* parent)
width = qMax(width, item_model->item(i)->sizeHint().width());
}
width += ui->treeView->contentsMargins().left() * 4 + ui->treeView->contentsMargins().right() * 4;
width +=
ui->treeView->contentsMargins().left() * 4 + ui->treeView->contentsMargins().right() * 4;
ui->treeView->setMinimumHeight(qMin(height, 600));
ui->treeView->setMinimumWidth(qMin(width, 700));
adjustSize();

View file

@ -14,11 +14,12 @@ class ModSelectDialog : public QDialog {
Q_OBJECT
public:
explicit ModSelectDialog(const QStringList &mods, QWidget* parent = nullptr);
explicit ModSelectDialog(const QStringList& mods, QWidget* parent = nullptr);
~ModSelectDialog();
signals:
void modsSelected(const QStringList &mods);
void modsSelected(const QStringList& mods);
private:
Ui::ModSelectDialog* ui;

View file

@ -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: Copyright 2018 yuzu Emulator Project
@ -16,12 +16,12 @@
#include "common/settings.h"
#include "common/settings_common.h"
#include "core/core.h"
#include "qt_common/config/shared_translation.h"
#include "qt_common/config/uisettings.h"
#include "ui_configure_audio.h"
#include "yuzu/configuration/configuration_shared.h"
#include "yuzu/configuration/configure_audio.h"
#include "qt_common/config/shared_translation.h"
#include "yuzu/configuration/shared_widget.h"
#include "qt_common/config/uisettings.h"
ConfigureAudio::ConfigureAudio(const Core::System& system_,
std::shared_ptr<std::vector<ConfigurationShared::Tab*>> group_,
@ -188,8 +188,8 @@ void ConfigureAudio::SetOutputSinkFromSinkID() {
const std::string new_sink_id = []() -> const std::string {
const Settings::AudioEngine sink_id = Settings::values.sink_id.GetValue();
const auto canonicalizations
= Settings::EnumMetadata<Settings::AudioEngine>::Canonicalizations();
const auto canonicalizations =
Settings::EnumMetadata<Settings::AudioEngine>::Canonicalizations();
for (u32 i = 0; i < canonicalizations.size(); ++i) {
const Settings::AudioEngine value = canonicalizations[i].second;
@ -242,8 +242,8 @@ void ConfigureAudio::ApplyConfiguration() {
const u32 new_sink_id = [this]() {
const std::string sink_id = sink_combo_box->currentText().toStdString();
const auto canonicalizations
= Settings::EnumMetadata<Settings::AudioEngine>::Canonicalizations();
const auto canonicalizations =
Settings::EnumMetadata<Settings::AudioEngine>::Canonicalizations();
for (u32 i = 0; i < canonicalizations.size(); ++i) {
if (sink_id == canonicalizations[i].first)
@ -291,7 +291,8 @@ void ConfigureAudio::InitializeAudioSinkComboBox() {
sink_combo_box->clear();
sink_combo_box->addItem(QString::fromUtf8(AudioCore::Sink::auto_device_name));
for (const auto& id : AudioCore::Sink::GetSinkIDs())
sink_combo_box->addItem(QString::fromStdString(std::string{Settings::CanonicalizeEnum(id)}));
sink_combo_box->addItem(
QString::fromStdString(std::string{Settings::CanonicalizeEnum(id)}));
}
void ConfigureAudio::RetranslateUI() {

View file

@ -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: Copyright 2020 yuzu Emulator Project
@ -76,9 +76,9 @@ void ConfigureCpu::Setup(const ConfigurationShared::Builder& builder) {
} else if (setting->Id() == Settings::values.cpu_backend.Id()) {
backend_layout->addWidget(widget);
backend_combobox = widget->combobox;
} else if (setting->Id() == Settings::values.fast_cpu_time.Id()
|| setting->Id() == Settings::values.vtable_bouncing.Id()
|| setting->Id() == Settings::values.cpu_ticks.Id()) {
} else if (setting->Id() == Settings::values.fast_cpu_time.Id() ||
setting->Id() == Settings::values.vtable_bouncing.Id() ||
setting->Id() == Settings::values.cpu_ticks.Id()) {
ui->general_layout->addWidget(widget);
} else {
// Presently, all other settings here are unsafe checkboxes
@ -93,12 +93,12 @@ void ConfigureCpu::Setup(const ConfigurationShared::Builder& builder) {
UpdateGroup();
}
void ConfigureCpu::UpdateGroup()
{
void ConfigureCpu::UpdateGroup() {
const u32 accuracy = accuracy_combobox->currentIndex();
const u32 backend = backend_combobox->currentIndex();
// TODO(crueter): see if this works on NCE
ui->unsafe_group->setVisible(accuracy == (u32) Settings::CpuAccuracy::Unsafe && backend == (u32) Settings::CpuBackend::Dynarmic);
ui->unsafe_group->setVisible(accuracy == (u32)Settings::CpuAccuracy::Unsafe &&
backend == (u32)Settings::CpuBackend::Dynarmic);
}
void ConfigureCpu::ApplyConfiguration() {

View file

@ -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: Copyright 2020 yuzu Emulator Project
@ -9,8 +9,8 @@
#include <memory>
#include <vector>
#include <QWidget>
#include "yuzu/configuration/configuration_shared.h"
#include "qt_common/config/shared_translation.h"
#include "yuzu/configuration/configuration_shared.h"
class QComboBox;

View file

@ -13,10 +13,10 @@
#include "common/settings.h"
#include "core/core.h"
#include "core/crypto/key_manager.h"
#include "qt_common/config/uisettings.h"
#include "ui_configure_debug.h"
#include "yuzu/configuration/configure_debug.h"
#include "yuzu/debugger/console.h"
#include "qt_common/config/uisettings.h"
ConfigureDebug::ConfigureDebug(const Core::System& system_, QWidget* parent)
: QScrollArea(parent), ui{std::make_unique<Ui::ConfigureDebug>()}, system{system_} {
@ -60,7 +60,8 @@ void ConfigureDebug::SetConfiguration() {
// Immutable after starting
ui->homebrew_args_edit->setEnabled(runtime_lock);
ui->homebrew_args_edit->setText(QString::fromStdString(Settings::values.program_args.GetValue()));
ui->homebrew_args_edit->setText(
QString::fromStdString(Settings::values.program_args.GetValue()));
ui->toggle_console->setEnabled(runtime_lock);
ui->toggle_console->setChecked(UISettings::values.show_console.GetValue());
ui->fs_access_log->setEnabled(runtime_lock);
@ -84,7 +85,8 @@ void ConfigureDebug::SetConfiguration() {
ui->disable_macro_hle->setEnabled(runtime_lock);
ui->disable_macro_hle->setChecked(Settings::values.disable_macro_hle.GetValue());
ui->disable_loop_safety_checks->setEnabled(runtime_lock);
ui->disable_loop_safety_checks->setChecked(Settings::values.disable_shader_loop_safety_checks.GetValue());
ui->disable_loop_safety_checks->setChecked(
Settings::values.disable_shader_loop_safety_checks.GetValue());
ui->perform_vulkan_check->setChecked(Settings::values.perform_vulkan_check.GetValue());
ui->debug_knobs_spinbox->setValue(Settings::values.debug_knobs.GetValue());
#ifdef YUZU_USE_QT_WEB_ENGINE
@ -118,7 +120,8 @@ void ConfigureDebug::ApplyConfiguration() {
Settings::values.enable_nsight_aftermath = ui->enable_nsight_aftermath->isChecked();
Settings::values.dump_shaders = ui->dump_shaders->isChecked();
Settings::values.dump_macros = ui->dump_macros->isChecked();
Settings::values.disable_shader_loop_safety_checks = ui->disable_loop_safety_checks->isChecked();
Settings::values.disable_shader_loop_safety_checks =
ui->disable_loop_safety_checks->isChecked();
Settings::values.disable_macro_jit = ui->disable_macro_jit->isChecked();
Settings::values.disable_macro_hle = ui->disable_macro_hle->isChecked();
Settings::values.extended_logging = ui->extended_logging->isChecked();

View file

@ -9,6 +9,7 @@
#include "common/settings.h"
#include "common/settings_enums.h"
#include "core/core.h"
#include "qt_common/config/uisettings.h"
#include "ui_configure.h"
#include "vk_device_info.h"
#include "yuzu/configuration/configure_applets.h"
@ -30,15 +31,14 @@
#include "yuzu/configuration/configure_ui.h"
#include "yuzu/configuration/configure_web.h"
#include "yuzu/hotkeys.h"
#include "qt_common/config/uisettings.h"
ConfigureDialog::ConfigureDialog(QWidget* parent, HotkeyRegistry& registry_,
InputCommon::InputSubsystem* input_subsystem,
std::vector<VkDeviceInfo::Record>& vk_device_records,
Core::System& system_, bool enable_web_config)
: QDialog(parent), ui{std::make_unique<Ui::ConfigureDialog>()},
registry(registry_), system{system_}, builder{std::make_unique<ConfigurationShared::Builder>(
this, !system_.IsPoweredOn())},
: QDialog(parent), ui{std::make_unique<Ui::ConfigureDialog>()}, registry(registry_),
system{system_},
builder{std::make_unique<ConfigurationShared::Builder>(this, !system_.IsPoweredOn())},
applets_tab{std::make_unique<ConfigureApplets>(system_, nullptr, *builder, this)},
audio_tab{std::make_unique<ConfigureAudio>(system_, nullptr, *builder, this)},
cpu_tab{std::make_unique<ConfigureCpu>(system_, nullptr, *builder, this)},
@ -178,7 +178,8 @@ void ConfigureDialog::PopulateSelectionList() {
{system_tab.get(), profile_tab.get(), network_tab.get(), filesystem_tab.get(),
applets_tab.get()}},
{tr("CPU"), {cpu_tab.get()}},
{tr("Graphics"), {graphics_tab.get(), graphics_advanced_tab.get(), graphics_extensions_tab.get()}},
{tr("Graphics"),
{graphics_tab.get(), graphics_advanced_tab.get(), graphics_extensions_tab.get()}},
{tr("Audio"), {audio_tab.get()}},
{tr("Controls"), input_tab->GetSubTabs()}},
};

View file

@ -10,8 +10,8 @@
#include <vector>
#include <QDialog>
#include "configuration/shared_widget.h"
#include "yuzu/configuration/configuration_shared.h"
#include "qt_common/config/shared_translation.h"
#include "yuzu/configuration/configuration_shared.h"
#include "yuzu/vk_device_info.h"
namespace Core {

View file

@ -4,7 +4,6 @@
// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "yuzu/configuration/configure_filesystem.h"
#include <filesystem>
#include <QFileDialog>
#include <QMessageBox>
@ -12,10 +11,11 @@
#include "common/fs/fs.h"
#include "common/fs/path_util.h"
#include "common/settings.h"
#include "qt_common/config/uisettings.h"
#include "qt_common/qt_compat.h"
#include "qt_common/util/game.h"
#include "qt_common/config/uisettings.h"
#include "ui_configure_filesystem.h"
#include "yuzu/configuration/configure_filesystem.h"
ConfigureFilesystem::ConfigureFilesystem(QWidget* parent)
: QWidget(parent), ui(std::make_unique<Ui::ConfigureFilesystem>()) {
@ -26,8 +26,7 @@ ConfigureFilesystem::ConfigureFilesystem(QWidget* parent)
[this] { SetDirectory(DirectoryTarget::NAND, ui->nand_directory_edit); });
connect(ui->sdmc_directory_button, &QToolButton::pressed, this,
[this] { SetDirectory(DirectoryTarget::SD, ui->sdmc_directory_edit); });
connect(ui->save_directory_button, &QToolButton::pressed, this,
[this] { SetSaveDirectory(); });
connect(ui->save_directory_button, &QToolButton::pressed, this, [this] { SetSaveDirectory(); });
connect(ui->gamecard_path_button, &QToolButton::pressed, this,
[this] { SetDirectory(DirectoryTarget::Gamecard, ui->gamecard_path_edit); });
connect(ui->dump_path_button, &QToolButton::pressed, this,
@ -221,8 +220,8 @@ void ConfigureFilesystem::PromptSaveMigration(const QString& from_path, const QS
.arg(QString::fromStdString(dest_save_dir.string()));
}
QMessageBox::StandardButton reply = QMessageBox::question(
this, tr("Migrate Save Data"), message,
QMessageBox::StandardButton reply =
QMessageBox::question(this, tr("Migrate Save Data"), message,
QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
if (reply != QMessageBox::Yes) {
@ -249,14 +248,14 @@ void ConfigureFilesystem::PromptSaveMigration(const QString& from_path, const QS
progress.close();
if (ec) {
QMessageBox::warning(this, tr("Migration Failed"),
tr("Failed to migrate save data:\n%1")
.arg(QString::fromStdString(ec.message())));
QMessageBox::warning(
this, tr("Migration Failed"),
tr("Failed to migrate save data:\n%1").arg(QString::fromStdString(ec.message())));
return;
}
QMessageBox::StandardButton deleteReply = QMessageBox::question(
this, tr("Migration Complete"),
QMessageBox::StandardButton deleteReply =
QMessageBox::question(this, tr("Migration Complete"),
tr("Save data has been migrated successfully.\n\n"
"Would you like to delete the old save data?"),
QMessageBox::Yes | QMessageBox::No, QMessageBox::No);
@ -278,7 +277,6 @@ void ConfigureFilesystem::UpdateEnabledControls() {
!ui->gamecard_current_game->isChecked());
}
void ConfigureFilesystem::RetranslateUI() {
ui->retranslateUi(this);
}

View file

@ -13,11 +13,11 @@
#include <QMessageBox>
#include "common/settings.h"
#include "core/core.h"
#include "qt_common/config/uisettings.h"
#include "ui_configure_general.h"
#include "yuzu/configuration/configuration_shared.h"
#include "yuzu/configuration/configure_general.h"
#include "yuzu/configuration/shared_widget.h"
#include "qt_common/config/uisettings.h"
ConfigureGeneral::ConfigureGeneral(const Core::System& system_,
std::shared_ptr<std::vector<ConfigurationShared::Tab*>> group_,

View file

@ -39,12 +39,12 @@
#include "common/settings.h"
#include "common/settings_enums.h"
#include "core/core.h"
#include "qt_common/config/uisettings.h"
#include "qt_common/qt_common.h"
#include "ui_configure_graphics.h"
#include "yuzu/configuration/configuration_shared.h"
#include "yuzu/configuration/configure_graphics.h"
#include "yuzu/configuration/shared_widget.h"
#include "qt_common/qt_common.h"
#include "qt_common/config/uisettings.h"
#include "yuzu/vk_device_info.h"
static const std::vector<VkPresentModeKHR> default_present_modes{VK_PRESENT_MODE_IMMEDIATE_KHR,
@ -91,8 +91,7 @@ ConfigureGraphics::ConfigureGraphics(
: ConfigurationShared::Tab(group_, parent), ui{std::make_unique<Ui::ConfigureGraphics>()},
records{records_}, expose_compute_option{expose_compute_option_},
update_aspect_ratio{update_aspect_ratio_}, system{system_},
combobox_translations{builder.ComboboxTranslations()}
{
combobox_translations{builder.ComboboxTranslations()} {
vulkan_device = Settings::values.vulkan_device.GetValue();
RetrieveVulkanDevices();
@ -215,9 +214,9 @@ void ConfigureGraphics::PopulateVSyncModeSelection(bool use_setting) {
const Settings::VSyncMode global_vsync_mode = Settings::values.vsync_mode.GetValue(true);
vsync_restore_global_button->setEnabled(
((backend == Settings::RendererBackend::OpenGL_GLSL
|| backend == Settings::RendererBackend::OpenGL_GLASM
|| backend == Settings::RendererBackend::OpenGL_SPIRV) &&
((backend == Settings::RendererBackend::OpenGL_GLSL ||
backend == Settings::RendererBackend::OpenGL_GLASM ||
backend == Settings::RendererBackend::OpenGL_SPIRV) &&
(global_vsync_mode == Settings::VSyncMode::Immediate ||
global_vsync_mode == Settings::VSyncMode::Fifo)) ||
backend == Settings::RendererBackend::Vulkan);
@ -286,7 +285,9 @@ void ConfigureGraphics::Setup(const ConfigurationShared::Builder& builder) {
api_combobox = widget->combobox;
api_restore_global_button = widget->restore_button;
if (!Settings::IsConfiguringGlobal()) {
api_restore_global_button->connect(api_restore_global_button, &QAbstractButton::clicked, [this](bool) { UpdateAPILayout(); });
api_restore_global_button->connect(api_restore_global_button,
&QAbstractButton::clicked,
[this](bool) { UpdateAPILayout(); });
// Detach API's restore button and place it where we want
// Lets us put it on the side, and it will automatically scale if there's a
// second combobox (vulkan_device)
@ -324,7 +325,8 @@ void ConfigureGraphics::Setup(const ConfigurationShared::Builder& builder) {
UpdateVsyncSetting();
restore_button->setVisible(true);
};
widget->combobox->connect(widget->combobox, QOverload<int>::of(&QComboBox::activated),
widget->combobox->connect(widget->combobox,
QOverload<int>::of(&QComboBox::activated),
[set_non_global]() { set_non_global(); });
vsync_restore_global_button = restore_button;
}
@ -397,17 +399,19 @@ const QString ConfigureGraphics::TranslateVSyncMode(VkPresentModeKHR mode,
Settings::RendererBackend backend) const {
switch (mode) {
case VK_PRESENT_MODE_IMMEDIATE_KHR:
return (backend == Settings::RendererBackend::OpenGL_GLSL
|| backend == Settings::RendererBackend::OpenGL_GLASM
|| backend == Settings::RendererBackend::OpenGL_SPIRV)
? tr("Off") : QStringLiteral("Immediate (%1)").arg(tr("VSync Off"));
return (backend == Settings::RendererBackend::OpenGL_GLSL ||
backend == Settings::RendererBackend::OpenGL_GLASM ||
backend == Settings::RendererBackend::OpenGL_SPIRV)
? tr("Off")
: QStringLiteral("Immediate (%1)").arg(tr("VSync Off"));
case VK_PRESENT_MODE_MAILBOX_KHR:
return QStringLiteral("Mailbox (%1)").arg(tr("Recommended"));
case VK_PRESENT_MODE_FIFO_KHR:
return (backend == Settings::RendererBackend::OpenGL_GLSL
|| backend == Settings::RendererBackend::OpenGL_GLASM
|| backend == Settings::RendererBackend::OpenGL_SPIRV)
? tr("On") : QStringLiteral("FIFO (%1)").arg(tr("VSync On"));
return (backend == Settings::RendererBackend::OpenGL_GLSL ||
backend == Settings::RendererBackend::OpenGL_GLASM ||
backend == Settings::RendererBackend::OpenGL_SPIRV)
? tr("On")
: QStringLiteral("FIFO (%1)").arg(tr("VSync On"));
case VK_PRESENT_MODE_FIFO_RELAXED_KHR:
return QStringLiteral("FIFO Relaxed");
default:
@ -416,7 +420,9 @@ const QString ConfigureGraphics::TranslateVSyncMode(VkPresentModeKHR mode,
}
int ConfigureGraphics::FindIndex(u32 enumeration, int value) const {
for (u32 i = 0; enumeration < combobox_translations.size() && i < combobox_translations.at(enumeration).size(); i++)
for (u32 i = 0; enumeration < combobox_translations.size() &&
i < combobox_translations.at(enumeration).size();
i++)
if (combobox_translations.at(enumeration)[i].first == u32(value))
return i;
return -1;
@ -432,10 +438,14 @@ void ConfigureGraphics::ApplyConfiguration() {
Settings::values.vulkan_device.SetGlobal(true);
auto const index = Settings::EnumMetadata<Settings::RendererBackend>::Index();
if (Settings::IsConfiguringGlobal() || (!Settings::IsConfiguringGlobal() && api_restore_global_button->isEnabled())) {
auto backend = index >= combobox_translations.size() || size_t(api_combobox->currentIndex()) >= combobox_translations.at(index).size()
if (Settings::IsConfiguringGlobal() ||
(!Settings::IsConfiguringGlobal() && api_restore_global_button->isEnabled())) {
auto backend =
index >= combobox_translations.size() ||
size_t(api_combobox->currentIndex()) >= combobox_translations.at(index).size()
? Settings::values.renderer_backend.GetValue()
: Settings::RendererBackend(combobox_translations.at(index)[api_combobox->currentIndex()].first);
: Settings::RendererBackend(
combobox_translations.at(index)[api_combobox->currentIndex()].first);
switch (backend) {
case Settings::RendererBackend::Vulkan:
Settings::values.vulkan_device.SetGlobal(Settings::IsConfiguringGlobal());
@ -506,12 +516,15 @@ Settings::RendererBackend ConfigureGraphics::GetCurrentGraphicsBackend() const {
auto const index = Settings::EnumMetadata<Settings::RendererBackend>::Index();
if (!Settings::IsConfiguringGlobal() && !api_restore_global_button->isEnabled())
return Settings::values.renderer_backend.GetValue(true);
return index >= combobox_translations.size() || size_t(api_combobox->currentIndex()) >= combobox_translations.at(index).size()
return index >= combobox_translations.size() || size_t(api_combobox->currentIndex()) >=
combobox_translations.at(index).size()
? Settings::values.renderer_backend.GetValue()
: Settings::RendererBackend(combobox_translations.at(index).at(api_combobox->currentIndex()).first);
: Settings::RendererBackend(
combobox_translations.at(index).at(api_combobox->currentIndex()).first);
}();
if (selected_backend == Settings::RendererBackend::Vulkan && UISettings::values.has_broken_vulkan)
if (selected_backend == Settings::RendererBackend::Vulkan &&
UISettings::values.has_broken_vulkan)
return Settings::RendererBackend::OpenGL_GLSL;
return selected_backend;
}

View file

@ -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: Copyright 2020 yuzu Emulator Project
@ -9,10 +9,10 @@
#include <qnamespace.h>
#include "common/settings.h"
#include "core/core.h"
#include "qt_common/config/shared_translation.h"
#include "ui_configure_graphics_advanced.h"
#include "yuzu/configuration/configuration_shared.h"
#include "yuzu/configuration/configure_graphics_advanced.h"
#include "qt_common/config/shared_translation.h"
#include "yuzu/configuration/shared_widget.h"
ConfigureGraphicsAdvanced::ConfigureGraphicsAdvanced(

View file

@ -1,26 +1,27 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include <vector>
#include <QLabel>
#include <qnamespace.h>
#include <QCheckBox>
#include <QLabel>
#include <QSlider>
#include <qnamespace.h>
#include "common/settings.h"
#include "core/core.h"
#include "qt_common/config/shared_translation.h"
#include "ui_configure_graphics_extensions.h"
#include "yuzu/configuration/configuration_shared.h"
#include "yuzu/configuration/configure_graphics_extensions.h"
#include "qt_common/config/shared_translation.h"
#include "yuzu/configuration/shared_widget.h"
ConfigureGraphicsExtensions::ConfigureGraphicsExtensions(
const Core::System& system_, std::shared_ptr<std::vector<ConfigurationShared::Tab*>> group_,
const ConfigurationShared::Builder& builder, QWidget* parent)
: Tab(group_, parent), ui{std::make_unique<Ui::ConfigureGraphicsExtensions>()}, system{system_} {
: Tab(group_, parent), ui{std::make_unique<Ui::ConfigureGraphicsExtensions>()},
system{system_} {
ui->setupUi(this);
@ -44,8 +45,8 @@ void ConfigureGraphicsExtensions::Setup(const ConfigurationShared::Builder& buil
if (setting->Id() == Settings::values.sample_shading.Id()) {
// TODO(crueter): should support this natively perhaps?
return builder.BuildWidget(
setting, apply_funcs, ConfigurationShared::RequestType::Slider, true,
1.0f, nullptr, tr("%", "Sample Shading percentage (e.g. 50%)"));
setting, apply_funcs, ConfigurationShared::RequestType::Slider, true, 1.0f,
nullptr, tr("%", "Sample Shading percentage (e.g. 50%)"));
} else {
return builder.BuildWidget(setting, apply_funcs);
}
@ -64,7 +65,8 @@ void ConfigureGraphicsExtensions::Setup(const ConfigurationShared::Builder& buil
#ifdef __APPLE__
if (setting->Id() == Settings::values.dyna_state.Id()) {
widget->setEnabled(false);
widget->setToolTip(tr("Extended Dynamic State is disabled on macOS due to MoltenVK compatibility issues that cause black screens."));
widget->setToolTip(tr("Extended Dynamic State is disabled on macOS due to MoltenVK "
"compatibility issues that cause black screens."));
}
#endif
}

View file

@ -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: 2017 Citra Emulator Project
@ -13,10 +13,10 @@
#include "hid_core/hid_core.h"
#include "frontend_common/config.h"
#include "qt_common/config/uisettings.h"
#include "ui_configure_hotkeys.h"
#include "yuzu/configuration/configure_hotkeys.h"
#include "yuzu/hotkeys.h"
#include "qt_common/config/uisettings.h"
#include "yuzu/util/sequence_dialog/sequence_dialog.h"
constexpr int name_column = 0;

View file

@ -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: 2016 Citra Emulator Project
@ -15,10 +15,10 @@
#include "core/hle/service/sm/sm.h"
#include "hid_core/frontend/emulated_controller.h"
#include "hid_core/hid_core.h"
#include "qt_common/qt_compat.h"
#include "ui_configure_input.h"
#include "ui_configure_input_advanced.h"
#include "ui_configure_input_player.h"
#include "qt_common/qt_compat.h"
#include "yuzu/configuration/configure_camera.h"
#include "yuzu/configuration/configure_debug_controller.h"
#include "yuzu/configuration/configure_input.h"
@ -102,7 +102,7 @@ void ConfigureInput::Initialize(InputCommon::InputSubsystem* input_subsystem,
};
for (std::size_t i = 0; i < player_tabs.size(); ++i) {
QHBoxLayout *tab_layout = new QHBoxLayout(player_tabs[i]);
QHBoxLayout* tab_layout = new QHBoxLayout(player_tabs[i]);
tab_layout->addWidget(player_controllers[i]);
connect(player_controllers[i], &ConfigureInputPlayer::Connected, [this, i](bool checked) {
// Ensures that connecting a controller changes the number of players
@ -125,7 +125,8 @@ void ConfigureInput::Initialize(InputCommon::InputSubsystem* input_subsystem,
&ConfigureInput::UpdateAllInputDevices);
connect(player_controllers[i], &ConfigureInputPlayer::RefreshInputProfiles, this,
&ConfigureInput::UpdateAllInputProfiles, Qt::QueuedConnection);
connect(connected_controller_checkboxes[i], &QCheckBox::STATE_CHANGED, [this, i](int state) {
connect(connected_controller_checkboxes[i], &QCheckBox::STATE_CHANGED,
[this, i](int state) {
// Keep activated controllers synced with the "Connected Controllers" checkboxes
player_controllers[i]->ConnectPlayer(state == Qt::Checked);
});

View file

@ -9,8 +9,8 @@
#include "core/core.h"
#include "hid_core/frontend/emulated_controller.h"
#include "hid_core/hid_core.h"
#include "ui_configure_input_advanced.h"
#include "qt_common/qt_compat.h"
#include "ui_configure_input_advanced.h"
#include "yuzu/configuration/configure_input_advanced.h"
ConfigureInputAdvanced::ConfigureInputAdvanced(Core::HID::HIDCore& hid_core_, QWidget* parent)

View file

@ -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: 2022 yuzu Emulator Project
@ -10,9 +10,9 @@
#include <QWidget>
#include "qt_common/config/qt_config.h"
#include "ui_configure_input_per_game.h"
#include "yuzu/configuration/input_profiles.h"
#include "qt_common/config/qt_config.h"
class QComboBox;

View file

@ -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: 2016 Citra Emulator Project
@ -14,13 +14,13 @@
#include <QTimer>
#include "common/assert.h"
#include "common/param_package.h"
#include "qt_common/config/qt_config.h"
#include "hid_core/frontend/emulated_controller.h"
#include "hid_core/hid_core.h"
#include "hid_core/hid_types.h"
#include "input_common/drivers/keyboard.h"
#include "input_common/drivers/mouse.h"
#include "input_common/main.h"
#include "qt_common/config/qt_config.h"
#include "ui_configure_input_player.h"
#include "yuzu/bootmanager.h"
#include "yuzu/configuration/configure_input_player.h"
@ -294,11 +294,11 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
InputCommon::InputSubsystem* input_subsystem_,
InputProfiles* profiles_, Core::HID::HIDCore& hid_core_,
bool is_powered_on_, bool debug_)
: QWidget(parent),
ui(std::make_unique<Ui::ConfigureInputPlayer>()), player_index{player_index_}, debug{debug_},
is_powered_on{is_powered_on_}, input_subsystem{input_subsystem_}, profiles(profiles_),
timeout_timer(std::make_unique<QTimer>()),
poll_timer(std::make_unique<QTimer>()), bottom_row{bottom_row_}, hid_core{hid_core_} {
: QWidget(parent), ui(std::make_unique<Ui::ConfigureInputPlayer>()),
player_index{player_index_}, debug{debug_}, is_powered_on{is_powered_on_},
input_subsystem{input_subsystem_}, profiles(profiles_),
timeout_timer(std::make_unique<QTimer>()), poll_timer(std::make_unique<QTimer>()),
bottom_row{bottom_row_}, hid_core{hid_core_} {
if (player_index == 0) {
auto* emulated_controller_p1 =
hid_core.GetEmulatedController(Core::HID::NpadIdType::Player1);
@ -1215,10 +1215,8 @@ void ConfigureInputPlayer::UpdateControllerAvailableButtons() {
case Core::HID::NpadStyleIndex::Fullkey:
case Core::HID::NpadStyleIndex::Handheld:
layout_hidden = {
ui->buttonShoulderButtonsSLSRLeft,
ui->buttonShoulderButtonsSLSRRight,
ui->horizontalSpacerShoulderButtonsWidget2,
ui->horizontalSpacerShoulderButtonsWidget4,
ui->buttonShoulderButtonsSLSRLeft, ui->buttonShoulderButtonsSLSRRight,
ui->horizontalSpacerShoulderButtonsWidget2, ui->horizontalSpacerShoulderButtonsWidget4,
ui->buttonMiscButtonsScreenshotGroup,
};
break;

View file

@ -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: Copyright 2020 yuzu Emulator Project
@ -2432,7 +2432,8 @@ void PlayerControlPreview::DrawProJoystick(QPainter& p, const QPointF center, co
1.0 - std::sqrt((offset.x() * offset.x()) + (offset.y() * offset.y())) * 0.1f);
const float rotation =
((offset.x() == 0.f) ? std::atan(1.f) * 2.f : std::atan(offset.y() / offset.x())) * (180.f / (std::atan(1.f) * 4.f));
((offset.x() == 0.f) ? std::atan(1.f) * 2.f : std::atan(offset.y() / offset.x())) *
(180.f / (std::atan(1.f) * 4.f));
p.save();
p.translate(offset_center);

View file

@ -12,10 +12,7 @@
#include "yuzu/configuration/configure_network.h"
ConfigureNetwork::ConfigureNetwork(const Core::System& system_, QWidget* parent)
: QWidget(parent)
, ui(std::make_unique<Ui::ConfigureNetwork>())
, system{system_}
{
: QWidget(parent), ui(std::make_unique<Ui::ConfigureNetwork>()), system{system_} {
ui->setupUi(this);
for (const auto& iface : Network::GetAvailableNetworkInterfaces())
ui->network_interface->addItem(QString::fromStdString(iface.name));

View file

@ -29,28 +29,28 @@
#include "core/file_sys/xts_archive.h"
#include "core/loader/loader.h"
#include "frontend_common/config.h"
#include "qt_common/config/uisettings.h"
#include "ui_configure_per_game.h"
#include "yuzu/configuration/configuration_shared.h"
#include "yuzu/configuration/configure_applets.h"
#include "yuzu/configuration/configure_audio.h"
#include "yuzu/configuration/configure_cpu.h"
#include "yuzu/configuration/configure_graphics.h"
#include "yuzu/configuration/configure_graphics_advanced.h"
#include "yuzu/configuration/configure_graphics_extensions.h"
#include "yuzu/configuration/configure_input_per_game.h"
#include "yuzu/configuration/configure_network.h"
#include "yuzu/configuration/configure_per_game.h"
#include "yuzu/configuration/configure_per_game_addons.h"
#include "yuzu/configuration/configure_system.h"
#include "yuzu/configuration/configure_network.h"
#include "yuzu/configuration/configure_applets.h"
#include "qt_common/config/uisettings.h"
#include "yuzu/util/util.h"
#include "yuzu/vk_device_info.h"
ConfigurePerGame::ConfigurePerGame(QWidget* parent, u64 title_id_, const std::string& file_name,
std::vector<VkDeviceInfo::Record>& vk_device_records,
Core::System& system_)
: QDialog(parent),
ui(std::make_unique<Ui::ConfigurePerGame>()), title_id{title_id_}, system{system_},
: QDialog(parent), ui(std::make_unique<Ui::ConfigurePerGame>()), title_id{title_id_},
system{system_},
builder{std::make_unique<ConfigurationShared::Builder>(this, !system_.IsPoweredOn())},
tab_group{std::make_shared<std::vector<ConfigurationShared::Tab*>>()} {
const auto file_path = std::filesystem::path(Common::FS::ToU8String(file_name));

View file

@ -16,10 +16,10 @@
#include "configuration/shared_widget.h"
#include "core/file_sys/vfs/vfs_types.h"
#include "frontend_common/config.h"
#include "vk_device_info.h"
#include "yuzu/configuration/configuration_shared.h"
#include "qt_common/config/qt_config.h"
#include "qt_common/config/shared_translation.h"
#include "vk_device_info.h"
#include "yuzu/configuration/configuration_shared.h"
namespace Core {
class System;

View file

@ -80,7 +80,8 @@ ConfigurePerGameAddons::ConfigurePerGameAddons(Core::System& system_, QWidget* p
connect(ui->folder, &QAbstractButton::clicked, this, &ConfigurePerGameAddons::InstallModFolder);
connect(ui->zip, &QAbstractButton::clicked, this, &ConfigurePerGameAddons::InstallModZip);
connect(tree_view, &QTreeView::customContextMenuRequested, this, &ConfigurePerGameAddons::showContextMenu);
connect(tree_view, &QTreeView::customContextMenuRequested, this,
&ConfigurePerGameAddons::showContextMenu);
}
ConfigurePerGameAddons::~ConfigurePerGameAddons() = default;
@ -109,7 +110,8 @@ void ConfigurePerGameAddons::ApplyConfiguration() {
const auto disabled = item.front()->checkState() == Qt::Unchecked;
if (disabled) {
QVariant userData = item.front()->data(Qt::UserRole);
if (userData.isValid() && userData.canConvert<quint32>() && item.front()->text() == QStringLiteral("Update")) {
if (userData.isValid() && userData.canConvert<quint32>() &&
item.front()->text() == QStringLiteral("Update")) {
quint32 numeric_version = userData.toUInt();
disabled_addons.push_back(fmt::format("Update@{}", numeric_version));
} else {
@ -164,7 +166,7 @@ void ConfigurePerGameAddons::InstallMods(const QStringList& mods) {
}
}
void ConfigurePerGameAddons::InstallModPath(const QString& path, const QString &fallbackName) {
void ConfigurePerGameAddons::InstallModPath(const QString& path, const QString& fallbackName) {
const auto mods = QtCommon::Mod::GetModFolders(path, fallbackName);
if (mods.size() > 1) {
@ -203,8 +205,9 @@ void ConfigurePerGameAddons::InstallModZip() {
void ConfigurePerGameAddons::AddonDeleteRequested(QList<QModelIndex> selected) {
QList<QModelIndex> filtered;
for (const QModelIndex &index : selected) {
if (!index.data(PATCH_LOCATION).toString().isEmpty()) filtered << index;
for (const QModelIndex& index : selected) {
if (!index.data(PATCH_LOCATION).toString().isEmpty())
filtered << index;
}
if (filtered.empty()) {
@ -215,10 +218,9 @@ void ConfigurePerGameAddons::AddonDeleteRequested(QList<QModelIndex> selected) {
return;
}
const auto header = tr("You are about to delete the following installed mods:\n");
QString selected_str;
for (const QModelIndex &index : filtered) {
for (const QModelIndex& index : filtered) {
selected_str = selected_str % index.data().toString() % QStringLiteral("\n");
}
@ -231,9 +233,10 @@ void ConfigurePerGameAddons::AddonDeleteRequested(QList<QModelIndex> selected) {
QtCommon::Frontend::StandardButton::Yes |
QtCommon::Frontend::StandardButton::No);
if (choice == QtCommon::Frontend::StandardButton::No) return;
if (choice == QtCommon::Frontend::StandardButton::No)
return;
for (const QModelIndex &index : filtered) {
for (const QModelIndex& index : filtered) {
std::filesystem::remove_all(index.data(PATCH_LOCATION).toString().toStdString());
}
@ -252,17 +255,18 @@ void ConfigurePerGameAddons::showContextMenu(const QPoint& pos) {
auto selected = tree_view->selectionModel()->selectedRows();
if (index.isValid() && selected.empty()) {
QModelIndex idx = item_model->index(index.row(), 0);
if (idx.isValid()) selected << idx;
if (idx.isValid())
selected << idx;
}
if (selected.empty()) return;
if (selected.empty())
return;
QMenu menu(this);
QAction *remove = menu.addAction(tr("&Delete"));
connect(remove, &QAction::triggered, this, [this, selected]() {
AddonDeleteRequested(selected);
});
QAction* remove = menu.addAction(tr("&Delete"));
connect(remove, &QAction::triggered, this,
[this, selected]() { AddonDeleteRequested(selected); });
if (selected.length() == 1) {
auto loc = selected.at(0).data(PATCH_LOCATION).toString();
@ -333,9 +337,11 @@ void ConfigurePerGameAddons::LoadConfiguration() {
bool patch_disabled = false;
if (is_external_update) {
std::string disabled_key = fmt::format("Update@{}", patch.numeric_version);
patch_disabled = std::find(disabled.begin(), disabled.end(), disabled_key) != disabled.end();
patch_disabled =
std::find(disabled.begin(), disabled.end(), disabled_key) != disabled.end();
} else {
patch_disabled = std::find(disabled.begin(), disabled.end(), name.toStdString()) != disabled.end();
patch_disabled =
std::find(disabled.begin(), disabled.end(), name.toStdString()) != disabled.end();
}
bool should_enable = !patch_disabled;

View file

@ -32,10 +32,7 @@ class ConfigurePerGameAddons : public QWidget {
Q_OBJECT
public:
enum PatchData {
NUMERIC_VERSION = Qt::UserRole,
PATCH_LOCATION
};
enum PatchData { NUMERIC_VERSION = Qt::UserRole, PATCH_LOCATION };
explicit ConfigurePerGameAddons(Core::System& system_, QWidget* parent = nullptr);
~ConfigurePerGameAddons() override;
@ -48,7 +45,7 @@ public:
void SetTitleId(u64 id);
public slots:
void InstallMods(const QStringList &mods);
void InstallMods(const QStringList& mods);
void InstallModPath(const QString& path, const QString& fallbackName = {});
void InstallModFolder();

View file

@ -106,7 +106,8 @@ ConfigureProfileManager::ConfigureProfileManager(Core::System& system_, QWidget*
ui->scrollArea->setLayout(layout);
connect(tree_view, &QTreeView::customContextMenuRequested, this, &ConfigureProfileManager::showContextMenu);
connect(tree_view, &QTreeView::customContextMenuRequested, this,
&ConfigureProfileManager::showContextMenu);
connect(tree_view, &QTreeView::clicked, this, &ConfigureProfileManager::SelectUser);
@ -229,8 +230,7 @@ void ConfigureProfileManager::showContextMenu(const QPoint& pos) {
QAction* edit = menu.addAction(tr("&Edit"));
QAction* remove = menu.addAction(tr("&Delete"));
QAction* chosen =
menu.exec(tree_view->viewport()->mapToGlobal(pos));
QAction* chosen = menu.exec(tree_view->viewport()->mapToGlobal(pos));
if (!chosen)
return;
@ -250,7 +250,7 @@ void ConfigureProfileManager::SelectUser(const QModelIndex& index) {
}
void ConfigureProfileManager::AddUser() {
NewUserDialog *dialog = new NewUserDialog(this);
NewUserDialog* dialog = new NewUserDialog(this);
connect(dialog, &NewUserDialog::userAdded, this, [dialog, this](User user) {
auto uuid = user.uuid;
@ -285,11 +285,13 @@ void ConfigureProfileManager::EditUser() {
std::string username;
username.reserve(32);
std::ranges::copy_if(profile.username, std::back_inserter(username), [](u8 byte) { return byte != 0; });
std::ranges::copy_if(profile.username, std::back_inserter(username),
[](u8 byte) { return byte != 0; });
NewUserDialog *dialog = new NewUserDialog(uuid.value(), username, tr("Edit User"), this);
NewUserDialog* dialog = new NewUserDialog(uuid.value(), username, tr("Edit User"), this);
connect(dialog, &NewUserDialog::userAdded, this, [dialog, profile, user_idx, uuid, this](User user) mutable {
connect(dialog, &NewUserDialog::userAdded, this,
[dialog, profile, user_idx, uuid, this](User user) mutable {
// TODO: MOVE UUID
// auto new_uuid = user.uuid;
auto new_username = user.username;
@ -306,8 +308,8 @@ void ConfigureProfileManager::EditUser() {
item_model->setItem(
user_idx, 0,
new QStandardItem{pixmap,
FormatUserEntryText(QString::fromStdString(username_std), uuid_val)});
new QStandardItem{pixmap, FormatUserEntryText(
QString::fromStdString(username_std), uuid_val)});
saveImage(pixmap, uuid_val);
UpdateCurrentUser();

View file

@ -47,8 +47,7 @@ public:
explicit ConfigureProfileManagerDeleteDialog(QWidget* parent);
~ConfigureProfileManagerDeleteDialog();
void SetInfo(const QString& username, const Common::UUID& uuid,
int index);
void SetInfo(const QString& username, const Common::UUID& uuid, int index);
signals:
void deleteUser(int index);
@ -71,7 +70,7 @@ public:
private slots:
void saveImage(QPixmap pixmap, Common::UUID uuid);
void showContextMenu(const QPoint &pos);
void showContextMenu(const QPoint& pos);
void DeleteUser(const int index);
private:

View file

@ -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: Copyright 2022 yuzu Emulator Project
@ -11,12 +11,12 @@
#include <QTimer>
#include <fmt/ranges.h>
#include "qt_common/config/qt_config.h"
#include "hid_core/frontend/emulated_controller.h"
#include "hid_core/hid_core.h"
#include "input_common/drivers/keyboard.h"
#include "input_common/drivers/mouse.h"
#include "input_common/main.h"
#include "qt_common/config/qt_config.h"
#include "ui_configure_ringcon.h"
#include "yuzu/bootmanager.h"
#include "yuzu/configuration/configure_ringcon.h"

View file

@ -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: 2016 Citra Emulator Project
@ -19,8 +19,8 @@
#include "common/settings.h"
#include "core/core.h"
#include "ui_configure_system.h"
#include "qt_common/qt_compat.h"
#include "ui_configure_system.h"
#include "yuzu/configuration/configuration_shared.h"
#include "yuzu/configuration/configure_system.h"
#include "yuzu/configuration/shared_widget.h"
@ -87,7 +87,8 @@ ConfigureSystem::ConfigureSystem(Core::System& system_,
connect(combo_language, qOverload<int>(&QComboBox::currentIndexChanged), this, locale_check);
connect(combo_region, qOverload<int>(&QComboBox::currentIndexChanged), this, locale_check);
connect(checkbox_rtc, qOverload<CHECKSTATE_TYPE>(&QCheckBox::STATE_CHANGED), this, update_rtc_date);
connect(checkbox_rtc, qOverload<CHECKSTATE_TYPE>(&QCheckBox::STATE_CHANGED), this,
update_rtc_date);
connect(date_rtc_offset, qOverload<int>(&QSpinBox::valueChanged), this, update_rtc_date);
connect(date_rtc, &QDateTimeEdit::dateTimeChanged, this, update_date_offset);

View file

@ -9,9 +9,9 @@
#include "common/fs/fs.h"
#include "common/fs/path_util.h"
#include "common/settings.h"
#include "qt_common/config/uisettings.h"
#include "ui_configure_tas.h"
#include "yuzu/configuration/configure_tas.h"
#include "qt_common/config/uisettings.h"
ConfigureTasDialog::ConfigureTasDialog(QWidget* parent)
: QDialog(parent), ui(std::make_unique<Ui::ConfigureTas>()) {
@ -35,7 +35,8 @@ void ConfigureTasDialog::LoadConfiguration() {
ui->tas_enable->setChecked(Settings::values.tas_enable.GetValue());
ui->tas_loop_script->setChecked(Settings::values.tas_loop.GetValue());
ui->tas_pause_on_load->setChecked(Settings::values.pause_tas_on_load.GetValue());
ui->tas_show_recording_dialog->setChecked(Settings::values.tas_show_recording_dialog.GetValue());
ui->tas_show_recording_dialog->setChecked(
Settings::values.tas_show_recording_dialog.GetValue());
}
void ConfigureTasDialog::ApplyConfiguration() {

View file

@ -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
#include <QInputDialog>
@ -548,9 +548,8 @@ bool TouchScreenPreview::eventFilter(QObject* obj, QEvent* event) {
}
const auto mouse_event = static_cast<QMouseEvent*>(event);
if (!drag_state.active) {
drag_state.active =
(mouse_event->globalPosition().toPoint() - drag_state.start_pos).manhattanLength() >=
QApplication::startDragDistance();
drag_state.active = (mouse_event->globalPosition().toPoint() - drag_state.start_pos)
.manhattanLength() >= QApplication::startDragDistance();
if (!drag_state.active) {
break;
}

View file

@ -26,8 +26,8 @@
#include "core/frontend/framebuffer_layout.h"
#include "ui_configure_ui.h"
#include "qt_common/qt_compat.h"
#include "qt_common/config/uisettings.h"
#include "qt_common/qt_compat.h"
namespace {

View file

@ -1,12 +1,12 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: 2017 Citra Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "yuzu/configuration/configure_web.h"
#include <QIcon>
#include <QMessageBox>
#include "yuzu/configuration/configure_web.h"
#if QT_VERSION_MAJOR >= 6
#include <QRegularExpressionValidator>
@ -16,28 +16,25 @@
#include <QtConcurrentRun>
#include "common/settings.h"
#include "ui_configure_web.h"
#include "qt_common/config/uisettings.h"
#include "ui_configure_web.h"
ConfigureWeb::ConfigureWeb(QWidget* parent)
: QWidget(parent)
, ui(std::make_unique<Ui::ConfigureWeb>())
, m_rng{QRandomGenerator::system()}
{
: QWidget(parent), ui(std::make_unique<Ui::ConfigureWeb>()), m_rng{QRandomGenerator::system()} {
ui->setupUi(this);
QString user_regex = QStringLiteral(".{4,20}");
QString token_regex = QStringLiteral("[a-z]{48}");
#if QT_VERSION_MAJOR >= 6
QRegularExpressionValidator *username_validator = new QRegularExpressionValidator(this);
QRegularExpressionValidator *token_validator = new QRegularExpressionValidator(this);
QRegularExpressionValidator* username_validator = new QRegularExpressionValidator(this);
QRegularExpressionValidator* token_validator = new QRegularExpressionValidator(this);
username_validator->setRegularExpression(QRegularExpression(user_regex));
token_validator->setRegularExpression(QRegularExpression(token_regex));
#else
QRegExpValidator *username_validator = new QRegExpValidator(this);
QRegExpValidator *token_validator = new QRegExpValidator(this);
QRegExpValidator* username_validator = new QRegExpValidator(this);
QRegExpValidator* token_validator = new QRegExpValidator(this);
username_validator->setRegExp(QRegExp(user_regex));
token_validator->setRegExp(QRegExp(token_regex));
@ -121,7 +118,8 @@ void ConfigureWeb::VerifyLogin() {
ui->label_token_verified->setToolTip(tr("All Good", "Tooltip"));
} else {
ui->label_token_verified->setPixmap(failed);
ui->label_token_verified->setToolTip(tr("Must be 48 characters, and lowercase a-z", "Tooltip"));
ui->label_token_verified->setToolTip(
tr("Must be 48 characters, and lowercase a-z", "Tooltip"));
}
}

View file

@ -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: 2017 Citra Emulator Project
@ -8,8 +8,8 @@
#include <QRandomGenerator>
#include <QWidget>
#include <memory>
#include <QWidget>
namespace Ui {
class ConfigureWeb;
@ -32,7 +32,7 @@ private:
void SetConfiguration();
std::unique_ptr<Ui::ConfigureWeb> ui;
QRandomGenerator *m_rng;
QRandomGenerator* m_rng;
private slots:
void GenerateToken();

View file

@ -45,8 +45,8 @@
#include "common/logging/log.h"
#include "common/settings.h"
#include "common/settings_common.h"
#include "qt_common/qt_compat.h"
#include "qt_common/config/shared_translation.h"
#include "qt_common/qt_compat.h"
namespace ConfigurationShared {
@ -413,8 +413,8 @@ QWidget* Widget::CreateDoubleSpinBox(const QString& given_suffix,
};
if (!Settings::IsConfiguringGlobal()) {
double_spinbox->connect(double_spinbox, QOverload<double>::of(&QDoubleSpinBox::valueChanged),
[this, touch]() {
double_spinbox->connect(
double_spinbox, QOverload<double>::of(&QDoubleSpinBox::valueChanged), [this, touch]() {
if (double_spinbox->value() !=
std::strtod(setting.ToStringGlobal().c_str(), nullptr)) {
touch();
@ -570,7 +570,8 @@ void Widget::SetupComponent(const QString& label, std::function<void()>& load_fu
}
if (require_checkbox) {
QWidget* lhs = CreateCheckBox(other_setting, label, checkbox_serializer, checkbox_restore_func, touch);
QWidget* lhs =
CreateCheckBox(other_setting, label, checkbox_serializer, checkbox_restore_func, touch);
layout->addWidget(lhs, 1);
} else if (type_id != "bool") {
QLabel* qt_label = CreateLabel(label);
@ -766,8 +767,8 @@ Widget::Widget(Settings::BasicSetting* setting_, const TranslationMap& translati
Builder::Builder(QWidget* parent_, bool runtime_lock_)
: translations{InitializeTranslations(parent_)},
combobox_translations{ComboboxEnumeration(parent_)}, parent{parent_}, runtime_lock{
runtime_lock_} {}
combobox_translations{ComboboxEnumeration(parent_)}, parent{parent_},
runtime_lock{runtime_lock_} {}
Builder::~Builder() = default;

View file

@ -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: Copyright 2023 yuzu Emulator Project
@ -10,10 +10,10 @@
#include <memory>
#include <string>
#include <vector>
#include <QObject>
#include <QString>
#include <QStringLiteral>
#include <QWidget>
#include <QObject>
#include <qobjectdefs.h>
#include "qt_common/config/shared_translation.h"

View file

@ -20,15 +20,15 @@ struct User {
QPixmap pixmap;
};
class NewUserDialog : public QDialog
{
class NewUserDialog : public QDialog {
Q_OBJECT
Q_PROPERTY(bool isDefaultAvatar READ isDefaultAvatar WRITE setIsDefaultAvatar NOTIFY
isDefaultAvatarChanged FINAL)
public:
explicit NewUserDialog(QWidget *parent = nullptr);
explicit NewUserDialog(Common::UUID uuid, const std::string &username, const QString &title, QWidget *parent = nullptr);
explicit NewUserDialog(QWidget* parent = nullptr);
explicit NewUserDialog(Common::UUID uuid, const std::string& username, const QString& title,
QWidget* parent = nullptr);
~NewUserDialog();
bool isDefaultAvatar() const;
@ -39,8 +39,8 @@ public:
static QPixmap DefaultAvatar();
private:
Ui::NewUserDialog *ui;
QGraphicsScene *m_scene;
Ui::NewUserDialog* ui;
QGraphicsScene* m_scene;
QPixmap m_pixmap;
ProfileAvatarDialog* avatar_dialog;
@ -48,12 +48,12 @@ private:
bool m_isDefaultAvatar = true;
bool m_editing = false;
void setup(Common::UUID uuid, const std::string &username, const QString &title);
void setup(Common::UUID uuid, const std::string& username, const QString& title);
bool LoadAvatarData();
std::vector<uint8_t> DecompressYaz0(const FileSys::VirtualFile& file);
public slots:
void setImage(const QPixmap &pixmap);
void setImage(const QPixmap& pixmap);
void selectImage();
void setAvatar();

View file

@ -1,10 +1,10 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#include "data_dialog.h"
#include "frontend_common/data_manager.h"
#include "qt_common/util/content.h"
#include "qt_common/qt_string_lookup.h"
#include "qt_common/util/content.h"
#include "ui_data_dialog.h"
#include "util/util.h"
@ -18,18 +18,14 @@
#include <applets/qt_profile_select.h>
DataDialog::DataDialog(QWidget *parent)
: QDialog(parent)
, ui(std::make_unique<Ui::DataDialog>())
{
DataDialog::DataDialog(QWidget* parent) : QDialog(parent), ui(std::make_unique<Ui::DataDialog>()) {
ui->setupUi(this);
// TODO: Should we make this a single widget that pulls data from a model?
#define WIDGET(label, name) \
ui->page->addWidget(new DataWidget(FrontendCommon::DataManager::DataDir::name, \
QtCommon::StringLookup::DataManager##name##Tooltip, \
QStringLiteral(#name), \
this)); \
QStringLiteral(#name), this)); \
ui->labels->addItem(label);
WIDGET(tr("Shaders"), Shaders)
@ -53,14 +49,10 @@ DataDialog::DataDialog(QWidget *parent)
DataDialog::~DataDialog() = default;
DataWidget::DataWidget(FrontendCommon::DataManager::DataDir data_dir,
QtCommon::StringLookup::StringKey tooltip,
const QString &exportName,
QWidget *parent)
: QWidget(parent)
, ui(std::make_unique<Ui::DataWidget>())
, m_dir(data_dir)
, m_exportName(exportName)
{
QtCommon::StringLookup::StringKey tooltip, const QString& exportName,
QWidget* parent)
: QWidget(parent), ui(std::make_unique<Ui::DataWidget>()), m_dir(data_dir),
m_exportName(exportName) {
ui->setupUi(this);
ui->tooltip->setText(QtCommon::StringLookup::Lookup(tooltip));
@ -78,28 +70,24 @@ DataWidget::DataWidget(FrontendCommon::DataManager::DataDir data_dir,
scan();
}
void DataWidget::clear()
{
void DataWidget::clear() {
std::string user_id = selectProfile();
QtCommon::Content::ClearDataDir(m_dir, user_id);
scan();
}
void DataWidget::open()
{
void DataWidget::open() {
std::string user_id = selectProfile();
QDesktopServices::openUrl(QUrl::fromLocalFile(
QString::fromStdString(FrontendCommon::DataManager::GetDataDirString(m_dir, user_id))));
}
void DataWidget::upload()
{
void DataWidget::upload() {
std::string user_id = selectProfile();
QtCommon::Content::ExportDataDir(m_dir, user_id, m_exportName);
}
void DataWidget::download()
{
void DataWidget::download() {
std::string user_id = selectProfile();
QtCommon::Content::ImportDataDir(m_dir, user_id, std::bind(&DataWidget::scan, this));
}
@ -107,7 +95,7 @@ void DataWidget::download()
void DataWidget::scan() {
ui->size->setText(tr("Calculating..."));
QFutureWatcher<u64> *watcher = new QFutureWatcher<u64>(this);
QFutureWatcher<u64>* watcher = new QFutureWatcher<u64>(this);
connect(watcher, &QFutureWatcher<u64>::finished, this, [=, this]() {
u64 size = watcher->result();
@ -120,8 +108,7 @@ void DataWidget::scan() {
QtConcurrent::run([this]() { return FrontendCommon::DataManager::DataDirSize(m_dir); }));
}
std::string DataWidget::selectProfile()
{
std::string DataWidget::selectProfile() {
std::string user_id{};
if (m_dir == FrontendCommon::DataManager::DataDir::Saves) {
user_id = GetProfileIDString();

View file

@ -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
#ifndef DATA_DIALOG_H
@ -14,26 +14,23 @@ namespace Ui {
class DataDialog;
}
class DataDialog : public QDialog
{
class DataDialog : public QDialog {
Q_OBJECT
public:
explicit DataDialog(QWidget *parent = nullptr);
explicit DataDialog(QWidget* parent = nullptr);
~DataDialog();
private:
std::unique_ptr<Ui::DataDialog> ui;
};
class DataWidget : public QWidget
{
class DataWidget : public QWidget {
Q_OBJECT
public:
explicit DataWidget(FrontendCommon::DataManager::DataDir data_dir,
QtCommon::StringLookup::StringKey tooltip,
const QString &exportName,
QWidget *parent = nullptr);
QtCommon::StringLookup::StringKey tooltip, const QString& exportName,
QWidget* parent = nullptr);
public slots:
void clear();

View file

@ -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: Copyright 2018 yuzu Emulator Project
@ -11,8 +11,8 @@
#endif
#include "common/logging/backend.h"
#include "yuzu/debugger/console.h"
#include "qt_common/config/uisettings.h"
#include "yuzu/debugger/console.h"
namespace Debugger {
void ToggleConsole() {

View file

@ -1,24 +1,21 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#include "yuzu/deps_dialog.h"
#include <QAbstractTextDocumentLayout>
#include <QDesktopServices>
#include <QIcon>
#include <QPainter>
#include <QTableWidget>
#include <QTextEdit>
#include <fmt/ranges.h>
#include "dep_hashes.h"
#include "ui_deps_dialog.h"
#include <fmt/ranges.h>
#include "yuzu/deps_dialog.h"
DepsDialog::DepsDialog(QWidget* parent)
: QDialog(parent)
, ui{std::make_unique<Ui::DepsDialog>()}
{
DepsDialog::DepsDialog(QWidget* parent) : QDialog(parent), ui{std::make_unique<Ui::DepsDialog>()} {
ui->setupUi(this);
constexpr int rows = (int) Common::dep_hashes.size();
constexpr int rows = (int)Common::dep_hashes.size();
ui->tableDeps->setRowCount(rows);
QStringList labels;
@ -36,8 +33,8 @@ DepsDialog::DepsDialog(QWidget* parent)
std::string dependency = fmt::format("<a href=\"{}\">{}</a>", url, name);
QTableWidgetItem *nameItem = new QTableWidgetItem(QString::fromStdString(dependency));
QTableWidgetItem *shaItem = new QTableWidgetItem(QString::fromStdString(sha));
QTableWidgetItem* nameItem = new QTableWidgetItem(QString::fromStdString(dependency));
QTableWidgetItem* shaItem = new QTableWidgetItem(QString::fromStdString(sha));
ui->tableDeps->setItem(i, 0, nameItem);
ui->tableDeps->setItem(i, 1, shaItem);
@ -48,14 +45,10 @@ DepsDialog::DepsDialog(QWidget* parent)
DepsDialog::~DepsDialog() = default;
LinkItemDelegate::LinkItemDelegate(QObject *parent)
: QStyledItemDelegate(parent)
{}
LinkItemDelegate::LinkItemDelegate(QObject* parent) : QStyledItemDelegate(parent) {}
void LinkItemDelegate::paint(QPainter *painter,
const QStyleOptionViewItem &option,
const QModelIndex &index) const
{
void LinkItemDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option,
const QModelIndex& index) const {
auto options = option;
initStyleOption(&options, index);
@ -71,8 +64,8 @@ void LinkItemDelegate::paint(QPainter *painter,
painter->restore();
}
QSize LinkItemDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
{
QSize LinkItemDelegate::sizeHint(const QStyleOptionViewItem& option,
const QModelIndex& index) const {
QStyleOptionViewItem options = option;
initStyleOption(&options, index);
@ -82,13 +75,10 @@ QSize LinkItemDelegate::sizeHint(const QStyleOptionViewItem &option, const QMode
return QSize(doc.idealWidth(), doc.size().height());
}
bool LinkItemDelegate::editorEvent(QEvent *event,
QAbstractItemModel *model,
const QStyleOptionViewItem &option,
const QModelIndex &index)
{
bool LinkItemDelegate::editorEvent(QEvent* event, QAbstractItemModel* model,
const QStyleOptionViewItem& option, const QModelIndex& index) {
if (event->type() == QEvent::MouseButtonRelease) {
QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event);
QMouseEvent* mouseEvent = static_cast<QMouseEvent*>(event);
if (mouseEvent->button() == Qt::LeftButton) {
QString html = index.data(Qt::DisplayRole).toString();
QTextDocument doc;
@ -96,7 +86,7 @@ bool LinkItemDelegate::editorEvent(QEvent *event,
doc.setTextWidth(option.rect.width());
// this is kinda silly but it werks
QAbstractTextDocumentLayout *layout = doc.documentLayout();
QAbstractTextDocumentLayout* layout = doc.documentLayout();
QPoint pos = mouseEvent->pos() - option.rect.topLeft();
int charPos = layout->hitTest(pos, Qt::ExactHit);

View file

@ -1,41 +1,38 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#pragma once
#include <memory>
#include <QDialog>
#include <QStyledItemDelegate>
#include <QTableView>
#include <memory>
namespace Ui { class DepsDialog; }
namespace Ui {
class DepsDialog;
}
class DepsDialog : public QDialog
{
class DepsDialog : public QDialog {
Q_OBJECT
public:
explicit DepsDialog(QWidget *parent);
explicit DepsDialog(QWidget* parent);
~DepsDialog() override;
private:
std::unique_ptr<Ui::DepsDialog> ui;
};
class LinkItemDelegate : public QStyledItemDelegate
{
class LinkItemDelegate : public QStyledItemDelegate {
Q_OBJECT
public:
explicit LinkItemDelegate(QObject *parent = 0);
explicit LinkItemDelegate(QObject* parent = 0);
protected:
void paint(QPainter *painter,
const QStyleOptionViewItem &option,
const QModelIndex &index) const override;
QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const override;
bool editorEvent(QEvent *event,
QAbstractItemModel *model,
const QStyleOptionViewItem &option,
const QModelIndex &index) override;
void paint(QPainter* painter, const QStyleOptionViewItem& option,
const QModelIndex& index) const override;
QSize sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const override;
bool editorEvent(QEvent* event, QAbstractItemModel* model, const QStyleOptionViewItem& option,
const QModelIndex& index) override;
};

View file

@ -73,9 +73,7 @@ void GameCard::paint(QPainter* painter, const QStyleOptionViewItem& option,
painter->restore();
} else {
// if there is no icon just draw a blank rect
iconRect = QRect(cardRect.left() + padding,
cardRect.top() + padding,
_iconsize, _iconsize);
iconRect = QRect(cardRect.left() + padding, cardRect.top() + padding, _iconsize, _iconsize);
}
if (UISettings::values.show_game_name.GetValue()) {

View file

@ -14,12 +14,10 @@ class GameCard : public QStyledItemDelegate {
public:
explicit GameCard(QObject* parent = nullptr);
void paint(QPainter *painter,
const QStyleOptionViewItem &option,
const QModelIndex &index) const override;
void paint(QPainter* painter, const QStyleOptionViewItem& option,
const QModelIndex& index) const override;
QSize sizeHint(const QStyleOptionViewItem &option,
const QModelIndex &index) const override;
QSize sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const override;
void setSize(const QSize& newSize, const int padding);
private:

View file

@ -218,11 +218,13 @@ void GameList::OnTextChanged(const QString& new_text) {
for (int i = 0; i < row_count; ++i) {
QStandardItem* item = item_model->item(i, 0);
if (!item) continue;
if (!item)
continue;
children_total++;
const QString file_path = item->data(GameListItemPath::FullPathRole).toString().toLower();
const QString file_path =
item->data(GameListItemPath::FullPathRole).toString().toLower();
const QString file_title = item->data(GameListItemPath::TitleRole).toString().toLower();
const QString file_name = file_path.mid(file_path.lastIndexOf(QLatin1Char{'/'}) + 1) +
QLatin1Char{' '} + file_title;
@ -236,7 +238,8 @@ void GameList::OnTextChanged(const QString& new_text) {
}
search_field->setFilterResult(result_count, children_total);
} else if (edit_filter_text.isEmpty()) {
hide(0, UISettings::values.favorited_ids.size() == 0, item_model->invisibleRootItem()->index());
hide(0, UISettings::values.favorited_ids.size() == 0,
item_model->invisibleRootItem()->index());
for (int i = 1; i < item_model->rowCount() - 1; ++i) {
folder = item_model->item(i, 0);
const QModelIndex folder_index = folder->index();
@ -362,7 +365,8 @@ GameList::GameList(FileSys::VirtualFilesystem vfs_, FileSys::ManualContentProvid
external_watcher = new QFileSystemWatcher(this);
ResetExternalWatcher();
connect(external_watcher, &QFileSystemWatcher::directoryChanged, this, &GameList::RefreshExternalContent);
connect(external_watcher, &QFileSystemWatcher::directoryChanged, this,
&GameList::RefreshExternalContent);
this->main_window = parent;
layout = new QVBoxLayout;
@ -471,7 +475,7 @@ bool GameList::IsTreeMode() {
}
void GameList::ResetViewMode() {
auto &setting = UISettings::values.game_list_mode;
auto& setting = UISettings::values.game_list_mode;
bool newTreeMode = false;
switch (setting.GetValue()) {
@ -678,7 +682,7 @@ void GameList::PopupContextMenu(const QPoint& menu_location) {
return;
QMenu blank_menu;
QAction *addGameDirAction = blank_menu.addAction(tr("&Add New Game Directory"));
QAction* addGameDirAction = blank_menu.addAction(tr("&Add New Game Directory"));
connect(addGameDirAction, &QAction::triggered, this, &GameList::AddDirectory);
blank_menu.exec(m_currentView->viewport()->mapToGlobal(menu_location));
@ -1113,8 +1117,7 @@ const QStringList GameList::supported_file_extensions = {
QStringLiteral("nso"), QStringLiteral("nro"), QStringLiteral("nca"),
QStringLiteral("xci"), QStringLiteral("nsp"), QStringLiteral("kip")};
void GameList::RefreshGameDirectory()
{
void GameList::RefreshGameDirectory() {
// Reset the externals watcher whenever the game list is reloaded,
// primarily ensures that new titles and external dirs are caught.
ResetExternalWatcher();
@ -1142,7 +1145,7 @@ void GameList::ResetExternalWatcher() {
external_watcher->removePaths(watch_dirs);
}
for (const std::string &dir : Settings::values.external_content_dirs) {
for (const std::string& dir : Settings::values.external_content_dirs) {
external_watcher->addPath(QString::fromStdString(dir));
}
}
@ -1286,8 +1289,8 @@ bool GameList::eventFilter(QObject* obj, QEvent* event) {
horizontal_scroll_target = m_currentView->horizontalScrollBar()->value();
horizontal_scroll_target -= deltaX;
horizontal_scroll_target =
qBound(0, horizontal_scroll_target, m_currentView->horizontalScrollBar()->maximum());
horizontal_scroll_target = qBound(0, horizontal_scroll_target,
m_currentView->horizontalScrollBar()->maximum());
horizontal_scroll->stop();
horizontal_scroll->setStartValue(m_currentView->horizontalScrollBar()->value());

View file

@ -21,10 +21,10 @@
#include "common/common_types.h"
#include "core/core.h"
#include "frontend_common/play_time_manager.h"
#include "qt_common/config/uisettings.h"
#include "qt_common/util/game.h"
#include "yuzu/compatibility_list.h"
#include "frontend_common/play_time_manager.h"
class QVariantAnimation;
@ -124,7 +124,7 @@ signals:
void NavigateToGamedbEntryRequested(u64 program_id,
const CompatibilityList& compatibility_list);
void OpenPerGameGeneralRequested(const std::string& file);
void LinkToRyujinxRequested(const u64 &program_id);
void LinkToRyujinxRequested(const u64& program_id);
void OpenDirectory(const QString& directory);
void AddDirectory();
void ShowList(bool show);
@ -170,8 +170,8 @@ private:
QVBoxLayout* layout = nullptr;
QTreeView* tree_view = nullptr;
QListView *list_view = nullptr;
GameCard *m_gameCard = nullptr;
QListView* list_view = nullptr;
GameCard* m_gameCard = nullptr;
QStandardItemModel* item_model = nullptr;
std::unique_ptr<GameListWorker> current_worker;
@ -194,7 +194,7 @@ private:
Core::System& system;
bool m_isTreeMode = true;
QAbstractItemView *m_currentView = tree_view;
QAbstractItemView* m_currentView = tree_view;
};
class GameListPlaceholder : public QWidget {

View file

@ -14,10 +14,10 @@
#include <QCoreApplication>
#include <QFileInfo>
#include <QObject>
#include <QRegularExpression>
#include <QStandardItem>
#include <QString>
#include <QWidget>
#include <QRegularExpression>
#include "common/common_types.h"
#include "common/logging/log.h"
@ -77,7 +77,7 @@ public:
GameListItemPath() = default;
GameListItemPath(const QString& game_path, const std::vector<u8>& picture_data,
const QString& game_name, const QString& game_type, u64 program_id,
u64 play_time, const QString &patch_versions) {
u64 play_time, const QString& patch_versions) {
setData(type(), TypeRole);
setData(game_path, FullPathRole);
setData(game_name, TitleRole);
@ -85,14 +85,15 @@ public:
setData(game_type, FileTypeRole);
const auto readable_play_time =
play_time > 0
? QObject::tr("Play Time: %1").arg(QString::fromStdString(PlayTime::PlayTimeManager::GetReadablePlayTime(play_time)))
play_time > 0 ? QObject::tr("Play Time: %1")
.arg(QString::fromStdString(
PlayTime::PlayTimeManager::GetReadablePlayTime(play_time)))
: QObject::tr("Never Played");
const auto enabled_update = [patch_versions]() -> QString {
const QStringList lines = patch_versions.split(QLatin1Char('\n'));
const QRegularExpression regex{QStringLiteral(R"(^Update \(([0-9\.]+)\))")};
for (const QString &line : std::as_const(lines)) {
for (const QString& line : std::as_const(lines)) {
const auto match = regex.match(line);
if (match.hasMatch() && match.hasCaptured(1))
return QObject::tr("Version: %1").arg(match.captured(1));
@ -100,9 +101,7 @@ public:
return QObject::tr("Version: 1.0.0");
}();
const auto tooltip = QStringLiteral("%1\n%2").arg(
readable_play_time,
enabled_update);
const auto tooltip = QStringLiteral("%1\n%2").arg(readable_play_time, enabled_update);
setData(tooltip, Qt::ToolTipRole);
@ -163,7 +162,6 @@ public:
default:
break;
}
}
return GameListItem::data(role);

View file

@ -30,11 +30,11 @@
#include "core/file_sys/romfs.h"
#include "core/file_sys/submission_package.h"
#include "core/loader/loader.h"
#include "qt_common/config/uisettings.h"
#include "yuzu/compatibility_list.h"
#include "yuzu/game/game_list.h"
#include "yuzu/game/game_list_p.h"
#include "yuzu/game/game_list_worker.h"
#include "qt_common/config/uisettings.h"
namespace {
@ -198,24 +198,22 @@ QString FormatPatchNameVersions(const FileSys::PatchManager& patch_manager,
return out;
}
QList<QStandardItem*> MakeGameListEntry(const std::string& path,
const std::string& name,
const std::size_t size,
const std::vector<u8>& icon,
Loader::AppLoader& loader,
u64 program_id,
QList<QStandardItem*> MakeGameListEntry(const std::string& path, const std::string& name,
const std::size_t size, const std::vector<u8>& icon,
Loader::AppLoader& loader, u64 program_id,
const CompatibilityList& compatibility_list,
const PlayTime::PlayTimeManager& play_time_manager,
const FileSys::PatchManager& patch)
{
const FileSys::PatchManager& patch) {
auto const it = FindMatchingCompatibilityEntry(compatibility_list, program_id);
// The game list uses 99 as compatibility number for untested games
QString compatibility = it != compatibility_list.end() ? it->second.first : QStringLiteral("99");
QString compatibility =
it != compatibility_list.end() ? it->second.first : QStringLiteral("99");
auto const file_type = loader.GetFileType();
auto const file_type_string = QString::fromStdString(Loader::GetFileTypeString(file_type));
QString patch_versions = GetGameListCachedObject(fmt::format("{:016X}", patch.GetTitleID()), "pv.txt", [&patch, &loader] {
QString patch_versions = GetGameListCachedObject(
fmt::format("{:016X}", patch.GetTitleID()), "pv.txt", [&patch, &loader] {
return FormatPatchNameVersions(patch, loader, loader.IsRomFSUpdatable());
});
@ -238,13 +236,9 @@ GameListWorker::GameListWorker(FileSys::VirtualFilesystem vfs_,
const CompatibilityList& compatibility_list_,
const PlayTime::PlayTimeManager& play_time_manager_,
Core::System& system_)
: vfs{std::move(vfs_)}
, provider{provider_}
, game_dirs{game_dirs_}
, compatibility_list{compatibility_list_}
, play_time_manager{play_time_manager_}
, system{system_}
{
: vfs{std::move(vfs_)}, provider{provider_}, game_dirs{game_dirs_},
compatibility_list{compatibility_list_}, play_time_manager{play_time_manager_},
system{system_} {
// We want the game list to manage our lifetime.
setAutoDelete(false);
}
@ -338,15 +332,8 @@ void GameListWorker::AddTitlesToGameList(GameListDir* parent_dir) {
GetMetadataFromControlNCA(patch, *control, icon, name);
}
auto entry = MakeGameListEntry(file->GetFullPath(),
name,
file->GetSize(),
icon,
*loader,
program_id,
compatibility_list,
play_time_manager,
patch);
auto entry = MakeGameListEntry(file->GetFullPath(), name, file->GetSize(), icon, *loader,
program_id, compatibility_list, play_time_manager, patch);
RecordEvent([=](GameList* game_list) { game_list->AddEntry(entry, parent_dir); });
}
}
@ -424,15 +411,9 @@ void GameListWorker::ScanFileSystem(ScanTarget target, const std::string& dir_pa
const FileSys::PatchManager patch{id, system.GetFileSystemController(),
system.GetContentProvider()};
auto entry = MakeGameListEntry(physical_name,
name,
Common::FS::GetSize(physical_name),
icon,
*loader,
id,
compatibility_list,
play_time_manager,
patch);
auto entry = MakeGameListEntry(
physical_name, name, Common::FS::GetSize(physical_name), icon, *loader,
id, compatibility_list, play_time_manager, patch);
RecordEvent(
[=](GameList* game_list) { game_list->AddEntry(entry, parent_dir); });
@ -447,15 +428,9 @@ void GameListWorker::ScanFileSystem(ScanTarget target, const std::string& dir_pa
const FileSys::PatchManager patch{program_id, system.GetFileSystemController(),
system.GetContentProvider()};
auto entry = MakeGameListEntry(physical_name,
name,
Common::FS::GetSize(physical_name),
icon,
*loader,
program_id,
compatibility_list,
play_time_manager,
patch);
auto entry = MakeGameListEntry(
physical_name, name, Common::FS::GetSize(physical_name), icon, *loader,
program_id, compatibility_list, play_time_manager, patch);
RecordEvent(
[=](GameList* game_list) { game_list->AddEntry(entry, parent_dir); });

View file

@ -18,9 +18,9 @@
#include "common/thread.h"
#include "core/file_sys/registered_cache.h"
#include "frontend_common/play_time_manager.h"
#include "qt_common/config/uisettings.h"
#include "yuzu/compatibility_list.h"
#include "frontend_common/play_time_manager.h"
namespace Core {
class System;

View file

@ -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: 2014 Citra Emulator Project
@ -10,8 +10,8 @@
#include <QtGlobal>
#include "hid_core/frontend/emulated_controller.h"
#include "yuzu/hotkeys.h"
#include "qt_common/config/uisettings.h"
#include "yuzu/hotkeys.h"
HotkeyRegistry::HotkeyRegistry() = default;
HotkeyRegistry::~HotkeyRegistry() = default;

View file

@ -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: Copyright 2020 yuzu Emulator Project
@ -10,8 +10,8 @@
#include <QLabel>
#include <QListWidget>
#include <QVBoxLayout>
#include "yuzu/install_dialog.h"
#include "qt_common/config/uisettings.h"
#include "yuzu/install_dialog.h"
InstallDialog::InstallDialog(QWidget* parent, const QStringList& files) : QDialog(parent) {
file_list = new QListWidget(this);

119
src/yuzu/libqt_common.cpp Normal file
View file

@ -0,0 +1,119 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#include <QAbstractButton>
#include <QFileDialog>
#include <QInputDialog>
#include <QMessageBox>
#include <QProgressDialog>
#include "libqt_common.h"
#include "qt_common/abstract/frontend.h"
#include "qt_common/abstract/progress.h"
#include "qt_common/qt_common.h"
namespace QtCommon::Frontend {
StandardButton ShowMessage(Icon icon, const QString& title, const QString& text,
StandardButtons buttons, QObject* parent) {
QMessageBox* box =
new QMessageBox(QMessageBox::Icon(int(icon)), title, text,
QMessageBox::StandardButtons(int(buttons)), (QWidget*)parent);
return StandardButton(box->exec());
}
WidgetsProgressDialog::WidgetsProgressDialog(const QString& labelText,
const QString& cancelButtonText, int minimum,
int maximum, QWidget* parent, Qt::WindowFlags f)
: QtProgressDialog(labelText, cancelButtonText, minimum, maximum, parent, f),
m_dialog(new QProgressDialog(labelText, cancelButtonText, minimum, maximum, parent, f)) {
m_dialog->setAutoClose(false);
m_dialog->setAutoReset(false);
m_dialog->setMinimumDuration(100);
m_dialog->setWindowModality(Qt::WindowModal);
}
bool WidgetsProgressDialog::wasCanceled() const {
return m_dialog->wasCanceled();
}
void WidgetsProgressDialog::setWindowModality(Qt::WindowModality modality) {
m_dialog->setWindowModality(modality);
}
void WidgetsProgressDialog::setMinimumDuration(int durationMs) {
m_dialog->setMinimumDuration(durationMs);
}
void WidgetsProgressDialog::setAutoClose(bool autoClose) {
m_dialog->setAutoClose(autoClose);
}
void WidgetsProgressDialog::setAutoReset(bool autoReset) {
m_dialog->setAutoReset(autoReset);
}
void WidgetsProgressDialog::setTitle(QString title) {
m_dialog->setWindowTitle(title);
}
void WidgetsProgressDialog::setLabelText(QString text) {
m_dialog->setLabelText(text);
}
void WidgetsProgressDialog::setMinimum(int min) {
m_dialog->setMinimum(min);
}
void WidgetsProgressDialog::setMaximum(int max) {
m_dialog->setMaximum(max);
}
void WidgetsProgressDialog::setValue(int value) {
m_dialog->setValue(value);
}
bool WidgetsProgressDialog::close() {
m_dialog->close();
return true;
}
void WidgetsProgressDialog::show() {
m_dialog->show();
}
std::unique_ptr<QtProgressDialog> newProgressDialog(const QString& labelText,
const QString& cancelButtonText, int minimum,
int maximum, Qt::WindowFlags f) {
return std::make_unique<WidgetsProgressDialog>(labelText, cancelButtonText, minimum, maximum,
(QWidget*)rootObject, f);
}
QtProgressDialog* newProgressDialogPtr(const QString& labelText, const QString& cancelButtonText,
int minimum, int maximum, Qt::WindowFlags f) {
return new WidgetsProgressDialog(labelText, cancelButtonText, minimum, maximum,
(QWidget*)rootObject, f);
}
int Choice(const QString& title, const QString& caption, const QStringList& options) {
QMessageBox box(rootObject);
box.setText(caption);
box.setWindowTitle(title);
for (const QString& opt : options) {
box.addButton(opt, QMessageBox::AcceptRole);
}
box.addButton(QMessageBox::Cancel);
box.exec();
auto button = box.clickedButton();
return options.indexOf(button->text());
}
const QString GetTextInput(const QString& title, const QString& caption,
const QString& defaultText) {
return QInputDialog::getText(rootObject, title, caption, QLineEdit::Normal, defaultText);
}
} // namespace QtCommon::Frontend

37
src/yuzu/libqt_common.h Normal file
View file

@ -0,0 +1,37 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#pragma once
#include "qt_common/abstract/progress.h"
#include <QProgressDialog>
namespace QtCommon::Frontend {
class WidgetsProgressDialog : public QtProgressDialog {
Q_OBJECT
public:
WidgetsProgressDialog(const QString& labelText, const QString& cancelButtonText, int minimum,
int maximum, QWidget* parent = nullptr, Qt::WindowFlags f = {});
bool wasCanceled() const override;
void setWindowModality(Qt::WindowModality modality) override;
void setMinimumDuration(int durationMs) override;
void setAutoClose(bool autoClose) override;
void setAutoReset(bool autoReset) override;
public slots:
void setTitle(QString title) override;
void setLabelText(QString text) override;
void setMinimum(int min) override;
void setMaximum(int max) override;
void setValue(int value) override;
bool close() override;
void show() override;
private:
QProgressDialog* m_dialog;
};
} // namespace QtCommon::Frontend

View file

@ -4,7 +4,6 @@
// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include <ankerl/unordered_dense.h>
#include <QBuffer>
#include <QByteArray>
#include <QGraphicsOpacityEffect>
@ -14,6 +13,7 @@
#include <QPixmap>
#include <QPropertyAnimation>
#include <QStyleOption>
#include <ankerl/unordered_dense.h>
#include "core/frontend/framebuffer_layout.h"
#include "core/loader/loader.h"
#include "ui_loading_screen.h"

View file

@ -5,8 +5,8 @@
#include "startup_checks.h"
#if YUZU_ROOM
#include "dedicated_room/yuzu_room.h"
#include <cstring>
#include "dedicated_room/yuzu_room.h"
#endif
#include <common/detached_tasks.h>
@ -62,8 +62,7 @@ static Qt::HighDpiScaleFactorRoundingPolicy GetHighDpiRoundingPolicy() {
// Get the lower of the 2 ratios and truncate, this is the maximum integer scale.
const qreal max_ratio = std::trunc(std::min(width_ratio, height_ratio));
return max_ratio > real_ratio
? Qt::HighDpiScaleFactorRoundingPolicy::Round
return max_ratio > real_ratio ? Qt::HighDpiScaleFactorRoundingPolicy::Round
: Qt::HighDpiScaleFactorRoundingPolicy::Floor;
#else
// Other OSes should be better than Windows at fractional scaling.

Some files were not shown because too many files have changed in this diff Show more