summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/yuzu/CMakeLists.txt4
-rw-r--r--src/yuzu/applets/error.cpp6
-rw-r--r--src/yuzu/applets/software_keyboard.cpp23
-rw-r--r--src/yuzu/applets/software_keyboard.h1
-rw-r--r--src/yuzu/main.cpp260
5 files changed, 168 insertions, 126 deletions
diff --git a/src/yuzu/CMakeLists.txt b/src/yuzu/CMakeLists.txt
index 7e883991a..3ea7b55d0 100644
--- a/src/yuzu/CMakeLists.txt
+++ b/src/yuzu/CMakeLists.txt
@@ -155,6 +155,10 @@ target_compile_definitions(yuzu PRIVATE
155 # Use QStringBuilder for string concatenation to reduce 155 # Use QStringBuilder for string concatenation to reduce
156 # the overall number of temporary strings created. 156 # the overall number of temporary strings created.
157 -DQT_USE_QSTRINGBUILDER 157 -DQT_USE_QSTRINGBUILDER
158
159 # Disable implicit conversions from/to C strings
160 -DQT_NO_CAST_FROM_ASCII
161 -DQT_NO_CAST_TO_ASCII
158) 162)
159 163
160if (YUZU_ENABLE_COMPATIBILITY_REPORTING) 164if (YUZU_ENABLE_COMPATIBILITY_REPORTING)
diff --git a/src/yuzu/applets/error.cpp b/src/yuzu/applets/error.cpp
index 106dde9e2..08ed57355 100644
--- a/src/yuzu/applets/error.cpp
+++ b/src/yuzu/applets/error.cpp
@@ -29,11 +29,13 @@ void QtErrorDisplay::ShowError(ResultCode error, std::function<void()> finished)
29void QtErrorDisplay::ShowErrorWithTimestamp(ResultCode error, std::chrono::seconds time, 29void QtErrorDisplay::ShowErrorWithTimestamp(ResultCode error, std::chrono::seconds time,
30 std::function<void()> finished) const { 30 std::function<void()> finished) const {
31 this->callback = std::move(finished); 31 this->callback = std::move(finished);
32
33 const QDateTime date_time = QDateTime::fromSecsSinceEpoch(time.count());
32 emit MainWindowDisplayError( 34 emit MainWindowDisplayError(
33 tr("An error occured on %1 at %2.\nPlease try again or contact the " 35 tr("An error occured on %1 at %2.\nPlease try again or contact the "
34 "developer of the software.\n\nError Code: %3-%4 (0x%5)") 36 "developer of the software.\n\nError Code: %3-%4 (0x%5)")
35 .arg(QDateTime::fromSecsSinceEpoch(time.count()).toString("dddd, MMMM d, yyyy")) 37 .arg(date_time.toString(QStringLiteral("dddd, MMMM d, yyyy")))
36 .arg(QDateTime::fromSecsSinceEpoch(time.count()).toString("h:mm:ss A")) 38 .arg(date_time.toString(QStringLiteral("h:mm:ss A")))
37 .arg(static_cast<u32>(error.module.Value()) + 2000, 4, 10, QChar::fromLatin1('0')) 39 .arg(static_cast<u32>(error.module.Value()) + 2000, 4, 10, QChar::fromLatin1('0'))
38 .arg(error.description, 4, 10, QChar::fromLatin1('0')) 40 .arg(error.description, 4, 10, QChar::fromLatin1('0'))
39 .arg(error.raw, 8, 16, QChar::fromLatin1('0'))); 41 .arg(error.raw, 8, 16, QChar::fromLatin1('0')));
diff --git a/src/yuzu/applets/software_keyboard.cpp b/src/yuzu/applets/software_keyboard.cpp
index f3eb29b25..5223ec977 100644
--- a/src/yuzu/applets/software_keyboard.cpp
+++ b/src/yuzu/applets/software_keyboard.cpp
@@ -18,23 +18,30 @@ QtSoftwareKeyboardValidator::QtSoftwareKeyboardValidator(
18 : parameters(std::move(parameters)) {} 18 : parameters(std::move(parameters)) {}
19 19
20QValidator::State QtSoftwareKeyboardValidator::validate(QString& input, int& pos) const { 20QValidator::State QtSoftwareKeyboardValidator::validate(QString& input, int& pos) const {
21 if (input.size() > parameters.max_length) 21 if (input.size() > static_cast<s64>(parameters.max_length)) {
22 return Invalid; 22 return Invalid;
23 if (parameters.disable_space && input.contains(' ')) 23 }
24 if (parameters.disable_space && input.contains(QLatin1Char{' '})) {
24 return Invalid; 25 return Invalid;
25 if (parameters.disable_address && input.contains('@')) 26 }
27 if (parameters.disable_address && input.contains(QLatin1Char{'@'})) {
26 return Invalid; 28 return Invalid;
27 if (parameters.disable_percent && input.contains('%')) 29 }
30 if (parameters.disable_percent && input.contains(QLatin1Char{'%'})) {
28 return Invalid; 31 return Invalid;
29 if (parameters.disable_slash && (input.contains('/') || input.contains('\\'))) 32 }
33 if (parameters.disable_slash &&
34 (input.contains(QLatin1Char{'/'}) || input.contains(QLatin1Char{'\\'}))) {
30 return Invalid; 35 return Invalid;
36 }
31 if (parameters.disable_number && 37 if (parameters.disable_number &&
32 std::any_of(input.begin(), input.end(), [](QChar c) { return c.isDigit(); })) { 38 std::any_of(input.begin(), input.end(), [](QChar c) { return c.isDigit(); })) {
33 return Invalid; 39 return Invalid;
34 } 40 }
35 41
36 if (parameters.disable_download_code && 42 if (parameters.disable_download_code && std::any_of(input.begin(), input.end(), [](QChar c) {
37 std::any_of(input.begin(), input.end(), [](QChar c) { return c == 'O' || c == 'I'; })) { 43 return c == QLatin1Char{'O'} || c == QLatin1Char{'I'};
44 })) {
38 return Invalid; 45 return Invalid;
39 } 46 }
40 47
@@ -142,7 +149,7 @@ void QtSoftwareKeyboard::SendTextCheckDialog(std::u16string error_message,
142void QtSoftwareKeyboard::MainWindowFinishedText(std::optional<std::u16string> text) { 149void QtSoftwareKeyboard::MainWindowFinishedText(std::optional<std::u16string> text) {
143 // Acquire the HLE mutex 150 // Acquire the HLE mutex
144 std::lock_guard lock{HLE::g_hle_lock}; 151 std::lock_guard lock{HLE::g_hle_lock};
145 text_output(text); 152 text_output(std::move(text));
146} 153}
147 154
148void QtSoftwareKeyboard::MainWindowFinishedCheckDialog() { 155void QtSoftwareKeyboard::MainWindowFinishedCheckDialog() {
diff --git a/src/yuzu/applets/software_keyboard.h b/src/yuzu/applets/software_keyboard.h
index c63720ba4..78c5a042b 100644
--- a/src/yuzu/applets/software_keyboard.h
+++ b/src/yuzu/applets/software_keyboard.h
@@ -6,7 +6,6 @@
6 6
7#include <QDialog> 7#include <QDialog>
8#include <QValidator> 8#include <QValidator>
9#include "common/assert.h"
10#include "core/frontend/applets/software_keyboard.h" 9#include "core/frontend/applets/software_keyboard.h"
11 10
12class GMainWindow; 11class GMainWindow;
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index a59abf6e8..cef2cc1ae 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -281,7 +281,7 @@ void GMainWindow::SoftwareKeyboardInvokeCheckDialog(std::u16string error_message
281void GMainWindow::WebBrowserOpenPage(std::string_view filename, std::string_view additional_args) { 281void GMainWindow::WebBrowserOpenPage(std::string_view filename, std::string_view additional_args) {
282 NXInputWebEngineView web_browser_view(this); 282 NXInputWebEngineView web_browser_view(this);
283 283
284 // Scope to contain the QProgressDialog for initalization 284 // Scope to contain the QProgressDialog for initialization
285 { 285 {
286 QProgressDialog progress(this); 286 QProgressDialog progress(this);
287 progress.setMinimumDuration(200); 287 progress.setMinimumDuration(200);
@@ -301,7 +301,7 @@ void GMainWindow::WebBrowserOpenPage(std::string_view filename, std::string_view
301 QWebEngineScript nx_shim; 301 QWebEngineScript nx_shim;
302 nx_shim.setSourceCode(GetNXShimInjectionScript()); 302 nx_shim.setSourceCode(GetNXShimInjectionScript());
303 nx_shim.setWorldId(QWebEngineScript::MainWorld); 303 nx_shim.setWorldId(QWebEngineScript::MainWorld);
304 nx_shim.setName("nx_inject.js"); 304 nx_shim.setName(QStringLiteral("nx_inject.js"));
305 nx_shim.setInjectionPoint(QWebEngineScript::DocumentCreation); 305 nx_shim.setInjectionPoint(QWebEngineScript::DocumentCreation);
306 nx_shim.setRunsOnSubFrames(true); 306 nx_shim.setRunsOnSubFrames(true);
307 web_browser_view.page()->profile()->scripts()->insert(nx_shim); 307 web_browser_view.page()->profile()->scripts()->insert(nx_shim);
@@ -347,7 +347,7 @@ void GMainWindow::WebBrowserOpenPage(std::string_view filename, std::string_view
347 const auto fire_js_keypress = [&web_browser_view](u32 key_code) { 347 const auto fire_js_keypress = [&web_browser_view](u32 key_code) {
348 web_browser_view.page()->runJavaScript( 348 web_browser_view.page()->runJavaScript(
349 QStringLiteral("document.dispatchEvent(new KeyboardEvent('keydown', {'key': %1}));") 349 QStringLiteral("document.dispatchEvent(new KeyboardEvent('keydown', {'key': %1}));")
350 .arg(QString::fromStdString(std::to_string(key_code)))); 350 .arg(key_code));
351 }; 351 };
352 352
353 QMessageBox::information( 353 QMessageBox::information(
@@ -468,7 +468,7 @@ void GMainWindow::InitializeWidgets() {
468 statusBar()->addPermanentWidget(label, 0); 468 statusBar()->addPermanentWidget(label, 0);
469 } 469 }
470 statusBar()->setVisible(true); 470 statusBar()->setVisible(true);
471 setStyleSheet("QStatusBar::item{border: none;}"); 471 setStyleSheet(QStringLiteral("QStatusBar::item{border: none;}"));
472} 472}
473 473
474void GMainWindow::InitializeDebugWidgets() { 474void GMainWindow::InitializeDebugWidgets() {
@@ -518,58 +518,67 @@ void GMainWindow::InitializeRecentFileMenuActions() {
518void GMainWindow::InitializeHotkeys() { 518void GMainWindow::InitializeHotkeys() {
519 hotkey_registry.LoadHotkeys(); 519 hotkey_registry.LoadHotkeys();
520 520
521 ui.action_Load_File->setShortcut(hotkey_registry.GetKeySequence("Main Window", "Load File")); 521 const QString main_window = QStringLiteral("Main Window");
522 const QString load_file = QStringLiteral("Load File");
523 const QString exit_yuzu = QStringLiteral("Exit yuzu");
524 const QString stop_emulation = QStringLiteral("Stop Emulation");
525 const QString toggle_filter_bar = QStringLiteral("Toggle Filter Bar");
526 const QString toggle_status_bar = QStringLiteral("Toggle Status Bar");
527 const QString fullscreen = QStringLiteral("Fullscreen");
528
529 ui.action_Load_File->setShortcut(hotkey_registry.GetKeySequence(main_window, load_file));
522 ui.action_Load_File->setShortcutContext( 530 ui.action_Load_File->setShortcutContext(
523 hotkey_registry.GetShortcutContext("Main Window", "Load File")); 531 hotkey_registry.GetShortcutContext(main_window, load_file));
524 532
525 ui.action_Exit->setShortcut(hotkey_registry.GetKeySequence("Main Window", "Exit yuzu")); 533 ui.action_Exit->setShortcut(hotkey_registry.GetKeySequence(main_window, exit_yuzu));
526 ui.action_Exit->setShortcutContext( 534 ui.action_Exit->setShortcutContext(hotkey_registry.GetShortcutContext(main_window, exit_yuzu));
527 hotkey_registry.GetShortcutContext("Main Window", "Exit yuzu"));
528 535
529 ui.action_Stop->setShortcut(hotkey_registry.GetKeySequence("Main Window", "Stop Emulation")); 536 ui.action_Stop->setShortcut(hotkey_registry.GetKeySequence(main_window, stop_emulation));
530 ui.action_Stop->setShortcutContext( 537 ui.action_Stop->setShortcutContext(
531 hotkey_registry.GetShortcutContext("Main Window", "Stop Emulation")); 538 hotkey_registry.GetShortcutContext(main_window, stop_emulation));
532 539
533 ui.action_Show_Filter_Bar->setShortcut( 540 ui.action_Show_Filter_Bar->setShortcut(
534 hotkey_registry.GetKeySequence("Main Window", "Toggle Filter Bar")); 541 hotkey_registry.GetKeySequence(main_window, toggle_filter_bar));
535 ui.action_Show_Filter_Bar->setShortcutContext( 542 ui.action_Show_Filter_Bar->setShortcutContext(
536 hotkey_registry.GetShortcutContext("Main Window", "Toggle Filter Bar")); 543 hotkey_registry.GetShortcutContext(main_window, toggle_filter_bar));
537 544
538 ui.action_Show_Status_Bar->setShortcut( 545 ui.action_Show_Status_Bar->setShortcut(
539 hotkey_registry.GetKeySequence("Main Window", "Toggle Status Bar")); 546 hotkey_registry.GetKeySequence(main_window, toggle_status_bar));
540 ui.action_Show_Status_Bar->setShortcutContext( 547 ui.action_Show_Status_Bar->setShortcutContext(
541 hotkey_registry.GetShortcutContext("Main Window", "Toggle Status Bar")); 548 hotkey_registry.GetShortcutContext(main_window, toggle_status_bar));
542 549
543 connect(hotkey_registry.GetHotkey("Main Window", "Load File", this), &QShortcut::activated, 550 connect(hotkey_registry.GetHotkey(main_window, QStringLiteral("Load File"), this),
544 this, &GMainWindow::OnMenuLoadFile); 551 &QShortcut::activated, this, &GMainWindow::OnMenuLoadFile);
545 connect(hotkey_registry.GetHotkey("Main Window", "Continue/Pause Emulation", this), 552 connect(
546 &QShortcut::activated, this, [&] { 553 hotkey_registry.GetHotkey(main_window, QStringLiteral("Continue/Pause Emulation"), this),
547 if (emulation_running) { 554 &QShortcut::activated, this, [&] {
548 if (emu_thread->IsRunning()) { 555 if (emulation_running) {
549 OnPauseGame(); 556 if (emu_thread->IsRunning()) {
550 } else { 557 OnPauseGame();
551 OnStartGame(); 558 } else {
552 } 559 OnStartGame();
553 } 560 }
554 }); 561 }
555 connect(hotkey_registry.GetHotkey("Main Window", "Restart Emulation", this), 562 });
563 connect(hotkey_registry.GetHotkey(main_window, QStringLiteral("Restart Emulation"), this),
556 &QShortcut::activated, this, [this] { 564 &QShortcut::activated, this, [this] {
557 if (!Core::System::GetInstance().IsPoweredOn()) 565 if (!Core::System::GetInstance().IsPoweredOn()) {
558 return; 566 return;
559 BootGame(QString(game_path)); 567 }
568 BootGame(game_path);
560 }); 569 });
561 connect(hotkey_registry.GetHotkey("Main Window", "Fullscreen", render_window), 570 connect(hotkey_registry.GetHotkey(main_window, fullscreen, render_window),
562 &QShortcut::activated, ui.action_Fullscreen, &QAction::trigger); 571 &QShortcut::activated, ui.action_Fullscreen, &QAction::trigger);
563 connect(hotkey_registry.GetHotkey("Main Window", "Fullscreen", render_window), 572 connect(hotkey_registry.GetHotkey(main_window, fullscreen, render_window),
564 &QShortcut::activatedAmbiguously, ui.action_Fullscreen, &QAction::trigger); 573 &QShortcut::activatedAmbiguously, ui.action_Fullscreen, &QAction::trigger);
565 connect(hotkey_registry.GetHotkey("Main Window", "Exit Fullscreen", this), 574 connect(hotkey_registry.GetHotkey(main_window, QStringLiteral("Exit Fullscreen"), this),
566 &QShortcut::activated, this, [&] { 575 &QShortcut::activated, this, [&] {
567 if (emulation_running) { 576 if (emulation_running) {
568 ui.action_Fullscreen->setChecked(false); 577 ui.action_Fullscreen->setChecked(false);
569 ToggleFullscreen(); 578 ToggleFullscreen();
570 } 579 }
571 }); 580 });
572 connect(hotkey_registry.GetHotkey("Main Window", "Toggle Speed Limit", this), 581 connect(hotkey_registry.GetHotkey(main_window, QStringLiteral("Toggle Speed Limit"), this),
573 &QShortcut::activated, this, [&] { 582 &QShortcut::activated, this, [&] {
574 Settings::values.use_frame_limit = !Settings::values.use_frame_limit; 583 Settings::values.use_frame_limit = !Settings::values.use_frame_limit;
575 UpdateStatusBar(); 584 UpdateStatusBar();
@@ -578,33 +587,33 @@ void GMainWindow::InitializeHotkeys() {
578 // MSVC occurs and we make it a requirement (see: 587 // MSVC occurs and we make it a requirement (see:
579 // https://developercommunity.visualstudio.com/content/problem/93922/constexprs-are-trying-to-be-captured-in-lambda-fun.html) 588 // https://developercommunity.visualstudio.com/content/problem/93922/constexprs-are-trying-to-be-captured-in-lambda-fun.html)
580 static constexpr u16 SPEED_LIMIT_STEP = 5; 589 static constexpr u16 SPEED_LIMIT_STEP = 5;
581 connect(hotkey_registry.GetHotkey("Main Window", "Increase Speed Limit", this), 590 connect(hotkey_registry.GetHotkey(main_window, QStringLiteral("Increase Speed Limit"), this),
582 &QShortcut::activated, this, [&] { 591 &QShortcut::activated, this, [&] {
583 if (Settings::values.frame_limit < 9999 - SPEED_LIMIT_STEP) { 592 if (Settings::values.frame_limit < 9999 - SPEED_LIMIT_STEP) {
584 Settings::values.frame_limit += SPEED_LIMIT_STEP; 593 Settings::values.frame_limit += SPEED_LIMIT_STEP;
585 UpdateStatusBar(); 594 UpdateStatusBar();
586 } 595 }
587 }); 596 });
588 connect(hotkey_registry.GetHotkey("Main Window", "Decrease Speed Limit", this), 597 connect(hotkey_registry.GetHotkey(main_window, QStringLiteral("Decrease Speed Limit"), this),
589 &QShortcut::activated, this, [&] { 598 &QShortcut::activated, this, [&] {
590 if (Settings::values.frame_limit > SPEED_LIMIT_STEP) { 599 if (Settings::values.frame_limit > SPEED_LIMIT_STEP) {
591 Settings::values.frame_limit -= SPEED_LIMIT_STEP; 600 Settings::values.frame_limit -= SPEED_LIMIT_STEP;
592 UpdateStatusBar(); 601 UpdateStatusBar();
593 } 602 }
594 }); 603 });
595 connect(hotkey_registry.GetHotkey("Main Window", "Load Amiibo", this), &QShortcut::activated, 604 connect(hotkey_registry.GetHotkey(main_window, QStringLiteral("Load Amiibo"), this),
596 this, [&] { 605 &QShortcut::activated, this, [&] {
597 if (ui.action_Load_Amiibo->isEnabled()) { 606 if (ui.action_Load_Amiibo->isEnabled()) {
598 OnLoadAmiibo(); 607 OnLoadAmiibo();
599 } 608 }
600 }); 609 });
601 connect(hotkey_registry.GetHotkey("Main Window", "Capture Screenshot", this), 610 connect(hotkey_registry.GetHotkey(main_window, QStringLiteral("Capture Screenshot"), this),
602 &QShortcut::activated, this, [&] { 611 &QShortcut::activated, this, [&] {
603 if (emu_thread->IsRunning()) { 612 if (emu_thread->IsRunning()) {
604 OnCaptureScreenshot(); 613 OnCaptureScreenshot();
605 } 614 }
606 }); 615 });
607 connect(hotkey_registry.GetHotkey("Main Window", "Change Docked Mode", this), 616 connect(hotkey_registry.GetHotkey(main_window, QStringLiteral("Change Docked Mode"), this),
608 &QShortcut::activated, this, [&] { 617 &QShortcut::activated, this, [&] {
609 Settings::values.use_docked_mode = !Settings::values.use_docked_mode; 618 Settings::values.use_docked_mode = !Settings::values.use_docked_mode;
610 OnDockedModeChanged(!Settings::values.use_docked_mode, 619 OnDockedModeChanged(!Settings::values.use_docked_mode,
@@ -705,7 +714,9 @@ void GMainWindow::ConnectMenuEvents() {
705 714
706 // Fullscreen 715 // Fullscreen
707 ui.action_Fullscreen->setShortcut( 716 ui.action_Fullscreen->setShortcut(
708 hotkey_registry.GetHotkey("Main Window", "Fullscreen", this)->key()); 717 hotkey_registry
718 .GetHotkey(QStringLiteral("Main Window"), QStringLiteral("Fullscreen"), this)
719 ->key());
709 connect(ui.action_Fullscreen, &QAction::triggered, this, &GMainWindow::ToggleFullscreen); 720 connect(ui.action_Fullscreen, &QAction::triggered, this, &GMainWindow::ToggleFullscreen);
710 721
711 // Movie 722 // Movie
@@ -742,25 +753,33 @@ void GMainWindow::OnDisplayTitleBars(bool show) {
742QStringList GMainWindow::GetUnsupportedGLExtensions() { 753QStringList GMainWindow::GetUnsupportedGLExtensions() {
743 QStringList unsupported_ext; 754 QStringList unsupported_ext;
744 755
745 if (!GLAD_GL_ARB_direct_state_access) 756 if (!GLAD_GL_ARB_direct_state_access) {
746 unsupported_ext.append("ARB_direct_state_access"); 757 unsupported_ext.append(QStringLiteral("ARB_direct_state_access"));
747 if (!GLAD_GL_ARB_vertex_type_10f_11f_11f_rev) 758 }
748 unsupported_ext.append("ARB_vertex_type_10f_11f_11f_rev"); 759 if (!GLAD_GL_ARB_vertex_type_10f_11f_11f_rev) {
749 if (!GLAD_GL_ARB_texture_mirror_clamp_to_edge) 760 unsupported_ext.append(QStringLiteral("ARB_vertex_type_10f_11f_11f_rev"));
750 unsupported_ext.append("ARB_texture_mirror_clamp_to_edge"); 761 }
751 if (!GLAD_GL_ARB_multi_bind) 762 if (!GLAD_GL_ARB_texture_mirror_clamp_to_edge) {
752 unsupported_ext.append("ARB_multi_bind"); 763 unsupported_ext.append(QStringLiteral("ARB_texture_mirror_clamp_to_edge"));
764 }
765 if (!GLAD_GL_ARB_multi_bind) {
766 unsupported_ext.append(QStringLiteral("ARB_multi_bind"));
767 }
753 768
754 // Extensions required to support some texture formats. 769 // Extensions required to support some texture formats.
755 if (!GLAD_GL_EXT_texture_compression_s3tc) 770 if (!GLAD_GL_EXT_texture_compression_s3tc) {
756 unsupported_ext.append("EXT_texture_compression_s3tc"); 771 unsupported_ext.append(QStringLiteral("EXT_texture_compression_s3tc"));
757 if (!GLAD_GL_ARB_texture_compression_rgtc) 772 }
758 unsupported_ext.append("ARB_texture_compression_rgtc"); 773 if (!GLAD_GL_ARB_texture_compression_rgtc) {
759 if (!GLAD_GL_ARB_depth_buffer_float) 774 unsupported_ext.append(QStringLiteral("ARB_texture_compression_rgtc"));
760 unsupported_ext.append("ARB_depth_buffer_float"); 775 }
761 776 if (!GLAD_GL_ARB_depth_buffer_float) {
762 for (const QString& ext : unsupported_ext) 777 unsupported_ext.append(QStringLiteral("ARB_depth_buffer_float"));
778 }
779
780 for (const QString& ext : unsupported_ext) {
763 LOG_CRITICAL(Frontend, "Unsupported GL extension: {}", ext.toStdString()); 781 LOG_CRITICAL(Frontend, "Unsupported GL extension: {}", ext.toStdString());
782 }
764 783
765 return unsupported_ext; 784 return unsupported_ext;
766} 785}
@@ -782,13 +801,13 @@ bool GMainWindow::LoadROM(const QString& filename) {
782 } 801 }
783 } 802 }
784 803
785 QStringList unsupported_gl_extensions = GetUnsupportedGLExtensions(); 804 const QStringList unsupported_gl_extensions = GetUnsupportedGLExtensions();
786 if (!unsupported_gl_extensions.empty()) { 805 if (!unsupported_gl_extensions.empty()) {
787 QMessageBox::critical(this, tr("Error while initializing OpenGL Core!"), 806 QMessageBox::critical(this, tr("Error while initializing OpenGL Core!"),
788 tr("Your GPU may not support one or more required OpenGL" 807 tr("Your GPU may not support one or more required OpenGL"
789 "extensions. Please ensure you have the latest graphics " 808 "extensions. Please ensure you have the latest graphics "
790 "driver.<br><br>Unsupported extensions:<br>") + 809 "driver.<br><br>Unsupported extensions:<br>") +
791 unsupported_gl_extensions.join("<br>")); 810 unsupported_gl_extensions.join(QStringLiteral("<br>")));
792 return false; 811 return false;
793 } 812 }
794 813
@@ -1007,7 +1026,7 @@ void GMainWindow::UpdateRecentFiles() {
1007 std::min(UISettings::values.recent_files.size(), max_recent_files_item); 1026 std::min(UISettings::values.recent_files.size(), max_recent_files_item);
1008 1027
1009 for (int i = 0; i < num_recent_files; i++) { 1028 for (int i = 0; i < num_recent_files; i++) {
1010 const QString text = QString("&%1. %2").arg(i + 1).arg( 1029 const QString text = QStringLiteral("&%1. %2").arg(i + 1).arg(
1011 QFileInfo(UISettings::values.recent_files[i]).fileName()); 1030 QFileInfo(UISettings::values.recent_files[i]).fileName());
1012 actions_recent_files[i]->setText(text); 1031 actions_recent_files[i]->setText(text);
1013 actions_recent_files[i]->setData(UISettings::values.recent_files[i]); 1032 actions_recent_files[i]->setData(UISettings::values.recent_files[i]);
@@ -1029,10 +1048,10 @@ void GMainWindow::OnGameListLoadFile(QString game_path) {
1029 1048
1030void GMainWindow::OnGameListOpenFolder(u64 program_id, GameListOpenTarget target) { 1049void GMainWindow::OnGameListOpenFolder(u64 program_id, GameListOpenTarget target) {
1031 std::string path; 1050 std::string path;
1032 std::string open_target; 1051 QString open_target;
1033 switch (target) { 1052 switch (target) {
1034 case GameListOpenTarget::SaveData: { 1053 case GameListOpenTarget::SaveData: {
1035 open_target = "Save Data"; 1054 open_target = tr("Save Data");
1036 const std::string nand_dir = FileUtil::GetUserPath(FileUtil::UserPath::NANDDir); 1055 const std::string nand_dir = FileUtil::GetUserPath(FileUtil::UserPath::NANDDir);
1037 ASSERT(program_id != 0); 1056 ASSERT(program_id != 0);
1038 1057
@@ -1069,7 +1088,7 @@ void GMainWindow::OnGameListOpenFolder(u64 program_id, GameListOpenTarget target
1069 break; 1088 break;
1070 } 1089 }
1071 case GameListOpenTarget::ModData: { 1090 case GameListOpenTarget::ModData: {
1072 open_target = "Mod Data"; 1091 open_target = tr("Mod Data");
1073 const auto load_dir = FileUtil::GetUserPath(FileUtil::UserPath::LoadDir); 1092 const auto load_dir = FileUtil::GetUserPath(FileUtil::UserPath::LoadDir);
1074 path = fmt::format("{}{:016X}", load_dir, program_id); 1093 path = fmt::format("{}{:016X}", load_dir, program_id);
1075 break; 1094 break;
@@ -1079,27 +1098,26 @@ void GMainWindow::OnGameListOpenFolder(u64 program_id, GameListOpenTarget target
1079 } 1098 }
1080 1099
1081 const QString qpath = QString::fromStdString(path); 1100 const QString qpath = QString::fromStdString(path);
1082
1083 const QDir dir(qpath); 1101 const QDir dir(qpath);
1084 if (!dir.exists()) { 1102 if (!dir.exists()) {
1085 QMessageBox::warning(this, 1103 QMessageBox::warning(this, tr("Error Opening %1 Folder").arg(open_target),
1086 tr("Error Opening %1 Folder").arg(QString::fromStdString(open_target)),
1087 tr("Folder does not exist!")); 1104 tr("Folder does not exist!"));
1088 return; 1105 return;
1089 } 1106 }
1090 LOG_INFO(Frontend, "Opening {} path for program_id={:016x}", open_target, program_id); 1107 LOG_INFO(Frontend, "Opening {} path for program_id={:016x}", open_target.toStdString(),
1108 program_id);
1091 QDesktopServices::openUrl(QUrl::fromLocalFile(qpath)); 1109 QDesktopServices::openUrl(QUrl::fromLocalFile(qpath));
1092} 1110}
1093 1111
1094void GMainWindow::OnTransferableShaderCacheOpenFile(u64 program_id) { 1112void GMainWindow::OnTransferableShaderCacheOpenFile(u64 program_id) {
1095 ASSERT(program_id != 0); 1113 ASSERT(program_id != 0);
1096 1114
1115 const QString shader_dir =
1116 QString::fromStdString(FileUtil::GetUserPath(FileUtil::UserPath::ShaderDir));
1097 const QString tranferable_shader_cache_folder_path = 1117 const QString tranferable_shader_cache_folder_path =
1098 QString::fromStdString(FileUtil::GetUserPath(FileUtil::UserPath::ShaderDir)) + "opengl" + 1118 shader_dir + QStringLiteral("opengl") + QDir::separator() + QStringLiteral("transferable");
1099 DIR_SEP + "transferable";
1100
1101 const QString transferable_shader_cache_file_path = 1119 const QString transferable_shader_cache_file_path =
1102 tranferable_shader_cache_folder_path + DIR_SEP + 1120 tranferable_shader_cache_folder_path + QDir::separator() +
1103 QString::fromStdString(fmt::format("{:016X}.bin", program_id)); 1121 QString::fromStdString(fmt::format("{:016X}.bin", program_id));
1104 1122
1105 if (!QFile::exists(transferable_shader_cache_file_path)) { 1123 if (!QFile::exists(transferable_shader_cache_file_path)) {
@@ -1216,20 +1234,21 @@ void GMainWindow::OnGameListDumpRomFS(u64 program_id, const std::string& game_pa
1216 return; 1234 return;
1217 } 1235 }
1218 1236
1219 bool ok; 1237 bool ok = false;
1238 const QStringList selections{tr("Full"), tr("Skeleton")};
1220 const auto res = QInputDialog::getItem( 1239 const auto res = QInputDialog::getItem(
1221 this, tr("Select RomFS Dump Mode"), 1240 this, tr("Select RomFS Dump Mode"),
1222 tr("Please select the how you would like the RomFS dumped.<br>Full will copy all of the " 1241 tr("Please select the how you would like the RomFS dumped.<br>Full will copy all of the "
1223 "files into the new directory while <br>skeleton will only create the directory " 1242 "files into the new directory while <br>skeleton will only create the directory "
1224 "structure."), 1243 "structure."),
1225 {"Full", "Skeleton"}, 0, false, &ok); 1244 selections, 0, false, &ok);
1226 if (!ok) { 1245 if (!ok) {
1227 failed(); 1246 failed();
1228 vfs->DeleteDirectory(path); 1247 vfs->DeleteDirectory(path);
1229 return; 1248 return;
1230 } 1249 }
1231 1250
1232 const auto full = res == "Full"; 1251 const auto full = res == selections.constFirst();
1233 const auto entry_size = CalculateRomFSEntrySize(extracted, full); 1252 const auto entry_size = CalculateRomFSEntrySize(extracted, full);
1234 1253
1235 QProgressDialog progress(tr("Extracting RomFS..."), tr("Cancel"), 0, 1254 QProgressDialog progress(tr("Extracting RomFS..."), tr("Cancel"), 0,
@@ -1259,10 +1278,11 @@ void GMainWindow::OnGameListNavigateToGamedbEntry(u64 program_id,
1259 const auto it = FindMatchingCompatibilityEntry(compatibility_list, program_id); 1278 const auto it = FindMatchingCompatibilityEntry(compatibility_list, program_id);
1260 1279
1261 QString directory; 1280 QString directory;
1262 if (it != compatibility_list.end()) 1281 if (it != compatibility_list.end()) {
1263 directory = it->second.second; 1282 directory = it->second.second;
1283 }
1264 1284
1265 QDesktopServices::openUrl(QUrl("https://yuzu-emu.org/game/" + directory)); 1285 QDesktopServices::openUrl(QUrl(QStringLiteral("https://yuzu-emu.org/game/") + directory));
1266} 1286}
1267 1287
1268void GMainWindow::OnGameListOpenPerGameProperties(const std::string& file) { 1288void GMainWindow::OnGameListOpenPerGameProperties(const std::string& file) {
@@ -1293,7 +1313,9 @@ void GMainWindow::OnGameListOpenPerGameProperties(const std::string& file) {
1293 1313
1294void GMainWindow::OnMenuLoadFile() { 1314void GMainWindow::OnMenuLoadFile() {
1295 const QString extensions = 1315 const QString extensions =
1296 QString("*.").append(GameList::supported_file_extensions.join(" *.")).append(" main"); 1316 QStringLiteral("*.")
1317 .append(GameList::supported_file_extensions.join(QStringLiteral(" *.")))
1318 .append(QStringLiteral(" main"));
1297 const QString file_filter = tr("Switch Executable (%1);;All Files (*.*)", 1319 const QString file_filter = tr("Switch Executable (%1);;All Files (*.*)",
1298 "%1 is an identifier for the Switch executable file extensions.") 1320 "%1 is an identifier for the Switch executable file extensions.")
1299 .arg(extensions); 1321 .arg(extensions);
@@ -1317,9 +1339,9 @@ void GMainWindow::OnMenuLoadFolder() {
1317 } 1339 }
1318 1340
1319 const QDir dir{dir_path}; 1341 const QDir dir{dir_path};
1320 const QStringList matching_main = dir.entryList(QStringList("main"), QDir::Files); 1342 const QStringList matching_main = dir.entryList({QStringLiteral("main")}, QDir::Files);
1321 if (matching_main.size() == 1) { 1343 if (matching_main.size() == 1) {
1322 BootGame(dir.path() + DIR_SEP + matching_main[0]); 1344 BootGame(dir.path() + QDir::separator() + matching_main[0]);
1323 } else { 1345 } else {
1324 QMessageBox::warning(this, tr("Invalid Directory Selected"), 1346 QMessageBox::warning(this, tr("Invalid Directory Selected"),
1325 tr("The directory you have selected does not contain a 'main' file.")); 1347 tr("The directory you have selected does not contain a 'main' file."));
@@ -1391,11 +1413,10 @@ void GMainWindow::OnMenuInstallToNAND() {
1391 QMessageBox::Yes; 1413 QMessageBox::Yes;
1392 }; 1414 };
1393 1415
1394 if (filename.endsWith("xci", Qt::CaseInsensitive) || 1416 if (filename.endsWith(QStringLiteral("xci"), Qt::CaseInsensitive) ||
1395 filename.endsWith("nsp", Qt::CaseInsensitive)) { 1417 filename.endsWith(QStringLiteral("nsp"), Qt::CaseInsensitive)) {
1396
1397 std::shared_ptr<FileSys::NSP> nsp; 1418 std::shared_ptr<FileSys::NSP> nsp;
1398 if (filename.endsWith("nsp", Qt::CaseInsensitive)) { 1419 if (filename.endsWith(QStringLiteral("nsp"), Qt::CaseInsensitive)) {
1399 nsp = std::make_shared<FileSys::NSP>( 1420 nsp = std::make_shared<FileSys::NSP>(
1400 vfs->OpenFile(filename.toStdString(), FileSys::Mode::Read)); 1421 vfs->OpenFile(filename.toStdString(), FileSys::Mode::Read));
1401 if (nsp->IsExtractedType()) 1422 if (nsp->IsExtractedType())
@@ -1690,9 +1711,9 @@ void GMainWindow::OnConfigure() {
1690} 1711}
1691 1712
1692void GMainWindow::OnLoadAmiibo() { 1713void GMainWindow::OnLoadAmiibo() {
1693 const QString extensions{"*.bin"}; 1714 const QString extensions{QStringLiteral("*.bin")};
1694 const QString file_filter = tr("Amiibo File (%1);; All Files (*.*)").arg(extensions); 1715 const QString file_filter = tr("Amiibo File (%1);; All Files (*.*)").arg(extensions);
1695 const QString filename = QFileDialog::getOpenFileName(this, tr("Load Amiibo"), "", file_filter); 1716 const QString filename = QFileDialog::getOpenFileName(this, tr("Load Amiibo"), {}, file_filter);
1696 1717
1697 if (filename.isEmpty()) { 1718 if (filename.isEmpty()) {
1698 return; 1719 return;
@@ -1754,7 +1775,7 @@ void GMainWindow::OnCaptureScreenshot() {
1754 QFileDialog png_dialog(this, tr("Capture Screenshot"), UISettings::values.screenshot_path, 1775 QFileDialog png_dialog(this, tr("Capture Screenshot"), UISettings::values.screenshot_path,
1755 tr("PNG Image (*.png)")); 1776 tr("PNG Image (*.png)"));
1756 png_dialog.setAcceptMode(QFileDialog::AcceptSave); 1777 png_dialog.setAcceptMode(QFileDialog::AcceptSave);
1757 png_dialog.setDefaultSuffix("png"); 1778 png_dialog.setDefaultSuffix(QStringLiteral("png"));
1758 if (png_dialog.exec()) { 1779 if (png_dialog.exec()) {
1759 const QString path = png_dialog.selectedFiles().first(); 1780 const QString path = png_dialog.selectedFiles().first();
1760 if (!path.isEmpty()) { 1781 if (!path.isEmpty()) {
@@ -1817,17 +1838,17 @@ void GMainWindow::OnCoreError(Core::System::ResultStatus result, std::string det
1817 "data, or other bugs."); 1838 "data, or other bugs.");
1818 switch (result) { 1839 switch (result) {
1819 case Core::System::ResultStatus::ErrorSystemFiles: { 1840 case Core::System::ResultStatus::ErrorSystemFiles: {
1820 QString message = "yuzu was unable to locate a Switch system archive"; 1841 QString message = tr("yuzu was unable to locate a Switch system archive");
1821 if (!details.empty()) { 1842 if (!details.empty()) {
1822 message.append(tr(": %1. ").arg(details.c_str())); 1843 message.append(tr(": %1. ").arg(QString::fromStdString(details)));
1823 } else { 1844 } else {
1824 message.append(". "); 1845 message.append(tr(". "));
1825 } 1846 }
1826 message.append(common_message); 1847 message.append(common_message);
1827 1848
1828 answer = QMessageBox::question(this, tr("System Archive Not Found"), message, 1849 answer = QMessageBox::question(this, tr("System Archive Not Found"), message,
1829 QMessageBox::Yes | QMessageBox::No, QMessageBox::No); 1850 QMessageBox::Yes | QMessageBox::No, QMessageBox::No);
1830 status_message = "System Archive Missing"; 1851 status_message = tr("System Archive Missing");
1831 break; 1852 break;
1832 } 1853 }
1833 1854
@@ -1836,7 +1857,7 @@ void GMainWindow::OnCoreError(Core::System::ResultStatus result, std::string det
1836 message.append(common_message); 1857 message.append(common_message);
1837 answer = QMessageBox::question(this, tr("Shared Fonts Not Found"), message, 1858 answer = QMessageBox::question(this, tr("Shared Fonts Not Found"), message,
1838 QMessageBox::Yes | QMessageBox::No, QMessageBox::No); 1859 QMessageBox::Yes | QMessageBox::No, QMessageBox::No);
1839 status_message = "Shared Font Missing"; 1860 status_message = tr("Shared Font Missing");
1840 break; 1861 break;
1841 } 1862 }
1842 1863
@@ -1852,7 +1873,7 @@ void GMainWindow::OnCoreError(Core::System::ResultStatus result, std::string det
1852 "Continuing emulation may result in crashes, corrupted save data, or other " 1873 "Continuing emulation may result in crashes, corrupted save data, or other "
1853 "bugs."), 1874 "bugs."),
1854 QMessageBox::Yes | QMessageBox::No, QMessageBox::No); 1875 QMessageBox::Yes | QMessageBox::No, QMessageBox::No);
1855 status_message = "Fatal Error encountered"; 1876 status_message = tr("Fatal Error encountered");
1856 break; 1877 break;
1857 } 1878 }
1858 1879
@@ -1903,18 +1924,19 @@ void GMainWindow::OnReinitializeKeys(ReinitializeKeyBehavior behavior) {
1903 }; 1924 };
1904 1925
1905 QString errors; 1926 QString errors;
1906 1927 if (!pdm.HasFuses()) {
1907 if (!pdm.HasFuses())
1908 errors += tr("- Missing fuses - Cannot derive SBK\n"); 1928 errors += tr("- Missing fuses - Cannot derive SBK\n");
1909 if (!pdm.HasBoot0()) 1929 }
1930 if (!pdm.HasBoot0()) {
1910 errors += tr("- Missing BOOT0 - Cannot derive master keys\n"); 1931 errors += tr("- Missing BOOT0 - Cannot derive master keys\n");
1911 if (!pdm.HasPackage2()) 1932 }
1933 if (!pdm.HasPackage2()) {
1912 errors += tr("- Missing BCPKG2-1-Normal-Main - Cannot derive general keys\n"); 1934 errors += tr("- Missing BCPKG2-1-Normal-Main - Cannot derive general keys\n");
1913 if (!pdm.HasProdInfo()) 1935 }
1936 if (!pdm.HasProdInfo()) {
1914 errors += tr("- Missing PRODINFO - Cannot derive title keys\n"); 1937 errors += tr("- Missing PRODINFO - Cannot derive title keys\n");
1915 1938 }
1916 if (!errors.isEmpty()) { 1939 if (!errors.isEmpty()) {
1917
1918 QMessageBox::warning( 1940 QMessageBox::warning(
1919 this, tr("Warning Missing Derivation Components"), 1941 this, tr("Warning Missing Derivation Components"),
1920 tr("The following are missing from your configuration that may hinder key " 1942 tr("The following are missing from your configuration that may hinder key "
@@ -1964,13 +1986,15 @@ std::optional<u64> GMainWindow::SelectRomFSDumpTarget(const FileSys::ContentProv
1964 1986
1965 std::vector<u64> romfs_tids; 1987 std::vector<u64> romfs_tids;
1966 romfs_tids.push_back(program_id); 1988 romfs_tids.push_back(program_id);
1967 for (const auto& entry : dlc_match) 1989 for (const auto& entry : dlc_match) {
1968 romfs_tids.push_back(entry.title_id); 1990 romfs_tids.push_back(entry.title_id);
1991 }
1969 1992
1970 if (romfs_tids.size() > 1) { 1993 if (romfs_tids.size() > 1) {
1971 QStringList list{"Base"}; 1994 QStringList list{QStringLiteral("Base")};
1972 for (std::size_t i = 1; i < romfs_tids.size(); ++i) 1995 for (std::size_t i = 1; i < romfs_tids.size(); ++i) {
1973 list.push_back(QStringLiteral("DLC %1").arg(romfs_tids[i] & 0x7FF)); 1996 list.push_back(QStringLiteral("DLC %1").arg(romfs_tids[i] & 0x7FF));
1997 }
1974 1998
1975 bool ok; 1999 bool ok;
1976 const auto res = QInputDialog::getItem( 2000 const auto res = QInputDialog::getItem(
@@ -2082,26 +2106,32 @@ void GMainWindow::filterBarSetChecked(bool state) {
2082} 2106}
2083 2107
2084void GMainWindow::UpdateUITheme() { 2108void GMainWindow::UpdateUITheme() {
2109 const QString default_icons = QStringLiteral(":/icons/default");
2110 const QString& current_theme = UISettings::values.theme;
2111 const bool is_default_theme = current_theme == QString::fromUtf8(UISettings::themes[0].second);
2085 QStringList theme_paths(default_theme_paths); 2112 QStringList theme_paths(default_theme_paths);
2086 if (UISettings::values.theme != UISettings::themes[0].second && 2113
2087 !UISettings::values.theme.isEmpty()) { 2114 if (is_default_theme || current_theme.isEmpty()) {
2088 const QString theme_uri(":" + UISettings::values.theme + "/style.qss"); 2115 qApp->setStyleSheet({});
2116 setStyleSheet({});
2117 theme_paths.append(default_icons);
2118 QIcon::setThemeName(default_icons);
2119 } else {
2120 const QString theme_uri(QLatin1Char{':'} + current_theme + QStringLiteral("/style.qss"));
2089 QFile f(theme_uri); 2121 QFile f(theme_uri);
2090 if (f.open(QFile::ReadOnly | QFile::Text)) { 2122 if (f.open(QFile::ReadOnly | QFile::Text)) {
2091 QTextStream ts(&f); 2123 QTextStream ts(&f);
2092 qApp->setStyleSheet(ts.readAll()); 2124 qApp->setStyleSheet(ts.readAll());
2093 GMainWindow::setStyleSheet(ts.readAll()); 2125 setStyleSheet(ts.readAll());
2094 } else { 2126 } else {
2095 LOG_ERROR(Frontend, "Unable to set style, stylesheet file not found"); 2127 LOG_ERROR(Frontend, "Unable to set style, stylesheet file not found");
2096 } 2128 }
2097 theme_paths.append(QStringList{":/icons/default", ":/icons/" + UISettings::values.theme}); 2129
2098 QIcon::setThemeName(":/icons/" + UISettings::values.theme); 2130 const QString theme_name = QStringLiteral(":/icons/") + current_theme;
2099 } else { 2131 theme_paths.append({default_icons, theme_name});
2100 qApp->setStyleSheet(""); 2132 QIcon::setThemeName(theme_name);
2101 GMainWindow::setStyleSheet("");
2102 theme_paths.append(QStringList{":/icons/default"});
2103 QIcon::setThemeName(":/icons/default");
2104 } 2133 }
2134
2105 QIcon::setThemeSearchPaths(theme_paths); 2135 QIcon::setThemeSearchPaths(theme_paths);
2106 emit UpdateThemedIcons(); 2136 emit UpdateThemedIcons();
2107} 2137}
@@ -2129,8 +2159,8 @@ int main(int argc, char* argv[]) {
2129 SCOPE_EXIT({ MicroProfileShutdown(); }); 2159 SCOPE_EXIT({ MicroProfileShutdown(); });
2130 2160
2131 // Init settings params 2161 // Init settings params
2132 QCoreApplication::setOrganizationName("yuzu team"); 2162 QCoreApplication::setOrganizationName(QStringLiteral("yuzu team"));
2133 QCoreApplication::setApplicationName("yuzu"); 2163 QCoreApplication::setApplicationName(QStringLiteral("yuzu"));
2134 2164
2135 // Enables the core to make the qt created contexts current on std::threads 2165 // Enables the core to make the qt created contexts current on std::threads
2136 QCoreApplication::setAttribute(Qt::AA_DontCheckOpenGLContextThreadAffinity); 2166 QCoreApplication::setAttribute(Qt::AA_DontCheckOpenGLContextThreadAffinity);