diff options
Diffstat (limited to 'src/yuzu')
26 files changed, 193 insertions, 88 deletions
diff --git a/src/yuzu/CMakeLists.txt b/src/yuzu/CMakeLists.txt index f6b389ede..50007338f 100644 --- a/src/yuzu/CMakeLists.txt +++ b/src/yuzu/CMakeLists.txt @@ -221,6 +221,9 @@ if (ENABLE_QT_TRANSLATION) # Update source TS file if enabled if (GENERATE_QT_TRANSLATION) get_target_property(SRCS yuzu SOURCES) + # these calls to qt_create_translation also creates a rule to generate en.qm which conflicts with providing english plurals + # so we have to set a OUTPUT_LOCATION so that we don't have multiple rules to generate en.qm + set_source_files_properties(${YUZU_QT_LANGUAGES}/en.ts PROPERTIES OUTPUT_LOCATION "${CMAKE_CURRENT_BINARY_DIR}/translations") qt_create_translation(QM_FILES ${SRCS} ${UIS} @@ -229,7 +232,13 @@ if (ENABLE_QT_TRANSLATION) -source-language en_US -target-language en_US ) - add_custom_target(translation ALL DEPENDS ${YUZU_QT_LANGUAGES}/en.ts) + + # Generate plurals into dist/english_plurals/generated_en.ts so it can be used to revise dist/english_plurals/en.ts + set(GENERATED_PLURALS_FILE ${PROJECT_SOURCE_DIR}/dist/english_plurals/generated_en.ts) + set_source_files_properties(${GENERATED_PLURALS_FILE} PROPERTIES OUTPUT_LOCATION "${CMAKE_CURRENT_BINARY_DIR}/plurals") + qt_create_translation(QM_FILES ${SRCS} ${UIS} ${GENERATED_PLURALS_FILE} OPTIONS -pluralonly -source-language en_US -target-language en_US) + + add_custom_target(translation ALL DEPENDS ${YUZU_QT_LANGUAGES}/en.ts ${GENERATED_PLURALS_FILE}) endif() # Find all TS files except en.ts @@ -239,6 +248,9 @@ if (ENABLE_QT_TRANSLATION) # Compile TS files to QM files qt_add_translation(LANGUAGES_QM ${LANGUAGES_TS}) + # Compile english plurals TS file to en.qm + qt_add_translation(LANGUAGES_QM ${PROJECT_SOURCE_DIR}/dist/english_plurals/en.ts) + # Build a QRC file from the QM file list set(LANGUAGES_QRC ${CMAKE_CURRENT_BINARY_DIR}/languages.qrc) file(WRITE ${LANGUAGES_QRC} "<RCC><qresource prefix=\"languages\">\n") diff --git a/src/yuzu/aboutdialog.ui b/src/yuzu/aboutdialog.ui index c4ffb293e..aea82809d 100644 --- a/src/yuzu/aboutdialog.ui +++ b/src/yuzu/aboutdialog.ui @@ -7,7 +7,7 @@ <x>0</x> <y>0</y> <width>616</width> - <height>261</height> + <height>294</height> </rect> </property> <property name="windowTitle"> @@ -165,6 +165,7 @@ p, li { white-space: pre-wrap; } </widget> <resources> <include location="../../dist/qt_themes_default/default/default.qrc"/> + <include location="../../dist/qt_themes/default/default.qrc"/> </resources> <connections> <connection> diff --git a/src/yuzu/applets/qt_profile_select.cpp b/src/yuzu/applets/qt_profile_select.cpp index 826c6c224..c8bcfb223 100644 --- a/src/yuzu/applets/qt_profile_select.cpp +++ b/src/yuzu/applets/qt_profile_select.cpp @@ -100,6 +100,7 @@ QtProfileSelectionDialog::QtProfileSelectionDialog(Core::HID::HIDCore& hid_core, } QKeyEvent* event = new QKeyEvent(QEvent::KeyPress, key, Qt::NoModifier); QCoreApplication::postEvent(tree_view, event); + SelectUser(tree_view->currentIndex()); }); const auto& profiles = profile_manager->GetAllUsers(); diff --git a/src/yuzu/bootmanager.cpp b/src/yuzu/bootmanager.cpp index ef3bdfb1a..c262d0a2b 100644 --- a/src/yuzu/bootmanager.cpp +++ b/src/yuzu/bootmanager.cpp @@ -1089,8 +1089,8 @@ QStringList GRenderWindow::GetUnsupportedGLExtensions() const { } if (!unsupported_ext.empty()) { - LOG_ERROR(Frontend, "GPU does not support all required extensions: {}", - glGetString(GL_RENDERER)); + const std::string gl_renderer{reinterpret_cast<const char*>(glGetString(GL_RENDERER))}; + LOG_ERROR(Frontend, "GPU does not support all required extensions: {}", gl_renderer); } for (const QString& ext : unsupported_ext) { LOG_ERROR(Frontend, "Unsupported GL extension: {}", ext.toStdString()); diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp index 58f1239bf..da6e5aa88 100644 --- a/src/yuzu/configuration/config.cpp +++ b/src/yuzu/configuration/config.cpp @@ -73,7 +73,7 @@ const std::array<int, 2> Config::default_ringcon_analogs{{ const std::array<UISettings::Shortcut, 22> Config::default_hotkeys{{ {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Audio Mute/Unmute")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("Ctrl+M"), QStringLiteral("Home+Dpad_Right"), Qt::WindowShortcut}}, {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Audio Volume Down")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("-"), QStringLiteral("Home+Dpad_Down"), Qt::ApplicationShortcut}}, - {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Audio Volume Up")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("+"), QStringLiteral("Home+Dpad_Up"), Qt::ApplicationShortcut}}, + {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Audio Volume Up")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("="), QStringLiteral("Home+Dpad_Up"), Qt::ApplicationShortcut}}, {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Capture Screenshot")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("Ctrl+P"), QStringLiteral("Screenshot"), Qt::WidgetWithChildrenShortcut}}, {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Change Adapting Filter")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("F8"), QStringLiteral("Home+L"), Qt::ApplicationShortcut}}, {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Change Docked Mode")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("F10"), QStringLiteral("Home+X"), Qt::ApplicationShortcut}}, diff --git a/src/yuzu/configuration/configure_audio.ui b/src/yuzu/configuration/configure_audio.ui index a5bcee415..6034d8581 100644 --- a/src/yuzu/configuration/configure_audio.ui +++ b/src/yuzu/configuration/configure_audio.ui @@ -120,10 +120,10 @@ </sizepolicy> </property> <property name="maximum"> - <number>100</number> + <number>200</number> </property> <property name="pageStep"> - <number>10</number> + <number>5</number> </property> <property name="orientation"> <enum>Qt::Horizontal</enum> diff --git a/src/yuzu/configuration/configure_graphics_advanced.ui b/src/yuzu/configuration/configure_graphics_advanced.ui index 96de0b3d1..d6d819364 100644 --- a/src/yuzu/configuration/configure_graphics_advanced.ui +++ b/src/yuzu/configuration/configure_graphics_advanced.ui @@ -75,7 +75,7 @@ <string>VSync prevents the screen from tearing, but some graphics cards have lower performance with VSync enabled. Keep it enabled if you don't notice a performance difference.</string> </property> <property name="text"> - <string>Use VSync (OpenGL only)</string> + <string>Use VSync</string> </property> </widget> </item> diff --git a/src/yuzu/configuration/configure_input_player.cpp b/src/yuzu/configuration/configure_input_player.cpp index 00bee85b2..109689c88 100644 --- a/src/yuzu/configuration/configure_input_player.cpp +++ b/src/yuzu/configuration/configure_input_player.cpp @@ -1475,7 +1475,7 @@ void ConfigureInputPlayer::keyPressEvent(QKeyEvent* event) { void ConfigureInputPlayer::CreateProfile() { const auto profile_name = - LimitableInputDialog::GetText(this, tr("New Profile"), tr("Enter a profile name:"), 1, 20, + LimitableInputDialog::GetText(this, tr("New Profile"), tr("Enter a profile name:"), 1, 30, LimitableInputDialog::InputLimiter::Filesystem); if (profile_name.isEmpty()) { diff --git a/src/yuzu/configuration/configure_ui.cpp b/src/yuzu/configuration/configure_ui.cpp index 2e98ede8e..48f71b53c 100644 --- a/src/yuzu/configuration/configure_ui.cpp +++ b/src/yuzu/configuration/configure_ui.cpp @@ -219,6 +219,7 @@ void ConfigureUi::InitializeLanguageComboBox() { for (const auto& lang : languages) { if (QString::fromLatin1(lang.id) == QStringLiteral("en")) { ui->language_combobox->addItem(lang.name, QStringLiteral("en")); + language_files.removeOne(QStringLiteral("en.qm")); continue; } for (int i = 0; i < language_files.size(); ++i) { diff --git a/src/yuzu/game_list.cpp b/src/yuzu/game_list.cpp index 041e6ac11..b127badc2 100644 --- a/src/yuzu/game_list.cpp +++ b/src/yuzu/game_list.cpp @@ -126,10 +126,8 @@ GameListSearchField::GameListSearchField(GameList* parent) : QWidget{parent} { layout_filter = new QHBoxLayout; layout_filter->setContentsMargins(8, 8, 8, 8); label_filter = new QLabel; - label_filter->setText(tr("Filter:")); edit_filter = new QLineEdit; edit_filter->clear(); - edit_filter->setPlaceholderText(tr("Enter pattern to filter")); edit_filter->installEventFilter(key_release_eater); edit_filter->setClearButtonEnabled(true); connect(edit_filter, &QLineEdit::textChanged, parent, &GameList::OnTextChanged); @@ -149,6 +147,7 @@ GameListSearchField::GameListSearchField(GameList* parent) : QWidget{parent} { layout_filter->addWidget(label_filter_result); layout_filter->addWidget(button_filter_close); setLayout(layout_filter); + RetranslateUI(); } /** @@ -286,7 +285,7 @@ void GameList::OnUpdateThemedIcons() { } case GameListItemType::AddDir: child->setData( - QIcon::fromTheme(QStringLiteral("plus")) + QIcon::fromTheme(QStringLiteral("list-add")) .pixmap(icon_size) .scaled(icon_size, icon_size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation), Qt::DecorationRole); @@ -333,13 +332,9 @@ GameList::GameList(FileSys::VirtualFilesystem vfs_, FileSys::ManualContentProvid tree_view->setStyleSheet(QStringLiteral("QTreeView{ border: none; }")); item_model->insertColumns(0, COLUMN_COUNT); - item_model->setHeaderData(COLUMN_NAME, Qt::Horizontal, tr("Name")); - item_model->setHeaderData(COLUMN_COMPATIBILITY, Qt::Horizontal, tr("Compatibility")); + RetranslateUI(); - item_model->setHeaderData(COLUMN_ADD_ONS, Qt::Horizontal, tr("Add-ons")); tree_view->setColumnHidden(COLUMN_ADD_ONS, !UISettings::values.show_add_ons); - item_model->setHeaderData(COLUMN_FILE_TYPE, Qt::Horizontal, tr("File type")); - item_model->setHeaderData(COLUMN_SIZE, Qt::Horizontal, tr("Size")); item_model->setSortRole(GameListItemPath::SortRole); connect(main_window, &GMainWindow::UpdateThemedIcons, this, &GameList::OnUpdateThemedIcons); @@ -753,6 +748,35 @@ void GameList::LoadCompatibilityList() { } } +void GameList::changeEvent(QEvent* event) { + if (event->type() == QEvent::LanguageChange) { + RetranslateUI(); + } + + QWidget::changeEvent(event); +} + +void GameList::RetranslateUI() { + item_model->setHeaderData(COLUMN_NAME, Qt::Horizontal, tr("Name")); + item_model->setHeaderData(COLUMN_COMPATIBILITY, Qt::Horizontal, tr("Compatibility")); + item_model->setHeaderData(COLUMN_ADD_ONS, Qt::Horizontal, tr("Add-ons")); + item_model->setHeaderData(COLUMN_FILE_TYPE, Qt::Horizontal, tr("File type")); + item_model->setHeaderData(COLUMN_SIZE, Qt::Horizontal, tr("Size")); +} + +void GameListSearchField::changeEvent(QEvent* event) { + if (event->type() == QEvent::LanguageChange) { + RetranslateUI(); + } + + QWidget::changeEvent(event); +} + +void GameListSearchField::RetranslateUI() { + label_filter->setText(tr("Filter:")); + edit_filter->setPlaceholderText(tr("Enter pattern to filter")); +} + QStandardItemModel* GameList::GetModel() const { return item_model; } diff --git a/src/yuzu/game_list.h b/src/yuzu/game_list.h index f783283c9..cdf085019 100644 --- a/src/yuzu/game_list.h +++ b/src/yuzu/game_list.h @@ -140,6 +140,9 @@ private: void AddPermDirPopup(QMenu& context_menu, QModelIndex selected); void AddFavoritesPopup(QMenu& context_menu); + void changeEvent(QEvent*) override; + void RetranslateUI(); + std::shared_ptr<FileSys::VfsFilesystem> vfs; FileSys::ManualContentProvider* provider; GameListSearchField* search_field; diff --git a/src/yuzu/game_list_p.h b/src/yuzu/game_list_p.h index e7667cf60..6198d1e4e 100644 --- a/src/yuzu/game_list_p.h +++ b/src/yuzu/game_list_p.h @@ -294,7 +294,7 @@ public: const int icon_size = UISettings::values.folder_icon_size.GetValue(); - setData(QIcon::fromTheme(QStringLiteral("plus")) + setData(QIcon::fromTheme(QStringLiteral("list-add")) .pixmap(icon_size) .scaled(icon_size, icon_size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation), Qt::DecorationRole); @@ -353,6 +353,9 @@ public: void setFocus(); private: + void changeEvent(QEvent*) override; + void RetranslateUI(); + class KeyReleaseEater : public QObject { public: explicit KeyReleaseEater(GameList* gamelist_, QObject* parent = nullptr); diff --git a/src/yuzu/loading_screen.cpp b/src/yuzu/loading_screen.cpp index e273744fd..e263a07a7 100644 --- a/src/yuzu/loading_screen.cpp +++ b/src/yuzu/loading_screen.cpp @@ -147,6 +147,10 @@ void LoadingScreen::OnLoadProgress(VideoCore::LoadCallbackStage stage, std::size ui->progress_bar->setMaximum(static_cast<int>(total)); previous_total = total; } + // Reset the progress bar ranges if compilation is done + if (stage == VideoCore::LoadCallbackStage::Complete) { + ui->progress_bar->setRange(0, 0); + } QString estimate; // If theres a drastic slowdown in the rate, then display an estimate diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index f8c234082..e103df977 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp @@ -257,6 +257,18 @@ static QString PrettyProductName() { return QSysInfo::prettyProductName(); } +bool GMainWindow::CheckDarkMode() { +#ifdef __linux__ + const QPalette test_palette(qApp->palette()); + const QColor text_color = test_palette.color(QPalette::Active, QPalette::Text); + const QColor window_color = test_palette.color(QPalette::Active, QPalette::Window); + return (text_color.value() > window_color.value()); +#else + // TODO: Windows + return false; +#endif // __linux__ +} + GMainWindow::GMainWindow(bool has_broken_vulkan) : ui{std::make_unique<Ui::MainWindow>()}, system{std::make_unique<Core::System>()}, input_subsystem{std::make_shared<InputCommon::InputSubsystem>()}, @@ -274,6 +286,13 @@ GMainWindow::GMainWindow(bool has_broken_vulkan) ui->setupUi(this); statusBar()->hide(); + // Check dark mode before a theme is loaded + os_dark_mode = CheckDarkMode(); + startup_icon_theme = QIcon::themeName(); + // fallback can only be set once, colorful theme icons are okay on both light/dark + QIcon::setFallbackThemeName(QStringLiteral("colorful")); + QIcon::setFallbackSearchPaths(QStringList(QStringLiteral(":/icons"))); + default_theme_paths = QIcon::themeSearchPaths(); UpdateUITheme(); @@ -473,8 +492,6 @@ GMainWindow::~GMainWindow() { delete render_window; } - system->GetRoomNetwork().Shutdown(); - #ifdef __linux__ ::close(sig_interrupt_fds[0]); ::close(sig_interrupt_fds[1]); @@ -1075,7 +1092,7 @@ void GMainWindow::InitializeHotkeys() { connect_shortcut(QStringLiteral("Audio Mute/Unmute"), [] { Settings::values.audio_muted = !Settings::values.audio_muted; }); connect_shortcut(QStringLiteral("Audio Volume Down"), [] { - const auto current_volume = static_cast<int>(Settings::values.volume.GetValue()); + const auto current_volume = static_cast<s32>(Settings::values.volume.GetValue()); int step = 5; if (current_volume <= 30) { step = 2; @@ -1083,11 +1100,10 @@ void GMainWindow::InitializeHotkeys() { if (current_volume <= 6) { step = 1; } - const auto new_volume = std::max(current_volume - step, 0); - Settings::values.volume.SetValue(static_cast<u8>(new_volume)); + Settings::values.volume.SetValue(std::max(current_volume - step, 0)); }); connect_shortcut(QStringLiteral("Audio Volume Up"), [] { - const auto current_volume = static_cast<int>(Settings::values.volume.GetValue()); + const auto current_volume = static_cast<s32>(Settings::values.volume.GetValue()); int step = 5; if (current_volume < 30) { step = 2; @@ -1095,8 +1111,7 @@ void GMainWindow::InitializeHotkeys() { if (current_volume < 6) { step = 1; } - const auto new_volume = std::min(current_volume + step, 100); - Settings::values.volume.SetValue(static_cast<u8>(new_volume)); + Settings::values.volume.SetValue(current_volume + step); }); connect_shortcut(QStringLiteral("Toggle Framerate Limit"), [] { Settings::values.use_speed_limit.SetValue(!Settings::values.use_speed_limit.GetValue()); @@ -1588,17 +1603,18 @@ bool GMainWindow::LoadROM(const QString& filename, u64 program_id, std::size_t p return true; } -void GMainWindow::SelectAndSetCurrentUser() { +bool GMainWindow::SelectAndSetCurrentUser() { QtProfileSelectionDialog dialog(system->HIDCore(), this); dialog.setWindowFlags(Qt::Dialog | Qt::CustomizeWindowHint | Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint); dialog.setWindowModality(Qt::WindowModal); if (dialog.exec() == QDialog::Rejected) { - return; + return false; } Settings::values.current_user = dialog.GetIndex(); + return true; } void GMainWindow::BootGame(const QString& filename, u64 program_id, std::size_t program_index, @@ -1632,11 +1648,14 @@ void GMainWindow::BootGame(const QString& filename, u64 program_id, std::size_t Settings::LogSettings(); if (UISettings::values.select_user_on_boot) { - SelectAndSetCurrentUser(); + if (SelectAndSetCurrentUser() == false) { + return; + } } - if (!LoadROM(filename, program_id, program_index)) + if (!LoadROM(filename, program_id, program_index)) { return; + } system->SetShuttingDown(false); @@ -3334,7 +3353,8 @@ void GMainWindow::MigrateConfigFiles() { } const auto origin = config_dir_fs_path / filename; const auto destination = config_dir_fs_path / "custom" / filename; - LOG_INFO(Frontend, "Migrating config file from {} to {}", origin, destination); + LOG_INFO(Frontend, "Migrating config file from {} to {}", origin.string(), + destination.string()); if (!Common::FS::RenameFile(origin, destination)) { // Delete the old config file if one already exists in the new location. Common::FS::RemoveFile(origin); @@ -3809,6 +3829,7 @@ void GMainWindow::closeEvent(QCloseEvent* event) { render_window->close(); multiplayer_state->Close(); + system->GetRoomNetwork().Shutdown(); QWidget::closeEvent(event); } @@ -3930,8 +3951,21 @@ void GMainWindow::filterBarSetChecked(bool state) { emit(OnToggleFilterBar()); } +static void AdjustLinkColor() { + QPalette new_pal(qApp->palette()); + if (UISettings::IsDarkTheme()) { + new_pal.setColor(QPalette::Link, QColor(0, 190, 255, 255)); + } else { + new_pal.setColor(QPalette::Link, QColor(0, 140, 200, 255)); + } + if (qApp->palette().color(QPalette::Link) != new_pal.color(QPalette::Link)) { + qApp->setPalette(new_pal); + } +} + void GMainWindow::UpdateUITheme() { - const QString default_theme = QStringLiteral("default"); + const QString default_theme = + QString::fromUtf8(UISettings::themes[static_cast<size_t>(Config::default_theme)].second); QString current_theme = UISettings::values.theme; QStringList theme_paths(default_theme_paths); @@ -3939,6 +3973,23 @@ void GMainWindow::UpdateUITheme() { current_theme = default_theme; } +#ifdef _WIN32 + QIcon::setThemeName(current_theme); + AdjustLinkColor(); +#else + if (current_theme == QStringLiteral("default") || current_theme == QStringLiteral("colorful")) { + QIcon::setThemeName(current_theme == QStringLiteral("colorful") ? current_theme + : startup_icon_theme); + QIcon::setThemeSearchPaths(theme_paths); + if (CheckDarkMode()) { + current_theme = QStringLiteral("default_dark"); + } + } else { + QIcon::setThemeName(current_theme); + QIcon::setThemeSearchPaths(QStringList(QStringLiteral(":/icons"))); + AdjustLinkColor(); + } +#endif if (current_theme != default_theme) { QString theme_uri{QStringLiteral(":%1/style.qss").arg(current_theme)}; QFile f(theme_uri); @@ -3961,25 +4012,9 @@ void GMainWindow::UpdateUITheme() { qApp->setStyleSheet({}); setStyleSheet({}); } - - QPalette new_pal(qApp->palette()); - if (UISettings::IsDarkTheme()) { - new_pal.setColor(QPalette::Link, QColor(0, 190, 255, 255)); - } else { - new_pal.setColor(QPalette::Link, QColor(0, 140, 200, 255)); - } - qApp->setPalette(new_pal); - - QIcon::setThemeName(current_theme); - QIcon::setThemeSearchPaths(theme_paths); } void GMainWindow::LoadTranslation() { - // If the selected language is English, no need to install any translation - if (UISettings::values.language == QStringLiteral("en")) { - return; - } - bool loaded; if (UISettings::values.language.isEmpty()) { @@ -4022,6 +4057,26 @@ void GMainWindow::SetDiscordEnabled([[maybe_unused]] bool state) { discord_rpc->Update(); } +void GMainWindow::changeEvent(QEvent* event) { +#ifdef __linux__ + // PaletteChange event appears to only reach so far into the GUI, explicitly asking to + // UpdateUITheme is a decent work around + if (event->type() == QEvent::PaletteChange) { + const QPalette test_palette(qApp->palette()); + const QString current_theme = UISettings::values.theme; + // Keeping eye on QPalette::Window to avoid looping. QPalette::Text might be useful too + static QColor last_window_color; + const QColor window_color = test_palette.color(QPalette::Active, QPalette::Window); + if (last_window_color != window_color && (current_theme == QStringLiteral("default") || + current_theme == QStringLiteral("colorful"))) { + UpdateUITheme(); + } + last_window_color = window_color; + } +#endif // __linux__ + QWidget::changeEvent(event); +} + #ifdef main #undef main #endif @@ -4067,6 +4122,15 @@ int main(int argc, char* argv[]) { QCoreApplication::setAttribute(Qt::AA_DontCheckOpenGLContextThreadAffinity); QApplication app(argc, argv); + // Workaround for QTBUG-85409, for Suzhou numerals the number 1 is actually \u3021 + // so we can see if we get \u3008 instead + // TL;DR all other number formats are consecutive in unicode code points + // This bug is fixed in Qt6, specifically 6.0.0-alpha1 + const QLocale locale = QLocale::system(); + if (QStringLiteral("\u3008") == locale.toString(1)) { + QLocale::setDefault(QLocale::system().name()); + } + // Qt changes the locale and causes issues in float conversion using std::to_string() when // generating shaders setlocale(LC_ALL, "C"); diff --git a/src/yuzu/main.h b/src/yuzu/main.h index 23b67a14e..1ae2b93d9 100644 --- a/src/yuzu/main.h +++ b/src/yuzu/main.h @@ -218,7 +218,7 @@ private: void SetDiscordEnabled(bool state); void LoadAmiibo(const QString& filename); - void SelectAndSetCurrentUser(); + bool SelectAndSetCurrentUser(); /** * Stores the filename in the recently loaded files list. @@ -251,6 +251,7 @@ private: bool ConfirmForceLockedExit(); void RequestGameExit(); void RequestGameResume(); + void changeEvent(QEvent* event) override; void closeEvent(QCloseEvent* event) override; #ifdef __linux__ @@ -347,6 +348,7 @@ private: void OpenURL(const QUrl& url); void LoadTranslation(); void OpenPerGameConfiguration(u64 title_id, const std::string& file_name); + bool CheckDarkMode(); QString GetTasStateDescription() const; @@ -392,6 +394,9 @@ private: QTimer mouse_hide_timer; QTimer mouse_center_timer; + QString startup_icon_theme; + bool os_dark_mode = false; + // FS std::shared_ptr<FileSys::VfsFilesystem> vfs; std::unique_ptr<FileSys::ManualContentProvider> provider; diff --git a/src/yuzu/multiplayer/chat_room.cpp b/src/yuzu/multiplayer/chat_room.cpp index 5837b36ab..1968a3c75 100644 --- a/src/yuzu/multiplayer/chat_room.cpp +++ b/src/yuzu/multiplayer/chat_room.cpp @@ -316,21 +316,19 @@ void ChatRoom::OnStatusMessageReceive(const Network::StatusMessageEntry& status_ } void ChatRoom::OnSendChat() { - if (auto room = room_network->GetRoomMember().lock()) { - if (room->GetState() != Network::RoomMember::State::Joined && - room->GetState() != Network::RoomMember::State::Moderator) { - + if (auto room_member = room_network->GetRoomMember().lock()) { + if (!room_member->IsConnected()) { return; } auto message = ui->chat_message->text().toStdString(); if (!ValidateMessage(message)) { return; } - auto nick = room->GetNickname(); - auto username = room->GetUsername(); + auto nick = room_member->GetNickname(); + auto username = room_member->GetUsername(); Network::ChatEntry chat{nick, username, message}; - auto members = room->GetMemberInformation(); + auto members = room_member->GetMemberInformation(); auto it = std::find_if(members.begin(), members.end(), [&chat](const Network::RoomMember::MemberInformation& member) { return member.nickname == chat.nickname && @@ -341,7 +339,7 @@ void ChatRoom::OnSendChat() { } auto player = std::distance(members.begin(), it); ChatMessage m(chat, *room_network); - room->SendChatMessage(message); + room_member->SendChatMessage(message); AppendChatMessage(m.GetPlayerChatMessage(player)); ui->chat_message->clear(); } diff --git a/src/yuzu/multiplayer/client_room.cpp b/src/yuzu/multiplayer/client_room.cpp index a9859ed70..86baafbf0 100644 --- a/src/yuzu/multiplayer/client_room.cpp +++ b/src/yuzu/multiplayer/client_room.cpp @@ -74,7 +74,6 @@ void ClientRoomWindow::OnRoomUpdate(const Network::RoomInformation& info) { void ClientRoomWindow::OnStateChange(const Network::RoomMember::State& state) { if (state == Network::RoomMember::State::Joined || state == Network::RoomMember::State::Moderator) { - ui->chat->Clear(); ui->chat->AppendStatusMessage(tr("Connected")); SetModPerms(state == Network::RoomMember::State::Moderator); diff --git a/src/yuzu/multiplayer/direct_connect.cpp b/src/yuzu/multiplayer/direct_connect.cpp index 9000c4531..4c0ea0a6b 100644 --- a/src/yuzu/multiplayer/direct_connect.cpp +++ b/src/yuzu/multiplayer/direct_connect.cpp @@ -97,9 +97,9 @@ void DirectConnectWindow::Connect() { QFuture<void> f = QtConcurrent::run([&] { if (auto room_member = room_network.GetRoomMember().lock()) { auto port = UISettings::values.multiplayer_port.GetValue(); - room_member->Join(ui->nickname->text().toStdString(), "", - ui->ip->text().toStdString().c_str(), port, 0, - Network::NoPreferredMac, ui->password->text().toStdString().c_str()); + room_member->Join(ui->nickname->text().toStdString(), + ui->ip->text().toStdString().c_str(), port, 0, Network::NoPreferredIP, + ui->password->text().toStdString().c_str()); } }); watcher->setFuture(f); @@ -121,9 +121,7 @@ void DirectConnectWindow::OnConnection() { EndConnecting(); if (auto room_member = room_network.GetRoomMember().lock()) { - if (room_member->GetState() == Network::RoomMember::State::Joined || - room_member->GetState() == Network::RoomMember::State::Moderator) { - + if (room_member->IsConnected()) { close(); } } diff --git a/src/yuzu/multiplayer/direct_connect.ui b/src/yuzu/multiplayer/direct_connect.ui index 681b6bf69..57d6ec25a 100644 --- a/src/yuzu/multiplayer/direct_connect.ui +++ b/src/yuzu/multiplayer/direct_connect.ui @@ -83,7 +83,7 @@ <number>5</number> </property> <property name="placeholderText"> - <string>24872</string> + <string notr="true" extracomment="placeholder string that tells user default port">24872</string> </property> </widget> </item> diff --git a/src/yuzu/multiplayer/host_room.cpp b/src/yuzu/multiplayer/host_room.cpp index cb9464b2b..d70a9a3c8 100644 --- a/src/yuzu/multiplayer/host_room.cpp +++ b/src/yuzu/multiplayer/host_room.cpp @@ -201,8 +201,8 @@ void HostRoomWindow::Host() { } #endif // TODO: Check what to do with this - member->Join(ui->username->text().toStdString(), "", "127.0.0.1", port, 0, - Network::NoPreferredMac, password, token); + member->Join(ui->username->text().toStdString(), "127.0.0.1", port, 0, + Network::NoPreferredIP, password, token); // Store settings UISettings::values.multiplayer_room_nickname = ui->username->text(); diff --git a/src/yuzu/multiplayer/lobby.cpp b/src/yuzu/multiplayer/lobby.cpp index 23c2f21ab..1cc518279 100644 --- a/src/yuzu/multiplayer/lobby.cpp +++ b/src/yuzu/multiplayer/lobby.cpp @@ -169,7 +169,7 @@ void Lobby::OnJoinRoom(const QModelIndex& source) { } #endif if (auto room_member = room_network.GetRoomMember().lock()) { - room_member->Join(nickname, "", ip.c_str(), port, 0, Network::NoPreferredMac, password, + room_member->Join(nickname, ip.c_str(), port, 0, Network::NoPreferredIP, password, token); } }); diff --git a/src/yuzu/multiplayer/message.cpp b/src/yuzu/multiplayer/message.cpp index 76ec276ad..94d7a38b8 100644 --- a/src/yuzu/multiplayer/message.cpp +++ b/src/yuzu/multiplayer/message.cpp @@ -43,11 +43,8 @@ const ConnectionError ErrorManager::LOST_CONNECTION( QT_TR_NOOP("Connection to room lost. Try to reconnect.")); const ConnectionError ErrorManager::HOST_KICKED( QT_TR_NOOP("You have been kicked by the room host.")); -const ConnectionError ErrorManager::MAC_COLLISION( - QT_TR_NOOP("MAC address is already in use. Please choose another.")); -const ConnectionError ErrorManager::CONSOLE_ID_COLLISION(QT_TR_NOOP( - "Your Console ID conflicted with someone else's in the room.\n\nPlease go to Emulation " - "> Configure > System to regenerate your Console ID.")); +const ConnectionError ErrorManager::IP_COLLISION( + QT_TR_NOOP("IP address is already in use. Please choose another.")); const ConnectionError ErrorManager::PERMISSION_DENIED( QT_TR_NOOP("You do not have enough permission to perform this action.")); const ConnectionError ErrorManager::NO_SUCH_USER(QT_TR_NOOP( diff --git a/src/yuzu/multiplayer/message.h b/src/yuzu/multiplayer/message.h index eb5c8d1be..812495c72 100644 --- a/src/yuzu/multiplayer/message.h +++ b/src/yuzu/multiplayer/message.h @@ -40,8 +40,7 @@ public: static const ConnectionError GENERIC_ERROR; static const ConnectionError LOST_CONNECTION; static const ConnectionError HOST_KICKED; - static const ConnectionError MAC_COLLISION; - static const ConnectionError CONSOLE_ID_COLLISION; + static const ConnectionError IP_COLLISION; static const ConnectionError PERMISSION_DENIED; static const ConnectionError NO_SUCH_USER; /** diff --git a/src/yuzu/multiplayer/state.cpp b/src/yuzu/multiplayer/state.cpp index 4149b5232..dba76b22b 100644 --- a/src/yuzu/multiplayer/state.cpp +++ b/src/yuzu/multiplayer/state.cpp @@ -59,7 +59,9 @@ MultiplayerState::MultiplayerState(QWidget* parent, QStandardItemModel* game_lis }); } -MultiplayerState::~MultiplayerState() { +MultiplayerState::~MultiplayerState() = default; + +void MultiplayerState::Close() { if (state_callback_handle) { if (auto member = room_network.GetRoomMember().lock()) { member->Unbind(state_callback_handle); @@ -71,9 +73,6 @@ MultiplayerState::~MultiplayerState() { member->Unbind(error_callback_handle); } } -} - -void MultiplayerState::Close() { if (host_room) { host_room->close(); } @@ -95,7 +94,6 @@ void MultiplayerState::retranslateUi() { status_text->setText(tr("Not Connected. Click here to find a room!")); } else if (current_state == Network::RoomMember::State::Joined || current_state == Network::RoomMember::State::Moderator) { - status_text->setText(tr("Connected")); } else { status_text->setText(tr("Not Connected")); @@ -151,11 +149,8 @@ void MultiplayerState::OnNetworkError(const Network::RoomMember::Error& error) { NetworkMessage::ErrorManager::ShowError( NetworkMessage::ErrorManager::USERNAME_NOT_VALID_SERVER); break; - case Network::RoomMember::Error::MacCollision: - NetworkMessage::ErrorManager::ShowError(NetworkMessage::ErrorManager::MAC_COLLISION); - break; - case Network::RoomMember::Error::ConsoleIdCollision: - NetworkMessage::ErrorManager::ShowError(NetworkMessage::ErrorManager::CONSOLE_ID_COLLISION); + case Network::RoomMember::Error::IpCollision: + NetworkMessage::ErrorManager::ShowError(NetworkMessage::ErrorManager::IP_COLLISION); break; case Network::RoomMember::Error::RoomIsFull: NetworkMessage::ErrorManager::ShowError(NetworkMessage::ErrorManager::ROOM_IS_FULL); diff --git a/src/yuzu/multiplayer/validation.h b/src/yuzu/multiplayer/validation.h index 7d48e589d..dabf860be 100644 --- a/src/yuzu/multiplayer/validation.h +++ b/src/yuzu/multiplayer/validation.h @@ -10,7 +10,7 @@ class Validation { public: Validation() - : room_name(room_name_regex), nickname(nickname_regex), ip(ip_regex), port(0, 65535) {} + : room_name(room_name_regex), nickname(nickname_regex), ip(ip_regex), port(0, UINT16_MAX) {} ~Validation() = default; diff --git a/src/yuzu/uisettings.h b/src/yuzu/uisettings.h index 25d1bf1e6..e12d414d9 100644 --- a/src/yuzu/uisettings.h +++ b/src/yuzu/uisettings.h @@ -104,11 +104,12 @@ struct Values { // multiplayer settings Settings::Setting<QString> multiplayer_nickname{QStringLiteral("yuzu"), "nickname"}; Settings::Setting<QString> multiplayer_ip{{}, "ip"}; - Settings::SwitchableSetting<uint, true> multiplayer_port{24872, 0, 65535, "port"}; + Settings::SwitchableSetting<uint, true> multiplayer_port{24872, 0, UINT16_MAX, "port"}; Settings::Setting<QString> multiplayer_room_nickname{{}, "room_nickname"}; Settings::Setting<QString> multiplayer_room_name{{}, "room_name"}; Settings::SwitchableSetting<uint, true> multiplayer_max_player{8, 0, 8, "max_player"}; - Settings::SwitchableSetting<uint, true> multiplayer_room_port{24872, 0, 65535, "room_port"}; + Settings::SwitchableSetting<uint, true> multiplayer_room_port{24872, 0, UINT16_MAX, + "room_port"}; Settings::SwitchableSetting<uint, true> multiplayer_host_type{0, 0, 1, "host_type"}; Settings::Setting<qulonglong> multiplayer_game_id{{}, "game_id"}; Settings::Setting<QString> multiplayer_room_description{{}, "room_description"}; |