Compare commits

..

18 Commits

Author SHA1 Message Date
Lioncash
88cd5e888e configure_hotkeys: Remove unnecessary Settings::Apply() call
Nothing from the hotkeys dialog relies on this call occurring, and is
already called from the dialog that calls applyConfiguration().
2019-05-25 04:34:54 -04:00
Lioncash
6640f631e2 configure_hotkeys: Tidy up key sequence conflict error string
Avoids mentioning the user and formalizes the error itself.
2019-05-25 04:25:11 -04:00
Lioncash
d61199721d configure_hotkeys: Change critical error dialog into a warning dialog
critical() is intended for critical/fatal errors that threaten the
overall stability of an application. A user entering a conflicting key
sequence is neither of those.
2019-05-25 04:08:18 -04:00
Lioncash
ef3c0f54d0 configure_hotkeys: Move conflict detection logic to IsUsedKey()
We don't need to extract the entire set of hotkeys into a list and then
iterate through it. We can traverse the list and early-exit if we're
able to.
2019-05-25 04:08:13 -04:00
Lioncash
c03fb00ac1 configure_hotkeys: Remove unused EmitHotkeysChanged()
1. This is something that should be solely emitted by the hotkey dialog
itself
2. This is functionally unused, given there's nothing listening for the
signal.
2019-05-25 04:08:07 -04:00
Lioncash
5d645c6dd9 sequence_dialog: Reorganize the constructor
The previous code was all "smushed" together wasn't really grouped
together that well.

This spaces things out and separates them by relation to one another,
making it easier to visually parse the individual sections of code that
make up the constructor.
2019-05-25 04:08:02 -04:00
Lioncash
9218e347cd sequence_dialog: Remove unnecessary horizontal specifier
QDialogButtonBoxes are horizontal by default.
2019-05-25 04:07:56 -04:00
bunnei
e86d2e2e5b Merge pull request #2513 from lioncash/string
yuzu/main: Specify string conversions explicitly
2019-05-24 22:46:10 -04:00
bunnei
68c9c9222d Merge pull request #2358 from ReinUsesLisp/parallel-shader
gl_shader_cache: Use shared contexts to build shaders in parallel at boot
2019-05-24 22:42:08 -04:00
Lioncash
3c0280cf66 yuzu/CMakeLists: Disable implicit QString conversions
Now that all of our code is compilable with implicit QString
conversions, we can enforce it at compile-time by disabling them.
2019-05-24 21:31:01 -04:00
Lioncash
bb06b98d81 yuzu/applets/software_keyboard: Remove unused assert header
This isn't actually used anywhere, so it can be removed.
2019-05-24 21:27:13 -04:00
Lioncash
16bf791939 yuzu/applets/software_keyboard: std::move argument in MainWindowFinishedText()
Given the std::optional can contain an object type that heap allocates,
we can use std::move to avoid an unnecessary copy/allocation from
occurring.
2019-05-24 21:27:12 -04:00
Lioncash
b3d7180164 yuzu/applets/software_keyboard: Resolve sign mismatch comparison
Qt uses a signed value to represent container sizes, so this was causing
a sign mismatch warning.
2019-05-24 21:27:12 -04:00
Lioncash
cf9cc41478 yuzu/applets/software_keyboard: Specify string conversions explicitly
Allows the software keyboard applet code to compile with implicit string
conversions disabled.
2019-05-24 21:27:12 -04:00
Lioncash
f5d416e071 yuzu/applets/error: Specify string conversions explicitly
Allows the error applet to build successfully with implicit string
conversions disabled.
2019-05-24 21:27:12 -04:00
Lioncash
6f2a8fbb13 yuzu/main: Specify string conversions where applicable 2019-05-24 21:27:09 -04:00
ReinUsesLisp
69215b5a55 gl_shader_cache: Fix clang strict standard build issues 2019-05-20 22:46:05 -03:00
ReinUsesLisp
c03b8c4c19 gl_shader_cache: Use shared contexts to build shaders in parallel 2019-05-20 22:45:55 -03:00
19 changed files with 322 additions and 229 deletions

View File

@@ -98,9 +98,11 @@ struct FramebufferCacheKey {
}
};
RasterizerOpenGL::RasterizerOpenGL(Core::System& system, ScreenInfo& info)
: res_cache{*this}, shader_cache{*this, system, device}, global_cache{*this}, system{system},
screen_info{info}, buffer_cache(*this, STREAM_BUFFER_SIZE) {
RasterizerOpenGL::RasterizerOpenGL(Core::System& system, Core::Frontend::EmuWindow& emu_window,
ScreenInfo& info)
: res_cache{*this}, shader_cache{*this, system, emu_window, device},
global_cache{*this}, system{system}, screen_info{info},
buffer_cache(*this, STREAM_BUFFER_SIZE) {
OpenGLState::ApplyDefaultState();
shader_program_manager = std::make_unique<GLShader::ProgramManager>();

View File

@@ -48,7 +48,8 @@ struct FramebufferCacheKey;
class RasterizerOpenGL : public VideoCore::RasterizerInterface {
public:
explicit RasterizerOpenGL(Core::System& system, ScreenInfo& info);
explicit RasterizerOpenGL(Core::System& system, Core::Frontend::EmuWindow& emu_window,
ScreenInfo& info);
~RasterizerOpenGL() override;
void DrawArrays() override;

View File

@@ -2,10 +2,14 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include <mutex>
#include <thread>
#include <boost/functional/hash.hpp>
#include "common/assert.h"
#include "common/hash.h"
#include "common/scope_exit.h"
#include "core/core.h"
#include "core/frontend/emu_window.h"
#include "video_core/engines/maxwell_3d.h"
#include "video_core/memory_manager.h"
#include "video_core/renderer_opengl/gl_rasterizer.h"
@@ -344,8 +348,8 @@ ShaderDiskCacheUsage CachedShader::GetUsage(GLenum primitive_mode,
}
ShaderCacheOpenGL::ShaderCacheOpenGL(RasterizerOpenGL& rasterizer, Core::System& system,
const Device& device)
: RasterizerCache{rasterizer}, device{device}, disk_cache{system} {}
Core::Frontend::EmuWindow& emu_window, const Device& device)
: RasterizerCache{rasterizer}, emu_window{emu_window}, device{device}, disk_cache{system} {}
void ShaderCacheOpenGL::LoadDiskCache(const std::atomic_bool& stop_loading,
const VideoCore::DiskResourceLoadCallback& callback) {
@@ -353,62 +357,107 @@ void ShaderCacheOpenGL::LoadDiskCache(const std::atomic_bool& stop_loading,
if (!transferable) {
return;
}
const auto [raws, usages] = *transferable;
const auto [raws, shader_usages] = *transferable;
auto [decompiled, dumps] = disk_cache.LoadPrecompiled();
const auto supported_formats{GetSupportedFormats()};
const auto unspecialized{
const auto unspecialized_shaders{
GenerateUnspecializedShaders(stop_loading, callback, raws, decompiled)};
if (stop_loading)
if (stop_loading) {
return;
}
// Track if precompiled cache was altered during loading to know if we have to serialize the
// virtual precompiled cache file back to the hard drive
bool precompiled_cache_altered = false;
// Build shaders
if (callback)
callback(VideoCore::LoadCallbackStage::Build, 0, usages.size());
for (std::size_t i = 0; i < usages.size(); ++i) {
if (stop_loading)
return;
// Inform the frontend about shader build initialization
if (callback) {
callback(VideoCore::LoadCallbackStage::Build, 0, shader_usages.size());
}
const auto& usage{usages[i]};
LOG_INFO(Render_OpenGL, "Building shader {:016x} ({} of {})", usage.unique_identifier,
i + 1, usages.size());
std::mutex mutex;
std::size_t built_shaders = 0; // It doesn't have be atomic since it's used behind a mutex
std::atomic_bool compilation_failed = false;
const auto& unspec{unspecialized.at(usage.unique_identifier)};
const auto dump_it = dumps.find(usage);
const auto Worker = [&](Core::Frontend::GraphicsContext* context, std::size_t begin,
std::size_t end, const std::vector<ShaderDiskCacheUsage>& shader_usages,
const ShaderDumpsMap& dumps) {
context->MakeCurrent();
SCOPE_EXIT({ return context->DoneCurrent(); });
CachedProgram shader;
if (dump_it != dumps.end()) {
// If the shader is dumped, attempt to load it with
shader = GeneratePrecompiledProgram(dump_it->second, supported_formats);
if (!shader) {
// Invalidate the precompiled cache if a shader dumped shader was rejected
disk_cache.InvalidatePrecompiled();
precompiled_cache_altered = true;
dumps.clear();
for (std::size_t i = begin; i < end; ++i) {
if (stop_loading || compilation_failed) {
return;
}
}
if (!shader) {
shader = SpecializeShader(unspec.code, unspec.entries, unspec.program_type,
usage.bindings, usage.primitive, true);
}
precompiled_programs.insert({usage, std::move(shader)});
const auto& usage{shader_usages[i]};
LOG_INFO(Render_OpenGL, "Building shader {:016x} (index {} of {})",
usage.unique_identifier, i, shader_usages.size());
if (callback)
callback(VideoCore::LoadCallbackStage::Build, i + 1, usages.size());
const auto& unspecialized{unspecialized_shaders.at(usage.unique_identifier)};
const auto dump{dumps.find(usage)};
CachedProgram shader;
if (dump != dumps.end()) {
// If the shader is dumped, attempt to load it with
shader = GeneratePrecompiledProgram(dump->second, supported_formats);
if (!shader) {
compilation_failed = true;
return;
}
}
if (!shader) {
shader = SpecializeShader(unspecialized.code, unspecialized.entries,
unspecialized.program_type, usage.bindings,
usage.primitive, true);
}
std::scoped_lock lock(mutex);
if (callback) {
callback(VideoCore::LoadCallbackStage::Build, ++built_shaders,
shader_usages.size());
}
precompiled_programs.emplace(usage, std::move(shader));
}
};
const auto num_workers{static_cast<std::size_t>(std::thread::hardware_concurrency() + 1)};
const std::size_t bucket_size{shader_usages.size() / num_workers};
std::vector<std::unique_ptr<Core::Frontend::GraphicsContext>> contexts(num_workers);
std::vector<std::thread> threads(num_workers);
for (std::size_t i = 0; i < num_workers; ++i) {
const bool is_last_worker = i + 1 == num_workers;
const std::size_t start{bucket_size * i};
const std::size_t end{is_last_worker ? shader_usages.size() : start + bucket_size};
// On some platforms the shared context has to be created from the GUI thread
contexts[i] = emu_window.CreateSharedContext();
threads[i] = std::thread(Worker, contexts[i].get(), start, end, shader_usages, dumps);
}
for (auto& thread : threads) {
thread.join();
}
if (compilation_failed) {
// Invalidate the precompiled cache if a shader dumped shader was rejected
disk_cache.InvalidatePrecompiled();
dumps.clear();
precompiled_cache_altered = true;
return;
}
if (stop_loading) {
return;
}
// TODO(Rodrigo): Do state tracking for transferable shaders and do a dummy draw before
// precompiling them
for (std::size_t i = 0; i < usages.size(); ++i) {
const auto& usage{usages[i]};
for (std::size_t i = 0; i < shader_usages.size(); ++i) {
const auto& usage{shader_usages[i]};
if (dumps.find(usage) == dumps.end()) {
const auto& program = precompiled_programs.at(usage);
const auto& program{precompiled_programs.at(usage)};
disk_cache.SaveDump(usage, program->handle);
precompiled_cache_altered = true;
}

View File

@@ -22,7 +22,11 @@
namespace Core {
class System;
} // namespace Core
}
namespace Core::Frontend {
class EmuWindow;
}
namespace OpenGL {
@@ -111,7 +115,7 @@ private:
class ShaderCacheOpenGL final : public RasterizerCache<Shader> {
public:
explicit ShaderCacheOpenGL(RasterizerOpenGL& rasterizer, Core::System& system,
const Device& device);
Core::Frontend::EmuWindow& emu_window, const Device& device);
/// Loads disk cache for the current game
void LoadDiskCache(const std::atomic_bool& stop_loading,
@@ -133,13 +137,13 @@ private:
CachedProgram GeneratePrecompiledProgram(const ShaderDiskCacheDump& dump,
const std::set<GLenum>& supported_formats);
Core::Frontend::EmuWindow& emu_window;
const Device& device;
std::array<Shader, Maxwell::MaxShaderProgram> last_shaders;
ShaderDiskCacheOpenGL disk_cache;
PrecompiledShaders precompiled_shaders;
PrecompiledPrograms precompiled_programs;
std::array<Shader, Maxwell::MaxShaderProgram> last_shaders;
};
} // namespace OpenGL

View File

@@ -183,8 +183,7 @@ ShaderDiskCacheOpenGL::LoadTransferable() {
return {{raws, usages}};
}
std::pair<std::unordered_map<u64, ShaderDiskCacheDecompiled>,
std::unordered_map<ShaderDiskCacheUsage, ShaderDiskCacheDump>>
std::pair<std::unordered_map<u64, ShaderDiskCacheDecompiled>, ShaderDumpsMap>
ShaderDiskCacheOpenGL::LoadPrecompiled() {
if (!IsUsable())
return {};
@@ -208,8 +207,7 @@ ShaderDiskCacheOpenGL::LoadPrecompiled() {
return *result;
}
std::optional<std::pair<std::unordered_map<u64, ShaderDiskCacheDecompiled>,
std::unordered_map<ShaderDiskCacheUsage, ShaderDiskCacheDump>>>
std::optional<std::pair<std::unordered_map<u64, ShaderDiskCacheDecompiled>, ShaderDumpsMap>>
ShaderDiskCacheOpenGL::LoadPrecompiledFile(FileUtil::IOFile& file) {
// Read compressed file from disk and decompress to virtual precompiled cache file
std::vector<u8> compressed(file.GetSize());
@@ -230,7 +228,7 @@ ShaderDiskCacheOpenGL::LoadPrecompiledFile(FileUtil::IOFile& file) {
}
std::unordered_map<u64, ShaderDiskCacheDecompiled> decompiled;
std::unordered_map<ShaderDiskCacheUsage, ShaderDiskCacheDump> dumps;
ShaderDumpsMap dumps;
while (precompiled_cache_virtual_file_offset < precompiled_cache_virtual_file.GetSize()) {
PrecompiledEntryKind kind{};
if (!LoadObjectFromPrecompiled(kind)) {

View File

@@ -33,6 +33,11 @@ namespace OpenGL {
using ProgramCode = std::vector<u64>;
using Maxwell = Tegra::Engines::Maxwell3D::Regs;
struct ShaderDiskCacheUsage;
struct ShaderDiskCacheDump;
using ShaderDumpsMap = std::unordered_map<ShaderDiskCacheUsage, ShaderDiskCacheDump>;
/// Allocated bindings used by an OpenGL shader program
struct BaseBindings {
u32 cbuf{};
@@ -294,4 +299,4 @@ private:
bool tried_to_load{};
};
} // namespace OpenGL
} // namespace OpenGL

View File

@@ -97,8 +97,8 @@ static std::array<GLfloat, 3 * 2> MakeOrthographicMatrix(const float width, cons
return matrix;
}
RendererOpenGL::RendererOpenGL(Core::Frontend::EmuWindow& window, Core::System& system)
: VideoCore::RendererBase{window}, system{system} {}
RendererOpenGL::RendererOpenGL(Core::Frontend::EmuWindow& emu_window, Core::System& system)
: VideoCore::RendererBase{emu_window}, emu_window{emu_window}, system{system} {}
RendererOpenGL::~RendererOpenGL() = default;
@@ -265,7 +265,7 @@ void RendererOpenGL::CreateRasterizer() {
}
// Initialize sRGB Usage
OpenGLState::ClearsRGBUsed();
rasterizer = std::make_unique<RasterizerOpenGL>(system, screen_info);
rasterizer = std::make_unique<RasterizerOpenGL>(system, emu_window, screen_info);
}
void RendererOpenGL::ConfigureFramebufferTexture(TextureInfo& texture,

View File

@@ -45,7 +45,7 @@ struct ScreenInfo {
class RendererOpenGL : public VideoCore::RendererBase {
public:
explicit RendererOpenGL(Core::Frontend::EmuWindow& window, Core::System& system);
explicit RendererOpenGL(Core::Frontend::EmuWindow& emu_window, Core::System& system);
~RendererOpenGL() override;
/// Swap buffers (render frame)
@@ -77,6 +77,7 @@ private:
void LoadColorToActiveGLTexture(u8 color_r, u8 color_g, u8 color_b, u8 color_a,
const TextureInfo& texture);
Core::Frontend::EmuWindow& emu_window;
Core::System& system;
OpenGLState state;

View File

@@ -155,6 +155,10 @@ target_compile_definitions(yuzu PRIVATE
# Use QStringBuilder for string concatenation to reduce
# the overall number of temporary strings created.
-DQT_USE_QSTRINGBUILDER
# Disable implicit conversions from/to C strings
-DQT_NO_CAST_FROM_ASCII
-DQT_NO_CAST_TO_ASCII
)
if (YUZU_ENABLE_COMPATIBILITY_REPORTING)

View File

@@ -29,11 +29,13 @@ void QtErrorDisplay::ShowError(ResultCode error, std::function<void()> finished)
void QtErrorDisplay::ShowErrorWithTimestamp(ResultCode error, std::chrono::seconds time,
std::function<void()> finished) const {
this->callback = std::move(finished);
const QDateTime date_time = QDateTime::fromSecsSinceEpoch(time.count());
emit MainWindowDisplayError(
tr("An error occured on %1 at %2.\nPlease try again or contact the "
"developer of the software.\n\nError Code: %3-%4 (0x%5)")
.arg(QDateTime::fromSecsSinceEpoch(time.count()).toString("dddd, MMMM d, yyyy"))
.arg(QDateTime::fromSecsSinceEpoch(time.count()).toString("h:mm:ss A"))
.arg(date_time.toString(QStringLiteral("dddd, MMMM d, yyyy")))
.arg(date_time.toString(QStringLiteral("h:mm:ss A")))
.arg(static_cast<u32>(error.module.Value()) + 2000, 4, 10, QChar::fromLatin1('0'))
.arg(error.description, 4, 10, QChar::fromLatin1('0'))
.arg(error.raw, 8, 16, QChar::fromLatin1('0')));

View File

@@ -18,23 +18,30 @@ QtSoftwareKeyboardValidator::QtSoftwareKeyboardValidator(
: parameters(std::move(parameters)) {}
QValidator::State QtSoftwareKeyboardValidator::validate(QString& input, int& pos) const {
if (input.size() > parameters.max_length)
if (input.size() > static_cast<s64>(parameters.max_length)) {
return Invalid;
if (parameters.disable_space && input.contains(' '))
}
if (parameters.disable_space && input.contains(QLatin1Char{' '})) {
return Invalid;
if (parameters.disable_address && input.contains('@'))
}
if (parameters.disable_address && input.contains(QLatin1Char{'@'})) {
return Invalid;
if (parameters.disable_percent && input.contains('%'))
}
if (parameters.disable_percent && input.contains(QLatin1Char{'%'})) {
return Invalid;
if (parameters.disable_slash && (input.contains('/') || input.contains('\\')))
}
if (parameters.disable_slash &&
(input.contains(QLatin1Char{'/'}) || input.contains(QLatin1Char{'\\'}))) {
return Invalid;
}
if (parameters.disable_number &&
std::any_of(input.begin(), input.end(), [](QChar c) { return c.isDigit(); })) {
return Invalid;
}
if (parameters.disable_download_code &&
std::any_of(input.begin(), input.end(), [](QChar c) { return c == 'O' || c == 'I'; })) {
if (parameters.disable_download_code && std::any_of(input.begin(), input.end(), [](QChar c) {
return c == QLatin1Char{'O'} || c == QLatin1Char{'I'};
})) {
return Invalid;
}
@@ -142,7 +149,7 @@ void QtSoftwareKeyboard::SendTextCheckDialog(std::u16string error_message,
void QtSoftwareKeyboard::MainWindowFinishedText(std::optional<std::u16string> text) {
// Acquire the HLE mutex
std::lock_guard lock{HLE::g_hle_lock};
text_output(text);
text_output(std::move(text));
}
void QtSoftwareKeyboard::MainWindowFinishedCheckDialog() {

View File

@@ -6,7 +6,6 @@
#include <QDialog>
#include <QValidator>
#include "common/assert.h"
#include "core/frontend/applets/software_keyboard.h"
class GMainWindow;

View File

@@ -91,25 +91,25 @@ void EmuThread::run() {
class GGLContext : public Core::Frontend::GraphicsContext {
public:
explicit GGLContext(QOpenGLContext* shared_context)
: context{std::make_unique<QOpenGLContext>(shared_context)} {
surface.setFormat(shared_context->format());
surface.create();
explicit GGLContext(QOpenGLContext* shared_context) : shared_context{shared_context} {
context.setFormat(shared_context->format());
context.setShareContext(shared_context);
context.create();
}
void MakeCurrent() override {
context->makeCurrent(&surface);
context.makeCurrent(shared_context->surface());
}
void DoneCurrent() override {
context->doneCurrent();
context.doneCurrent();
}
void SwapBuffers() override {}
private:
std::unique_ptr<QOpenGLContext> context;
QOffscreenSurface surface;
QOpenGLContext* shared_context;
QOpenGLContext context;
};
// This class overrides paintEvent and resizeEvent to prevent the GUI thread from stealing GL
@@ -358,7 +358,7 @@ void GRenderWindow::OnClientAreaResized(unsigned width, unsigned height) {
}
std::unique_ptr<Core::Frontend::GraphicsContext> GRenderWindow::CreateSharedContext() const {
return std::make_unique<GGLContext>(shared_context.get());
return std::make_unique<GGLContext>(context.get());
}
void GRenderWindow::InitRenderTarget() {

View File

@@ -25,9 +25,6 @@ ConfigureDialog::ConfigureDialog(QWidget* parent, HotkeyRegistry& registry)
adjustSize();
ui->selectorList->setCurrentRow(0);
// Synchronise lists upon initialisation
ui->hotkeysTab->EmitHotkeysChanged();
}
ConfigureDialog::~ConfigureDialog() = default;

View File

@@ -51,15 +51,17 @@ Resolution FromResolutionFactor(float factor) {
ConfigureGraphics::ConfigureGraphics(QWidget* parent)
: QWidget(parent), ui(new Ui::ConfigureGraphics) {
ui->setupUi(this);
setConfiguration();
connect(ui->toggle_frame_limit, &QCheckBox::toggled, ui->frame_limit, &QSpinBox::setEnabled);
ui->setupUi(this);
this->setConfiguration();
ui->frame_limit->setEnabled(Settings::values.use_frame_limit);
connect(ui->toggle_frame_limit, &QCheckBox::stateChanged, ui->frame_limit,
&QSpinBox::setEnabled);
connect(ui->bg_button, &QPushButton::clicked, this, [this] {
const QColor new_bg_color = QColorDialog::getColor(bg_color);
if (!new_bg_color.isValid()) {
if (!new_bg_color.isValid())
return;
}
UpdateBackgroundColorButton(new_bg_color);
});
}
@@ -72,7 +74,6 @@ void ConfigureGraphics::setConfiguration() {
ui->resolution_factor_combobox->setCurrentIndex(
static_cast<int>(FromResolutionFactor(Settings::values.resolution_factor)));
ui->toggle_frame_limit->setChecked(Settings::values.use_frame_limit);
ui->frame_limit->setEnabled(ui->toggle_frame_limit->isChecked());
ui->frame_limit->setValue(Settings::values.frame_limit);
ui->use_compatibility_profile->setEnabled(runtime_lock);
ui->use_compatibility_profile->setChecked(Settings::values.use_compatibility_profile);

View File

@@ -31,22 +31,6 @@ ConfigureHotkeys::ConfigureHotkeys(QWidget* parent)
ConfigureHotkeys::~ConfigureHotkeys() = default;
void ConfigureHotkeys::EmitHotkeysChanged() {
emit HotkeysChanged(GetUsedKeyList());
}
QList<QKeySequence> ConfigureHotkeys::GetUsedKeyList() const {
QList<QKeySequence> list;
for (int r = 0; r < model->rowCount(); r++) {
const QStandardItem* parent = model->item(r, 0);
for (int r2 = 0; r2 < parent->rowCount(); r2++) {
const QStandardItem* keyseq = parent->child(r2, 1);
list << QKeySequence::fromString(keyseq->text(), QKeySequence::NativeText);
}
}
return list;
}
void ConfigureHotkeys::Populate(const HotkeyRegistry& registry) {
for (const auto& group : registry.hotkey_groups) {
auto* parent_item = new QStandardItem(group.first);
@@ -83,16 +67,29 @@ void ConfigureHotkeys::Configure(QModelIndex index) {
}
if (IsUsedKey(key_sequence) && key_sequence != QKeySequence(previous_key.toString())) {
QMessageBox::critical(this, tr("Error in inputted key"),
tr("You're using a key that's already bound."));
QMessageBox::warning(this, tr("Conflicting Key Sequence"),
tr("The entered key sequence is already assigned to another hotkey."));
} else {
model->setData(index, key_sequence.toString(QKeySequence::NativeText));
EmitHotkeysChanged();
}
}
bool ConfigureHotkeys::IsUsedKey(QKeySequence key_sequence) const {
return GetUsedKeyList().contains(key_sequence);
for (int r = 0; r < model->rowCount(); r++) {
const QStandardItem* const parent = model->item(r, 0);
for (int r2 = 0; r2 < parent->rowCount(); r2++) {
const QStandardItem* const key_seq_item = parent->child(r2, 1);
const auto key_seq_str = key_seq_item->text();
const auto key_seq = QKeySequence::fromString(key_seq_str, QKeySequence::NativeText);
if (key_sequence == key_seq) {
return true;
}
}
}
return false;
}
void ConfigureHotkeys::applyConfiguration(HotkeyRegistry& registry) {
@@ -114,7 +111,6 @@ void ConfigureHotkeys::applyConfiguration(HotkeyRegistry& registry) {
}
registry.SaveHotkeys();
Settings::Apply();
}
void ConfigureHotkeys::retranslateUi() {

View File

@@ -24,8 +24,6 @@ public:
void applyConfiguration(HotkeyRegistry& registry);
void retranslateUi();
void EmitHotkeysChanged();
/**
* Populates the hotkey list widget using data from the provided registry.
* Called everytime the Configure dialog is opened.
@@ -33,13 +31,9 @@ public:
*/
void Populate(const HotkeyRegistry& registry);
signals:
void HotkeysChanged(QList<QKeySequence> new_key_list);
private:
void Configure(QModelIndex index);
bool IsUsedKey(QKeySequence key_sequence) const;
QList<QKeySequence> GetUsedKeyList() const;
std::unique_ptr<Ui::ConfigureHotkeys> ui;

View File

@@ -281,7 +281,7 @@ void GMainWindow::SoftwareKeyboardInvokeCheckDialog(std::u16string error_message
void GMainWindow::WebBrowserOpenPage(std::string_view filename, std::string_view additional_args) {
NXInputWebEngineView web_browser_view(this);
// Scope to contain the QProgressDialog for initalization
// Scope to contain the QProgressDialog for initialization
{
QProgressDialog progress(this);
progress.setMinimumDuration(200);
@@ -301,7 +301,7 @@ void GMainWindow::WebBrowserOpenPage(std::string_view filename, std::string_view
QWebEngineScript nx_shim;
nx_shim.setSourceCode(GetNXShimInjectionScript());
nx_shim.setWorldId(QWebEngineScript::MainWorld);
nx_shim.setName("nx_inject.js");
nx_shim.setName(QStringLiteral("nx_inject.js"));
nx_shim.setInjectionPoint(QWebEngineScript::DocumentCreation);
nx_shim.setRunsOnSubFrames(true);
web_browser_view.page()->profile()->scripts()->insert(nx_shim);
@@ -347,7 +347,7 @@ void GMainWindow::WebBrowserOpenPage(std::string_view filename, std::string_view
const auto fire_js_keypress = [&web_browser_view](u32 key_code) {
web_browser_view.page()->runJavaScript(
QStringLiteral("document.dispatchEvent(new KeyboardEvent('keydown', {'key': %1}));")
.arg(QString::fromStdString(std::to_string(key_code))));
.arg(key_code));
};
QMessageBox::information(
@@ -468,7 +468,7 @@ void GMainWindow::InitializeWidgets() {
statusBar()->addPermanentWidget(label, 0);
}
statusBar()->setVisible(true);
setStyleSheet("QStatusBar::item{border: none;}");
setStyleSheet(QStringLiteral("QStatusBar::item{border: none;}"));
}
void GMainWindow::InitializeDebugWidgets() {
@@ -518,58 +518,67 @@ void GMainWindow::InitializeRecentFileMenuActions() {
void GMainWindow::InitializeHotkeys() {
hotkey_registry.LoadHotkeys();
ui.action_Load_File->setShortcut(hotkey_registry.GetKeySequence("Main Window", "Load File"));
const QString main_window = QStringLiteral("Main Window");
const QString load_file = QStringLiteral("Load File");
const QString exit_yuzu = QStringLiteral("Exit yuzu");
const QString stop_emulation = QStringLiteral("Stop Emulation");
const QString toggle_filter_bar = QStringLiteral("Toggle Filter Bar");
const QString toggle_status_bar = QStringLiteral("Toggle Status Bar");
const QString fullscreen = QStringLiteral("Fullscreen");
ui.action_Load_File->setShortcut(hotkey_registry.GetKeySequence(main_window, load_file));
ui.action_Load_File->setShortcutContext(
hotkey_registry.GetShortcutContext("Main Window", "Load File"));
hotkey_registry.GetShortcutContext(main_window, load_file));
ui.action_Exit->setShortcut(hotkey_registry.GetKeySequence("Main Window", "Exit yuzu"));
ui.action_Exit->setShortcutContext(
hotkey_registry.GetShortcutContext("Main Window", "Exit yuzu"));
ui.action_Exit->setShortcut(hotkey_registry.GetKeySequence(main_window, exit_yuzu));
ui.action_Exit->setShortcutContext(hotkey_registry.GetShortcutContext(main_window, exit_yuzu));
ui.action_Stop->setShortcut(hotkey_registry.GetKeySequence("Main Window", "Stop Emulation"));
ui.action_Stop->setShortcut(hotkey_registry.GetKeySequence(main_window, stop_emulation));
ui.action_Stop->setShortcutContext(
hotkey_registry.GetShortcutContext("Main Window", "Stop Emulation"));
hotkey_registry.GetShortcutContext(main_window, stop_emulation));
ui.action_Show_Filter_Bar->setShortcut(
hotkey_registry.GetKeySequence("Main Window", "Toggle Filter Bar"));
hotkey_registry.GetKeySequence(main_window, toggle_filter_bar));
ui.action_Show_Filter_Bar->setShortcutContext(
hotkey_registry.GetShortcutContext("Main Window", "Toggle Filter Bar"));
hotkey_registry.GetShortcutContext(main_window, toggle_filter_bar));
ui.action_Show_Status_Bar->setShortcut(
hotkey_registry.GetKeySequence("Main Window", "Toggle Status Bar"));
hotkey_registry.GetKeySequence(main_window, toggle_status_bar));
ui.action_Show_Status_Bar->setShortcutContext(
hotkey_registry.GetShortcutContext("Main Window", "Toggle Status Bar"));
hotkey_registry.GetShortcutContext(main_window, toggle_status_bar));
connect(hotkey_registry.GetHotkey("Main Window", "Load File", this), &QShortcut::activated,
this, &GMainWindow::OnMenuLoadFile);
connect(hotkey_registry.GetHotkey("Main Window", "Continue/Pause Emulation", this),
&QShortcut::activated, this, [&] {
if (emulation_running) {
if (emu_thread->IsRunning()) {
OnPauseGame();
} else {
OnStartGame();
}
connect(hotkey_registry.GetHotkey(main_window, QStringLiteral("Load File"), this),
&QShortcut::activated, this, &GMainWindow::OnMenuLoadFile);
connect(
hotkey_registry.GetHotkey(main_window, QStringLiteral("Continue/Pause Emulation"), this),
&QShortcut::activated, this, [&] {
if (emulation_running) {
if (emu_thread->IsRunning()) {
OnPauseGame();
} else {
OnStartGame();
}
});
connect(hotkey_registry.GetHotkey("Main Window", "Restart Emulation", this),
}
});
connect(hotkey_registry.GetHotkey(main_window, QStringLiteral("Restart Emulation"), this),
&QShortcut::activated, this, [this] {
if (!Core::System::GetInstance().IsPoweredOn())
if (!Core::System::GetInstance().IsPoweredOn()) {
return;
BootGame(QString(game_path));
}
BootGame(game_path);
});
connect(hotkey_registry.GetHotkey("Main Window", "Fullscreen", render_window),
connect(hotkey_registry.GetHotkey(main_window, fullscreen, render_window),
&QShortcut::activated, ui.action_Fullscreen, &QAction::trigger);
connect(hotkey_registry.GetHotkey("Main Window", "Fullscreen", render_window),
connect(hotkey_registry.GetHotkey(main_window, fullscreen, render_window),
&QShortcut::activatedAmbiguously, ui.action_Fullscreen, &QAction::trigger);
connect(hotkey_registry.GetHotkey("Main Window", "Exit Fullscreen", this),
connect(hotkey_registry.GetHotkey(main_window, QStringLiteral("Exit Fullscreen"), this),
&QShortcut::activated, this, [&] {
if (emulation_running) {
ui.action_Fullscreen->setChecked(false);
ToggleFullscreen();
}
});
connect(hotkey_registry.GetHotkey("Main Window", "Toggle Speed Limit", this),
connect(hotkey_registry.GetHotkey(main_window, QStringLiteral("Toggle Speed Limit"), this),
&QShortcut::activated, this, [&] {
Settings::values.use_frame_limit = !Settings::values.use_frame_limit;
UpdateStatusBar();
@@ -578,33 +587,33 @@ void GMainWindow::InitializeHotkeys() {
// MSVC occurs and we make it a requirement (see:
// https://developercommunity.visualstudio.com/content/problem/93922/constexprs-are-trying-to-be-captured-in-lambda-fun.html)
static constexpr u16 SPEED_LIMIT_STEP = 5;
connect(hotkey_registry.GetHotkey("Main Window", "Increase Speed Limit", this),
connect(hotkey_registry.GetHotkey(main_window, QStringLiteral("Increase Speed Limit"), this),
&QShortcut::activated, this, [&] {
if (Settings::values.frame_limit < 9999 - SPEED_LIMIT_STEP) {
Settings::values.frame_limit += SPEED_LIMIT_STEP;
UpdateStatusBar();
}
});
connect(hotkey_registry.GetHotkey("Main Window", "Decrease Speed Limit", this),
connect(hotkey_registry.GetHotkey(main_window, QStringLiteral("Decrease Speed Limit"), this),
&QShortcut::activated, this, [&] {
if (Settings::values.frame_limit > SPEED_LIMIT_STEP) {
Settings::values.frame_limit -= SPEED_LIMIT_STEP;
UpdateStatusBar();
}
});
connect(hotkey_registry.GetHotkey("Main Window", "Load Amiibo", this), &QShortcut::activated,
this, [&] {
connect(hotkey_registry.GetHotkey(main_window, QStringLiteral("Load Amiibo"), this),
&QShortcut::activated, this, [&] {
if (ui.action_Load_Amiibo->isEnabled()) {
OnLoadAmiibo();
}
});
connect(hotkey_registry.GetHotkey("Main Window", "Capture Screenshot", this),
connect(hotkey_registry.GetHotkey(main_window, QStringLiteral("Capture Screenshot"), this),
&QShortcut::activated, this, [&] {
if (emu_thread->IsRunning()) {
OnCaptureScreenshot();
}
});
connect(hotkey_registry.GetHotkey("Main Window", "Change Docked Mode", this),
connect(hotkey_registry.GetHotkey(main_window, QStringLiteral("Change Docked Mode"), this),
&QShortcut::activated, this, [&] {
Settings::values.use_docked_mode = !Settings::values.use_docked_mode;
OnDockedModeChanged(!Settings::values.use_docked_mode,
@@ -705,7 +714,9 @@ void GMainWindow::ConnectMenuEvents() {
// Fullscreen
ui.action_Fullscreen->setShortcut(
hotkey_registry.GetHotkey("Main Window", "Fullscreen", this)->key());
hotkey_registry
.GetHotkey(QStringLiteral("Main Window"), QStringLiteral("Fullscreen"), this)
->key());
connect(ui.action_Fullscreen, &QAction::triggered, this, &GMainWindow::ToggleFullscreen);
// Movie
@@ -742,25 +753,33 @@ void GMainWindow::OnDisplayTitleBars(bool show) {
QStringList GMainWindow::GetUnsupportedGLExtensions() {
QStringList unsupported_ext;
if (!GLAD_GL_ARB_direct_state_access)
unsupported_ext.append("ARB_direct_state_access");
if (!GLAD_GL_ARB_vertex_type_10f_11f_11f_rev)
unsupported_ext.append("ARB_vertex_type_10f_11f_11f_rev");
if (!GLAD_GL_ARB_texture_mirror_clamp_to_edge)
unsupported_ext.append("ARB_texture_mirror_clamp_to_edge");
if (!GLAD_GL_ARB_multi_bind)
unsupported_ext.append("ARB_multi_bind");
if (!GLAD_GL_ARB_direct_state_access) {
unsupported_ext.append(QStringLiteral("ARB_direct_state_access"));
}
if (!GLAD_GL_ARB_vertex_type_10f_11f_11f_rev) {
unsupported_ext.append(QStringLiteral("ARB_vertex_type_10f_11f_11f_rev"));
}
if (!GLAD_GL_ARB_texture_mirror_clamp_to_edge) {
unsupported_ext.append(QStringLiteral("ARB_texture_mirror_clamp_to_edge"));
}
if (!GLAD_GL_ARB_multi_bind) {
unsupported_ext.append(QStringLiteral("ARB_multi_bind"));
}
// Extensions required to support some texture formats.
if (!GLAD_GL_EXT_texture_compression_s3tc)
unsupported_ext.append("EXT_texture_compression_s3tc");
if (!GLAD_GL_ARB_texture_compression_rgtc)
unsupported_ext.append("ARB_texture_compression_rgtc");
if (!GLAD_GL_ARB_depth_buffer_float)
unsupported_ext.append("ARB_depth_buffer_float");
if (!GLAD_GL_EXT_texture_compression_s3tc) {
unsupported_ext.append(QStringLiteral("EXT_texture_compression_s3tc"));
}
if (!GLAD_GL_ARB_texture_compression_rgtc) {
unsupported_ext.append(QStringLiteral("ARB_texture_compression_rgtc"));
}
if (!GLAD_GL_ARB_depth_buffer_float) {
unsupported_ext.append(QStringLiteral("ARB_depth_buffer_float"));
}
for (const QString& ext : unsupported_ext)
for (const QString& ext : unsupported_ext) {
LOG_CRITICAL(Frontend, "Unsupported GL extension: {}", ext.toStdString());
}
return unsupported_ext;
}
@@ -782,13 +801,13 @@ bool GMainWindow::LoadROM(const QString& filename) {
}
}
QStringList unsupported_gl_extensions = GetUnsupportedGLExtensions();
const QStringList unsupported_gl_extensions = GetUnsupportedGLExtensions();
if (!unsupported_gl_extensions.empty()) {
QMessageBox::critical(this, tr("Error while initializing OpenGL Core!"),
tr("Your GPU may not support one or more required OpenGL"
"extensions. Please ensure you have the latest graphics "
"driver.<br><br>Unsupported extensions:<br>") +
unsupported_gl_extensions.join("<br>"));
unsupported_gl_extensions.join(QStringLiteral("<br>")));
return false;
}
@@ -1007,7 +1026,7 @@ void GMainWindow::UpdateRecentFiles() {
std::min(UISettings::values.recent_files.size(), max_recent_files_item);
for (int i = 0; i < num_recent_files; i++) {
const QString text = QString("&%1. %2").arg(i + 1).arg(
const QString text = QStringLiteral("&%1. %2").arg(i + 1).arg(
QFileInfo(UISettings::values.recent_files[i]).fileName());
actions_recent_files[i]->setText(text);
actions_recent_files[i]->setData(UISettings::values.recent_files[i]);
@@ -1029,10 +1048,10 @@ void GMainWindow::OnGameListLoadFile(QString game_path) {
void GMainWindow::OnGameListOpenFolder(u64 program_id, GameListOpenTarget target) {
std::string path;
std::string open_target;
QString open_target;
switch (target) {
case GameListOpenTarget::SaveData: {
open_target = "Save Data";
open_target = tr("Save Data");
const std::string nand_dir = FileUtil::GetUserPath(FileUtil::UserPath::NANDDir);
ASSERT(program_id != 0);
@@ -1069,7 +1088,7 @@ void GMainWindow::OnGameListOpenFolder(u64 program_id, GameListOpenTarget target
break;
}
case GameListOpenTarget::ModData: {
open_target = "Mod Data";
open_target = tr("Mod Data");
const auto load_dir = FileUtil::GetUserPath(FileUtil::UserPath::LoadDir);
path = fmt::format("{}{:016X}", load_dir, program_id);
break;
@@ -1079,27 +1098,26 @@ void GMainWindow::OnGameListOpenFolder(u64 program_id, GameListOpenTarget target
}
const QString qpath = QString::fromStdString(path);
const QDir dir(qpath);
if (!dir.exists()) {
QMessageBox::warning(this,
tr("Error Opening %1 Folder").arg(QString::fromStdString(open_target)),
QMessageBox::warning(this, tr("Error Opening %1 Folder").arg(open_target),
tr("Folder does not exist!"));
return;
}
LOG_INFO(Frontend, "Opening {} path for program_id={:016x}", open_target, program_id);
LOG_INFO(Frontend, "Opening {} path for program_id={:016x}", open_target.toStdString(),
program_id);
QDesktopServices::openUrl(QUrl::fromLocalFile(qpath));
}
void GMainWindow::OnTransferableShaderCacheOpenFile(u64 program_id) {
ASSERT(program_id != 0);
const QString shader_dir =
QString::fromStdString(FileUtil::GetUserPath(FileUtil::UserPath::ShaderDir));
const QString tranferable_shader_cache_folder_path =
QString::fromStdString(FileUtil::GetUserPath(FileUtil::UserPath::ShaderDir)) + "opengl" +
DIR_SEP + "transferable";
shader_dir + QStringLiteral("opengl") + QDir::separator() + QStringLiteral("transferable");
const QString transferable_shader_cache_file_path =
tranferable_shader_cache_folder_path + DIR_SEP +
tranferable_shader_cache_folder_path + QDir::separator() +
QString::fromStdString(fmt::format("{:016X}.bin", program_id));
if (!QFile::exists(transferable_shader_cache_file_path)) {
@@ -1216,20 +1234,21 @@ void GMainWindow::OnGameListDumpRomFS(u64 program_id, const std::string& game_pa
return;
}
bool ok;
bool ok = false;
const QStringList selections{tr("Full"), tr("Skeleton")};
const auto res = QInputDialog::getItem(
this, tr("Select RomFS Dump Mode"),
tr("Please select the how you would like the RomFS dumped.<br>Full will copy all of the "
"files into the new directory while <br>skeleton will only create the directory "
"structure."),
{"Full", "Skeleton"}, 0, false, &ok);
selections, 0, false, &ok);
if (!ok) {
failed();
vfs->DeleteDirectory(path);
return;
}
const auto full = res == "Full";
const auto full = res == selections.constFirst();
const auto entry_size = CalculateRomFSEntrySize(extracted, full);
QProgressDialog progress(tr("Extracting RomFS..."), tr("Cancel"), 0,
@@ -1259,10 +1278,11 @@ void GMainWindow::OnGameListNavigateToGamedbEntry(u64 program_id,
const auto it = FindMatchingCompatibilityEntry(compatibility_list, program_id);
QString directory;
if (it != compatibility_list.end())
if (it != compatibility_list.end()) {
directory = it->second.second;
}
QDesktopServices::openUrl(QUrl("https://yuzu-emu.org/game/" + directory));
QDesktopServices::openUrl(QUrl(QStringLiteral("https://yuzu-emu.org/game/") + directory));
}
void GMainWindow::OnGameListOpenPerGameProperties(const std::string& file) {
@@ -1293,7 +1313,9 @@ void GMainWindow::OnGameListOpenPerGameProperties(const std::string& file) {
void GMainWindow::OnMenuLoadFile() {
const QString extensions =
QString("*.").append(GameList::supported_file_extensions.join(" *.")).append(" main");
QStringLiteral("*.")
.append(GameList::supported_file_extensions.join(QStringLiteral(" *.")))
.append(QStringLiteral(" main"));
const QString file_filter = tr("Switch Executable (%1);;All Files (*.*)",
"%1 is an identifier for the Switch executable file extensions.")
.arg(extensions);
@@ -1317,9 +1339,9 @@ void GMainWindow::OnMenuLoadFolder() {
}
const QDir dir{dir_path};
const QStringList matching_main = dir.entryList(QStringList("main"), QDir::Files);
const QStringList matching_main = dir.entryList({QStringLiteral("main")}, QDir::Files);
if (matching_main.size() == 1) {
BootGame(dir.path() + DIR_SEP + matching_main[0]);
BootGame(dir.path() + QDir::separator() + matching_main[0]);
} else {
QMessageBox::warning(this, tr("Invalid Directory Selected"),
tr("The directory you have selected does not contain a 'main' file."));
@@ -1391,11 +1413,10 @@ void GMainWindow::OnMenuInstallToNAND() {
QMessageBox::Yes;
};
if (filename.endsWith("xci", Qt::CaseInsensitive) ||
filename.endsWith("nsp", Qt::CaseInsensitive)) {
if (filename.endsWith(QStringLiteral("xci"), Qt::CaseInsensitive) ||
filename.endsWith(QStringLiteral("nsp"), Qt::CaseInsensitive)) {
std::shared_ptr<FileSys::NSP> nsp;
if (filename.endsWith("nsp", Qt::CaseInsensitive)) {
if (filename.endsWith(QStringLiteral("nsp"), Qt::CaseInsensitive)) {
nsp = std::make_shared<FileSys::NSP>(
vfs->OpenFile(filename.toStdString(), FileSys::Mode::Read));
if (nsp->IsExtractedType())
@@ -1690,9 +1711,9 @@ void GMainWindow::OnConfigure() {
}
void GMainWindow::OnLoadAmiibo() {
const QString extensions{"*.bin"};
const QString extensions{QStringLiteral("*.bin")};
const QString file_filter = tr("Amiibo File (%1);; All Files (*.*)").arg(extensions);
const QString filename = QFileDialog::getOpenFileName(this, tr("Load Amiibo"), "", file_filter);
const QString filename = QFileDialog::getOpenFileName(this, tr("Load Amiibo"), {}, file_filter);
if (filename.isEmpty()) {
return;
@@ -1754,7 +1775,7 @@ void GMainWindow::OnCaptureScreenshot() {
QFileDialog png_dialog(this, tr("Capture Screenshot"), UISettings::values.screenshot_path,
tr("PNG Image (*.png)"));
png_dialog.setAcceptMode(QFileDialog::AcceptSave);
png_dialog.setDefaultSuffix("png");
png_dialog.setDefaultSuffix(QStringLiteral("png"));
if (png_dialog.exec()) {
const QString path = png_dialog.selectedFiles().first();
if (!path.isEmpty()) {
@@ -1817,17 +1838,17 @@ void GMainWindow::OnCoreError(Core::System::ResultStatus result, std::string det
"data, or other bugs.");
switch (result) {
case Core::System::ResultStatus::ErrorSystemFiles: {
QString message = "yuzu was unable to locate a Switch system archive";
QString message = tr("yuzu was unable to locate a Switch system archive");
if (!details.empty()) {
message.append(tr(": %1. ").arg(details.c_str()));
message.append(tr(": %1. ").arg(QString::fromStdString(details)));
} else {
message.append(". ");
message.append(tr(". "));
}
message.append(common_message);
answer = QMessageBox::question(this, tr("System Archive Not Found"), message,
QMessageBox::Yes | QMessageBox::No, QMessageBox::No);
status_message = "System Archive Missing";
status_message = tr("System Archive Missing");
break;
}
@@ -1836,7 +1857,7 @@ void GMainWindow::OnCoreError(Core::System::ResultStatus result, std::string det
message.append(common_message);
answer = QMessageBox::question(this, tr("Shared Fonts Not Found"), message,
QMessageBox::Yes | QMessageBox::No, QMessageBox::No);
status_message = "Shared Font Missing";
status_message = tr("Shared Font Missing");
break;
}
@@ -1852,7 +1873,7 @@ void GMainWindow::OnCoreError(Core::System::ResultStatus result, std::string det
"Continuing emulation may result in crashes, corrupted save data, or other "
"bugs."),
QMessageBox::Yes | QMessageBox::No, QMessageBox::No);
status_message = "Fatal Error encountered";
status_message = tr("Fatal Error encountered");
break;
}
@@ -1903,18 +1924,19 @@ void GMainWindow::OnReinitializeKeys(ReinitializeKeyBehavior behavior) {
};
QString errors;
if (!pdm.HasFuses())
if (!pdm.HasFuses()) {
errors += tr("- Missing fuses - Cannot derive SBK\n");
if (!pdm.HasBoot0())
}
if (!pdm.HasBoot0()) {
errors += tr("- Missing BOOT0 - Cannot derive master keys\n");
if (!pdm.HasPackage2())
}
if (!pdm.HasPackage2()) {
errors += tr("- Missing BCPKG2-1-Normal-Main - Cannot derive general keys\n");
if (!pdm.HasProdInfo())
}
if (!pdm.HasProdInfo()) {
errors += tr("- Missing PRODINFO - Cannot derive title keys\n");
}
if (!errors.isEmpty()) {
QMessageBox::warning(
this, tr("Warning Missing Derivation Components"),
tr("The following are missing from your configuration that may hinder key "
@@ -1964,13 +1986,15 @@ std::optional<u64> GMainWindow::SelectRomFSDumpTarget(const FileSys::ContentProv
std::vector<u64> romfs_tids;
romfs_tids.push_back(program_id);
for (const auto& entry : dlc_match)
for (const auto& entry : dlc_match) {
romfs_tids.push_back(entry.title_id);
}
if (romfs_tids.size() > 1) {
QStringList list{"Base"};
for (std::size_t i = 1; i < romfs_tids.size(); ++i)
QStringList list{QStringLiteral("Base")};
for (std::size_t i = 1; i < romfs_tids.size(); ++i) {
list.push_back(QStringLiteral("DLC %1").arg(romfs_tids[i] & 0x7FF));
}
bool ok;
const auto res = QInputDialog::getItem(
@@ -2082,26 +2106,32 @@ void GMainWindow::filterBarSetChecked(bool state) {
}
void GMainWindow::UpdateUITheme() {
const QString default_icons = QStringLiteral(":/icons/default");
const QString& current_theme = UISettings::values.theme;
const bool is_default_theme = current_theme == QString::fromUtf8(UISettings::themes[0].second);
QStringList theme_paths(default_theme_paths);
if (UISettings::values.theme != UISettings::themes[0].second &&
!UISettings::values.theme.isEmpty()) {
const QString theme_uri(":" + UISettings::values.theme + "/style.qss");
if (is_default_theme || current_theme.isEmpty()) {
qApp->setStyleSheet({});
setStyleSheet({});
theme_paths.append(default_icons);
QIcon::setThemeName(default_icons);
} else {
const QString theme_uri(QLatin1Char{':'} + current_theme + QStringLiteral("/style.qss"));
QFile f(theme_uri);
if (f.open(QFile::ReadOnly | QFile::Text)) {
QTextStream ts(&f);
qApp->setStyleSheet(ts.readAll());
GMainWindow::setStyleSheet(ts.readAll());
setStyleSheet(ts.readAll());
} else {
LOG_ERROR(Frontend, "Unable to set style, stylesheet file not found");
}
theme_paths.append(QStringList{":/icons/default", ":/icons/" + UISettings::values.theme});
QIcon::setThemeName(":/icons/" + UISettings::values.theme);
} else {
qApp->setStyleSheet("");
GMainWindow::setStyleSheet("");
theme_paths.append(QStringList{":/icons/default"});
QIcon::setThemeName(":/icons/default");
const QString theme_name = QStringLiteral(":/icons/") + current_theme;
theme_paths.append({default_icons, theme_name});
QIcon::setThemeName(theme_name);
}
QIcon::setThemeSearchPaths(theme_paths);
emit UpdateThemedIcons();
}
@@ -2129,8 +2159,8 @@ int main(int argc, char* argv[]) {
SCOPE_EXIT({ MicroProfileShutdown(); });
// Init settings params
QCoreApplication::setOrganizationName("yuzu team");
QCoreApplication::setApplicationName("yuzu");
QCoreApplication::setOrganizationName(QStringLiteral("yuzu team"));
QCoreApplication::setApplicationName(QStringLiteral("yuzu"));
// Enables the core to make the qt created contexts current on std::threads
QCoreApplication::setAttribute(Qt::AA_DontCheckOpenGLContextThreadAffinity);

View File

@@ -9,16 +9,19 @@
SequenceDialog::SequenceDialog(QWidget* parent) : QDialog(parent) {
setWindowTitle(tr("Enter a hotkey"));
auto* layout = new QVBoxLayout(this);
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
key_sequence = new QKeySequenceEdit;
layout->addWidget(key_sequence);
auto* buttons =
new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, Qt::Horizontal);
auto* const buttons = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
buttons->setCenterButtons(true);
auto* const layout = new QVBoxLayout(this);
layout->addWidget(key_sequence);
layout->addWidget(buttons);
connect(buttons, &QDialogButtonBox::accepted, this, &QDialog::accept);
connect(buttons, &QDialogButtonBox::rejected, this, &QDialog::reject);
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
}
SequenceDialog::~SequenceDialog() = default;