From d3546d18a121efd7f74bdc9aa1833386668addc9 Mon Sep 17 00:00:00 2001 From: Stenzek Date: Mon, 6 May 2024 00:00:41 +1000 Subject: [PATCH] Qt: Add compatibility report in game summary --- src/core/game_database.cpp | 176 +++++++- src/core/game_database.h | 7 + src/duckstation-qt/gamesummarywidget.cpp | 29 ++ src/duckstation-qt/gamesummarywidget.h | 2 + src/duckstation-qt/gamesummarywidget.ui | 8 +- .../icons/black/svg/information-line.svg | 1 + .../icons/white/svg/information-line.svg | 1 + src/duckstation-qt/resources/resources.qrc | 384 +++++++++--------- 8 files changed, 405 insertions(+), 203 deletions(-) create mode 100644 src/duckstation-qt/resources/icons/black/svg/information-line.svg create mode 100644 src/duckstation-qt/resources/icons/white/svg/information-line.svg diff --git a/src/core/game_database.cpp b/src/core/game_database.cpp index 1ca69149e..893f2faaf 100644 --- a/src/core/game_database.cpp +++ b/src/core/game_database.cpp @@ -34,7 +34,7 @@ namespace GameDatabase { enum : u32 { GAME_DATABASE_CACHE_SIGNATURE = 0x45434C48, - GAME_DATABASE_CACHE_VERSION = 7, + GAME_DATABASE_CACHE_VERSION = 8, }; static Entry* GetMutableEntry(std::string_view serial); @@ -54,12 +54,10 @@ static constexpr const std::array(CompatibilityRat {"Unknown", "DoesntBoot", "CrashesInIntro", "CrashesInGame", "GraphicalAudioIssues", "NoIssues"}}; static constexpr const std::array(CompatibilityRating::Count)> - s_compatibility_rating_display_names = {{TRANSLATE_NOOP("GameListCompatibilityRating", "Unknown"), - TRANSLATE_NOOP("GameListCompatibilityRating", "Doesn't Boot"), - TRANSLATE_NOOP("GameListCompatibilityRating", "Crashes In Intro"), - TRANSLATE_NOOP("GameListCompatibilityRating", "Crashes In-Game"), - TRANSLATE_NOOP("GameListCompatibilityRating", "Graphical/Audio Issues"), - TRANSLATE_NOOP("GameListCompatibilityRating", "No Issues")}}; + s_compatibility_rating_display_names = { + {TRANSLATE_NOOP("GameDatabase", "Unknown"), TRANSLATE_NOOP("GameDatabase", "Doesn't Boot"), + TRANSLATE_NOOP("GameDatabase", "Crashes In Intro"), TRANSLATE_NOOP("GameDatabase", "Crashes In-Game"), + TRANSLATE_NOOP("GameDatabase", "Graphical/Audio Issues"), TRANSLATE_NOOP("GameDatabase", "No Issues")}}; static constexpr const std::array(GameDatabase::Trait::Count)> s_trait_names = {{ "ForceInterpreter", @@ -86,6 +84,31 @@ static constexpr const std::array(GameDatabase::Tr "IsLibCryptProtected", }}; +static constexpr const std::array(GameDatabase::Trait::Count)> s_trait_display_names = {{ + TRANSLATE_NOOP("GameDatabase", "Force Interpreter"), + TRANSLATE_NOOP("GameDatabase", "Force Software Renderer"), + TRANSLATE_NOOP("GameDatabase", "Force Software Renderer For Readbacks"), + TRANSLATE_NOOP("GameDatabase", "Force Interlacing"), + TRANSLATE_NOOP("GameDatabase", "Disable True Color"), + TRANSLATE_NOOP("GameDatabase", "Disable Upscaling"), + TRANSLATE_NOOP("GameDatabase", "Disable Texture Filtering"), + TRANSLATE_NOOP("GameDatabase", "Disable Scaled Dithering"), + TRANSLATE_NOOP("GameDatabase", "Disable Force NTSC Timings"), + TRANSLATE_NOOP("GameDatabase", "Disable Widescreen"), + TRANSLATE_NOOP("GameDatabase", "Disable PGXP"), + TRANSLATE_NOOP("GameDatabase", "Disable PGXP Culling"), + TRANSLATE_NOOP("GameDatabase", "Disable PGXP Texture Correction"), + TRANSLATE_NOOP("GameDatabase", "Disable PGXP Color Correction"), + TRANSLATE_NOOP("GameDatabase", "Disable PGXP Depth Buffer"), + TRANSLATE_NOOP("GameDatabase", "Disable PGXP Preserve Projection Floating Point"), + TRANSLATE_NOOP("GameDatabase", "Force PGXP Vertex Cache"), + TRANSLATE_NOOP("GameDatabase", "Force PGXP CPU Mode"), + TRANSLATE_NOOP("GameDatabase", "Force Recompiler Memory Exceptions"), + TRANSLATE_NOOP("GameDatabase", "Force Recompiler ICache"), + TRANSLATE_NOOP("GameDatabase", "Force Recompiler LUT Fastmem"), + TRANSLATE_NOOP("GameDatabase", "Is LibCrypt Protected"), +}}; + static constexpr const char* GAMEDB_YAML_FILENAME = "gamedb.yaml"; static constexpr const char* DISCDB_YAML_FILENAME = "discdb.yaml"; @@ -325,6 +348,17 @@ GameDatabase::Entry* GameDatabase::GetMutableEntry(std::string_view serial) return nullptr; } +const char* GameDatabase::GetTraitName(Trait trait) +{ + return s_trait_names[static_cast(trait)]; +} + +const char* GameDatabase::GetTraitDisplayName(Trait trait) +{ + return Host::TranslateToCString("GameDatabase", s_trait_display_names[static_cast(trait)]); + ""; +} + const char* GameDatabase::GetCompatibilityRatingName(CompatibilityRating rating) { return s_compatibility_rating_names[static_cast(rating)]; @@ -333,8 +367,7 @@ const char* GameDatabase::GetCompatibilityRatingName(CompatibilityRating rating) const char* GameDatabase::GetCompatibilityRatingDisplayName(CompatibilityRating rating) { return (rating >= CompatibilityRating::Unknown && rating < CompatibilityRating::Count) ? - Host::TranslateToCString("GameListCompatibilityRating", - s_compatibility_rating_display_names[static_cast(rating)]) : + Host::TranslateToCString("GameDatabase", s_compatibility_rating_display_names[static_cast(rating)]) : ""; } @@ -671,6 +704,122 @@ void GameDatabase::Entry::ApplySettings(Settings& settings, bool display_osd_mes #undef BIT_FOR } +template +static inline void AppendIntegerSetting(SmallStringBase& str, bool& heading, std::string_view title, + const std::optional& value) +{ + if (!value.has_value()) + return; + + if (!heading) + { + heading = true; + str.append_format("**{}**\n\n", TRANSLATE_SV("GameDatabase", "Settings")); + } + + str.append_format(" - {}: {}\n", title, value.value()); +} + +static inline void AppendFloatSetting(SmallStringBase& str, bool& heading, std::string_view title, + const std::optional& value) +{ + if (!value.has_value()) + return; + + if (!heading) + { + heading = true; + str.append_format("**{}**\n\n", TRANSLATE_SV("GameDatabase", "Settings")); + } + + str.append_format(" - {}: {:.2f}\n", title, value.value()); +} + +template +static inline void AppendEnumSetting(SmallStringBase& str, bool& heading, std::string_view title, + const char* (*get_display_name_func)(T), const std::optional& value) +{ + if (!value.has_value()) + return; + + if (!heading) + { + heading = true; + str.append_format("**{}**\n\n", TRANSLATE_SV("GameDatabase", "Settings")); + } + + str.append_format(" - {}: {}\n", title, get_display_name_func(value.value())); +} + +std::string GameDatabase::Entry::GenerateCompatibilityReport() const +{ + LargeString ret; + ret.append_format("**{}:** {}\n\n", TRANSLATE_SV("GameDatabase", "Title"), title); + ret.append_format("**{}:** {}\n\n", TRANSLATE_SV("GameDatabase", "Serial"), serial); + ret.append_format("**{}:** {}\n\n", TRANSLATE_SV("GameDatabase", "Rating"), + GetCompatibilityRatingDisplayName(compatibility)); + + if (!compatibility_version_tested.empty()) + ret.append_format("**{}:**\n{}\n\n", TRANSLATE_SV("GameDatabase", "Version Tested"), compatibility_version_tested); + + if (!compatibility_comments.empty()) + ret.append_format("**{}**\n\n{}\n\n", TRANSLATE_SV("GameDatabase", "Comments"), compatibility_comments); + + if (supported_controllers != 0) + { + ret.append_format("**{}**\n\n", TRANSLATE_SV("GameDatabase", "Supported Controllers")); + + for (u32 j = 0; j < static_cast(ControllerType::Count); j++) + { + if ((supported_controllers & (static_cast(1) << j)) == 0) + continue; + + ret.append_format(" - {}\n", Controller::GetControllerInfo(static_cast(j))->GetDisplayName()); + } + + ret.append("\n"); + } + + if (traits.any()) + { + ret.append_format("**{}**\n\n", TRANSLATE_SV("GameDatabase", "Traits")); + for (u32 i = 0; i < static_cast(Trait::Count); i++) + { + if (traits.test(i)) + ret.append_format(" - {}\n", GetTraitDisplayName(static_cast(i))); + } + ret.append("\n"); + } + + bool settings_heading = false; + AppendIntegerSetting(ret, settings_heading, TRANSLATE_SV("GameDatabase", "Display Active Start Offset"), + display_active_start_offset); + AppendIntegerSetting(ret, settings_heading, TRANSLATE_SV("GameDatabase", "Display Active End Offset"), + display_active_end_offset); + AppendIntegerSetting(ret, settings_heading, TRANSLATE_SV("GameDatabase", "Display Line Start Offset"), + display_line_start_offset); + AppendIntegerSetting(ret, settings_heading, TRANSLATE_SV("GameDatabase", "Display Line End Offset"), + display_line_end_offset); + AppendIntegerSetting(ret, settings_heading, TRANSLATE_SV("GameDatabase", "DMA Max Slice Ticks"), dma_max_slice_ticks); + AppendIntegerSetting(ret, settings_heading, TRANSLATE_SV("GameDatabase", "DMA Halt Ticks"), dma_halt_ticks); + AppendIntegerSetting(ret, settings_heading, TRANSLATE_SV("GameDatabase", "GPU FIFO Size"), gpu_fifo_size); + AppendIntegerSetting(ret, settings_heading, TRANSLATE_SV("GameDatabase", "GPU Max Runahead"), gpu_max_run_ahead); + AppendFloatSetting(ret, settings_heading, TRANSLATE_SV("GameDatabase", "GPU PGXP Tolerance"), gpu_pgxp_tolerance); + AppendFloatSetting(ret, settings_heading, TRANSLATE_SV("GameDatabase", "GPU PGXP Depth Threshold"), + gpu_pgxp_depth_threshold); + AppendEnumSetting(ret, settings_heading, TRANSLATE_SV("GameDatabase", "GPU Line Detect Mode"), + &Settings::GetLineDetectModeDisplayName, gpu_line_detect_mode); + + if (!disc_set_name.empty()) + { + ret.append_format("**{}:** {}\n", TRANSLATE_SV("GameDatabase", "Disc Set"), disc_set_name); + for (const std::string& ds_serial : disc_set_serials) + ret.append_format(" - {}\n", ds_serial); + } + + return std::string(ret.view()); +} + template bool ReadOptionalFromStream(ByteStream* stream, std::optional* dest) { @@ -748,7 +897,9 @@ bool GameDatabase::LoadFromCache() if (!stream->ReadSizePrefixedString(&entry.serial) || !stream->ReadSizePrefixedString(&entry.title) || !stream->ReadSizePrefixedString(&entry.genre) || !stream->ReadSizePrefixedString(&entry.developer) || - !stream->ReadSizePrefixedString(&entry.publisher) || !stream->ReadU64(&entry.release_date) || + !stream->ReadSizePrefixedString(&entry.publisher) || + !stream->ReadSizePrefixedString(&entry.compatibility_version_tested) || + !stream->ReadSizePrefixedString(&entry.compatibility_comments) || !stream->ReadU64(&entry.release_date) || !stream->ReadU8(&entry.min_players) || !stream->ReadU8(&entry.max_players) || !stream->ReadU8(&entry.min_blocks) || !stream->ReadU8(&entry.max_blocks) || !stream->ReadU16(&entry.supported_controllers) || !stream->ReadU8(&compatibility) || @@ -834,6 +985,8 @@ bool GameDatabase::SaveToCache() result = result && stream->WriteSizePrefixedString(entry.genre); result = result && stream->WriteSizePrefixedString(entry.developer); result = result && stream->WriteSizePrefixedString(entry.publisher); + result = result && stream->WriteSizePrefixedString(entry.compatibility_version_tested); + result = result && stream->WriteSizePrefixedString(entry.compatibility_comments); result = result && stream->WriteU64(entry.release_date); result = result && stream->WriteU8(entry.min_players); result = result && stream->WriteU8(entry.max_players); @@ -1020,6 +1173,9 @@ bool GameDatabase::ParseYamlEntry(Entry* entry, const ryml::ConstNodeRef& value) Log_WarningFmt("Unknown compatibility rating {} in {}", rating_str, entry->serial); } } + + GetStringFromObject(compatibility, "versionTested", &entry->compatibility_version_tested); + GetStringFromObject(compatibility, "comments", &entry->compatibility_comments); } if (const ryml::ConstNodeRef traits = value.find_child(to_csubstr("traits")); traits.valid() && traits.has_children()) diff --git a/src/core/game_database.h b/src/core/game_database.h index 364109104..4e2b38c0a 100644 --- a/src/core/game_database.h +++ b/src/core/game_database.h @@ -62,6 +62,8 @@ struct Entry std::string genre; std::string developer; std::string publisher; + std::string compatibility_version_tested; + std::string compatibility_comments; u64 release_date; u8 min_players; u8 max_players; @@ -89,6 +91,8 @@ struct Entry ALWAYS_INLINE bool HasTrait(Trait trait) const { return traits[static_cast(trait)]; } void ApplySettings(Settings& settings, bool display_osd_messages) const; + + std::string GenerateCompatibilityReport() const; }; void EnsureLoaded(); @@ -100,6 +104,9 @@ const Entry* GetEntryForSerial(std::string_view serial); std::string GetSerialForDisc(CDImage* image); std::string GetSerialForPath(const char* path); +const char* GetTraitName(Trait trait); +const char* GetTraitDisplayName(Trait trait); + const char* GetCompatibilityRatingName(CompatibilityRating rating); const char* GetCompatibilityRatingDisplayName(CompatibilityRating rating); diff --git a/src/duckstation-qt/gamesummarywidget.cpp b/src/duckstation-qt/gamesummarywidget.cpp index 94ac8c97a..c57426365 100644 --- a/src/duckstation-qt/gamesummarywidget.cpp +++ b/src/duckstation-qt/gamesummarywidget.cpp @@ -16,7 +16,11 @@ #include #include +#include +#include +#include #include +#include GameSummaryWidget::GameSummaryWidget(const std::string& path, const std::string& serial, DiscRegion region, const GameDatabase::Entry* entry, SettingsWindow* dialog, QWidget* parent) @@ -47,6 +51,7 @@ GameSummaryWidget::GameSummaryWidget(const std::string& path, const std::string& populateUi(path, serial, region, entry); + connect(m_ui.compatibilityComments, &QToolButton::clicked, this, &GameSummaryWidget::onCompatibilityCommentsClicked); connect(m_ui.inputProfile, &QComboBox::currentIndexChanged, this, &GameSummaryWidget::onInputProfileChanged); connect(m_ui.computeHashes, &QAbstractButton::clicked, this, &GameSummaryWidget::onComputeHashClicked); } @@ -121,6 +126,8 @@ void GameSummaryWidget::populateUi(const std::string& path, const std::string& s if (controllers.isEmpty()) controllers = tr("Unknown"); m_ui.controllers->setText(controllers); + + m_compatibility_comments = QString::fromStdString(entry->GenerateCompatibilityReport()); } else { @@ -138,6 +145,8 @@ void GameSummaryWidget::populateUi(const std::string& path, const std::string& s m_ui.entryType->setCurrentIndex(static_cast(gentry->type)); } + m_ui.compatibilityComments->setVisible(!m_compatibility_comments.isEmpty()); + m_ui.inputProfile->addItem(QIcon::fromTheme(QStringLiteral("controller-digital-line")), tr("Use Global Settings")); for (const std::string& name : InputManager::GetInputProfileNames()) m_ui.inputProfile->addItem(QString::fromStdString(name)); @@ -196,6 +205,26 @@ void GameSummaryWidget::populateTracksInfo() } } +void GameSummaryWidget::onCompatibilityCommentsClicked() +{ + QDialog dlg(QtUtils::GetRootWidget(this)); + dlg.resize(QSize(700, 400)); + dlg.setWindowModality(Qt::WindowModal); + dlg.setWindowTitle(tr("Compatibility Report")); + + QVBoxLayout* layout = new QVBoxLayout(&dlg); + + QTextBrowser* tb = new QTextBrowser(&dlg); + tb->setMarkdown(m_compatibility_comments); + layout->addWidget(tb, 1); + + QDialogButtonBox* bb = new QDialogButtonBox(QDialogButtonBox::Close, &dlg); + connect(bb->button(QDialogButtonBox::Close), &QPushButton::clicked, &dlg, &QDialog::accept); + layout->addWidget(bb); + + dlg.exec(); +} + void GameSummaryWidget::onInputProfileChanged(int index) { if (index == 0) diff --git a/src/duckstation-qt/gamesummarywidget.h b/src/duckstation-qt/gamesummarywidget.h index 2e7c99f31..fb0dbe107 100644 --- a/src/duckstation-qt/gamesummarywidget.h +++ b/src/duckstation-qt/gamesummarywidget.h @@ -25,6 +25,7 @@ public: ~GameSummaryWidget(); private Q_SLOTS: + void onCompatibilityCommentsClicked(); void onInputProfileChanged(int index); void onComputeHashClicked(); @@ -38,4 +39,5 @@ private: std::string m_path; std::string m_redump_search_keyword; + QString m_compatibility_comments; }; diff --git a/src/duckstation-qt/gamesummarywidget.ui b/src/duckstation-qt/gamesummarywidget.ui index f2d981825..7bd0b416e 100644 --- a/src/duckstation-qt/gamesummarywidget.ui +++ b/src/duckstation-qt/gamesummarywidget.ui @@ -270,9 +270,13 @@ - + - Edit... + Comments + + + + .. diff --git a/src/duckstation-qt/resources/icons/black/svg/information-line.svg b/src/duckstation-qt/resources/icons/black/svg/information-line.svg new file mode 100644 index 000000000..27a6fdbb6 --- /dev/null +++ b/src/duckstation-qt/resources/icons/black/svg/information-line.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/duckstation-qt/resources/icons/white/svg/information-line.svg b/src/duckstation-qt/resources/icons/white/svg/information-line.svg new file mode 100644 index 000000000..63aec2dab --- /dev/null +++ b/src/duckstation-qt/resources/icons/white/svg/information-line.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/duckstation-qt/resources/resources.qrc b/src/duckstation-qt/resources/resources.qrc index 5a7271dfd..f2b3f12c7 100644 --- a/src/duckstation-qt/resources/resources.qrc +++ b/src/duckstation-qt/resources/resources.qrc @@ -6,23 +6,26 @@ controllers/guncon.svg controllers/mouse.svg controllers/negcon.svg - icons/address-book-new-22@2x.png + icons/IssueTracker.png + icons/QT.png + icons/UpdateDuck.png icons/address-book-new-22.png - icons/antialias-icon@2x.png + icons/address-book-new-22@2x.png icons/antialias-icon.png - icons/applications-development@2x.png + icons/antialias-icon@2x.png icons/applications-development.png - icons/applications-graphics@2x.png + icons/applications-development@2x.png icons/applications-graphics.png + icons/applications-graphics@2x.png icons/applications-internet.png - icons/applications-other@2x.png icons/applications-other.png - icons/applications-system-24@2x.png + icons/applications-other@2x.png icons/applications-system-24.png - icons/applications-system@2x.png + icons/applications-system-24@2x.png icons/applications-system.png - icons/audio-card@2x.png + icons/applications-system@2x.png icons/audio-card.png + icons/audio-card@2x.png icons/black/index.theme icons/black/svg/add-line.svg icons/black/svg/alert-line.svg @@ -38,16 +41,16 @@ icons/black/svg/controller-digital-line.svg icons/black/svg/controller-line.svg icons/black/svg/controller-strike-line.svg - icons/black/svg/debugger-clear-breakpoint.svg - icons/black/svg/debugger-dump-address.svg - icons/black/svg/debugger-go-to-address.svg - icons/black/svg/debugger-go-to-cursor.svg - icons/black/svg/debugger-go-to-pc.svg icons/black/svg/debug-step-into-line.svg icons/black/svg/debug-step-out-line.svg icons/black/svg/debug-step-over-line.svg icons/black/svg/debug-toggle-breakpoint.svg icons/black/svg/debug-trace-line.svg + icons/black/svg/debugger-clear-breakpoint.svg + icons/black/svg/debugger-dump-address.svg + icons/black/svg/debugger-go-to-address.svg + icons/black/svg/debugger-go-to-cursor.svg + icons/black/svg/debugger-go-to-pc.svg icons/black/svg/disc-eject-line.svg icons/black/svg/disc-line.svg icons/black/svg/door-open-line.svg @@ -73,6 +76,7 @@ icons/black/svg/global-line.svg icons/black/svg/guncon-line.svg icons/black/svg/image-fill.svg + icons/black/svg/information-line.svg icons/black/svg/joystick-line.svg icons/black/svg/keyboard-line.svg icons/black/svg/layout-grid-line.svg @@ -102,17 +106,17 @@ icons/black/svg/tv-2-line.svg icons/black/svg/volume-up-line.svg icons/black/svg/window-2-line.svg - icons/camera-photo@2x.png icons/camera-photo.png - icons/camera-video@2x.png + icons/camera-photo@2x.png icons/camera-video.png - icons/conical-flask-red@2x.png + icons/camera-video@2x.png icons/conical-flask-red.png + icons/conical-flask-red@2x.png icons/cover-placeholder.png icons/debug-execute-from-cursor.png icons/debug-execute-to-cursor.png - icons/debug-pc@2x.png icons/debug-pc.png + icons/debug-pc@2x.png icons/debug-run-cursor.png icons/debug-run.png icons/debug-step-instruction.png @@ -122,137 +126,134 @@ icons/debug-step-over.png icons/debug-trace.png icons/discord.png - icons/document-new@2x.png icons/document-new.png - icons/document-open@2x.png + icons/document-new@2x.png icons/document-open.png - icons/document-save@2x.png + icons/document-open@2x.png icons/document-save.png - icons/drive-optical@2x.png + icons/document-save@2x.png icons/drive-optical.png - icons/drive-removable-media@2x.png + icons/drive-optical@2x.png icons/drive-removable-media.png + icons/drive-removable-media@2x.png + icons/duck.png icons/duck_128.png icons/duck_64.png - icons/duck.png - icons/edit-clear-16@2x.png icons/edit-clear-16.png + icons/edit-clear-16@2x.png icons/edit-find.png - icons/emblem-person-blue@2x.png icons/emblem-person-blue.png - icons/flag-eu@2x.png + icons/emblem-person-blue@2x.png icons/flag-eu.png icons/flag-eu.svg - icons/flag-jp@2x.png + icons/flag-eu@2x.png icons/flag-jp.png icons/flag-jp.svg - icons/flag-other@2x.png + icons/flag-jp@2x.png icons/flag-other.png - icons/flags/de@2x.png + icons/flag-other@2x.png + icons/flag-uc.png + icons/flag-uc.svg + icons/flag-uc@2x.png + icons/flag-us.png + icons/flag-us.svg + icons/flag-us@2x.png icons/flags/de.png - icons/flags/en@2x.png + icons/flags/de@2x.png icons/flags/en.png - icons/flags/es-ES@2x.png + icons/flags/en@2x.png icons/flags/es-ES.png - icons/flags/fr@2x.png + icons/flags/es-ES@2x.png icons/flags/fr.png - icons/flags/he@2x.png + icons/flags/fr@2x.png icons/flags/he.png - icons/flags/id@2x.png + icons/flags/he@2x.png icons/flags/id.png - icons/flags/it@2x.png + icons/flags/id@2x.png icons/flags/it.png - icons/flags/ja@2x.png + icons/flags/it@2x.png icons/flags/ja.png - icons/flags/ko@2x.png + icons/flags/ja@2x.png icons/flags/ko.png - icons/flags/nl@2x.png + icons/flags/ko@2x.png icons/flags/nl.png - icons/flags/pl@2x.png + icons/flags/nl@2x.png icons/flags/pl.png - icons/flags/pt-BR@2x.png + icons/flags/pl@2x.png icons/flags/pt-BR.png - icons/flags/pt-PT@2x.png + icons/flags/pt-BR@2x.png icons/flags/pt-PT.png - icons/flags/ru@2x.png + icons/flags/pt-PT@2x.png icons/flags/ru.png - icons/flags/tr@2x.png + icons/flags/ru@2x.png icons/flags/tr.png - icons/flags/zh-CN@2x.png + icons/flags/tr@2x.png icons/flags/zh-CN.png - icons/flag-uc@2x.png - icons/flag-uc.png - icons/flag-uc.svg - icons/flag-us@2x.png - icons/flag-us.png - icons/flag-us.svg - icons/folder-open@2x.png + icons/flags/zh-CN@2x.png icons/folder-open.png + icons/folder-open@2x.png icons/github.png - icons/go-down-16@2x.png icons/go-down-16.png - icons/go-up-16@2x.png + icons/go-down-16@2x.png icons/go-up-16.png - icons/input-gaming@2x.png + icons/go-up-16@2x.png icons/input-gaming.png - icons/IssueTracker.png - icons/list-add@2x.png + icons/input-gaming@2x.png icons/list-add.png - icons/list-remove@2x.png + icons/list-add@2x.png icons/list-remove.png - icons/media-flash-2@2x.png - icons/media-flash-24@2x.png - icons/media-flash-24.png + icons/list-remove@2x.png icons/media-flash-2.png - icons/media-flash@2x.png + icons/media-flash-24.png + icons/media-flash-24@2x.png + icons/media-flash-2@2x.png icons/media-flash.png - icons/media-optical-24@2x.png + icons/media-flash@2x.png icons/media-optical-24.png - icons/media-optical@2x.png - icons/media-optical-gear-24@2x.png + icons/media-optical-24@2x.png icons/media-optical-gear-24.png + icons/media-optical-gear-24@2x.png icons/media-optical.png - icons/media-playback-pause@2x.png + icons/media-optical@2x.png icons/media-playback-pause.png - icons/media-playback-start@2x.png + icons/media-playback-pause@2x.png icons/media-playback-start.png - icons/media-record@2x.png + icons/media-playback-start@2x.png icons/media-record.png - icons/multimedia-player@2x.png + icons/media-record@2x.png icons/multimedia-player.png - icons/preferences-desktop-keyboard-shortcuts@2x.png + icons/multimedia-player@2x.png icons/preferences-desktop-keyboard-shortcuts.png - icons/preferences-system@2x.png + icons/preferences-desktop-keyboard-shortcuts@2x.png icons/preferences-system.png - icons/process-stop@2x.png + icons/preferences-system@2x.png icons/process-stop.png - icons/QT.png - icons/software-update-available@2x.png + icons/process-stop@2x.png icons/software-update-available.png + icons/software-update-available@2x.png icons/star-0.png icons/star-1.png icons/star-2.png icons/star-3.png icons/star-4.png icons/star-5.png - icons/system-file-manager@2x.png icons/system-file-manager.png - icons/system-search@2x.png + icons/system-file-manager@2x.png icons/system-search.png - icons/system-shutdown@2x.png + icons/system-search@2x.png icons/system-shutdown.png - icons/trophy@2x.png + icons/system-shutdown@2x.png icons/trophy.png - icons/UpdateDuck.png + icons/trophy@2x.png icons/update.png - icons/utilities-system-monitor@2x.png icons/utilities-system-monitor.png - icons/video-display@2x.png + icons/utilities-system-monitor@2x.png icons/video-display.png - icons/view-fullscreen@2x.png + icons/video-display@2x.png icons/view-fullscreen.png - icons/view-refresh@2x.png + icons/view-fullscreen@2x.png icons/view-refresh.png + icons/view-refresh@2x.png icons/white/index.theme icons/white/svg/add-line.svg icons/white/svg/alert-line.svg @@ -268,16 +269,16 @@ icons/white/svg/controller-digital-line.svg icons/white/svg/controller-line.svg icons/white/svg/controller-strike-line.svg - icons/white/svg/debugger-clear-breakpoint.svg - icons/white/svg/debugger-dump-address.svg - icons/white/svg/debugger-go-to-address.svg - icons/white/svg/debugger-go-to-cursor.svg - icons/white/svg/debugger-go-to-pc.svg icons/white/svg/debug-step-into-line.svg icons/white/svg/debug-step-out-line.svg icons/white/svg/debug-step-over-line.svg icons/white/svg/debug-toggle-breakpoint.svg icons/white/svg/debug-trace-line.svg + icons/white/svg/debugger-clear-breakpoint.svg + icons/white/svg/debugger-dump-address.svg + icons/white/svg/debugger-go-to-address.svg + icons/white/svg/debugger-go-to-cursor.svg + icons/white/svg/debugger-go-to-pc.svg icons/white/svg/disc-eject-line.svg icons/white/svg/disc-line.svg icons/white/svg/door-open-line.svg @@ -303,6 +304,7 @@ icons/white/svg/global-line.svg icons/white/svg/guncon-line.svg icons/white/svg/image-fill.svg + icons/white/svg/information-line.svg icons/white/svg/joystick-line.svg icons/white/svg/keyboard-line.svg icons/white/svg/layout-grid-line.svg @@ -332,214 +334,214 @@ icons/white/svg/tv-2-line.svg icons/white/svg/volume-up-line.svg icons/white/svg/window-2-line.svg + qdarkstyle/arrow_down.png qdarkstyle/arrow_down@2x.png - qdarkstyle/arrow_down_disabled@2x.png qdarkstyle/arrow_down_disabled.png - qdarkstyle/arrow_down_focus@2x.png + qdarkstyle/arrow_down_disabled@2x.png qdarkstyle/arrow_down_focus.png - qdarkstyle/arrow_down.png - qdarkstyle/arrow_down_pressed@2x.png + qdarkstyle/arrow_down_focus@2x.png qdarkstyle/arrow_down_pressed.png + qdarkstyle/arrow_down_pressed@2x.png + qdarkstyle/arrow_left.png qdarkstyle/arrow_left@2x.png - qdarkstyle/arrow_left_disabled@2x.png qdarkstyle/arrow_left_disabled.png - qdarkstyle/arrow_left_focus@2x.png + qdarkstyle/arrow_left_disabled@2x.png qdarkstyle/arrow_left_focus.png - qdarkstyle/arrow_left.png - qdarkstyle/arrow_left_pressed@2x.png + qdarkstyle/arrow_left_focus@2x.png qdarkstyle/arrow_left_pressed.png + qdarkstyle/arrow_left_pressed@2x.png + qdarkstyle/arrow_right.png qdarkstyle/arrow_right@2x.png - qdarkstyle/arrow_right_disabled@2x.png qdarkstyle/arrow_right_disabled.png - qdarkstyle/arrow_right_focus@2x.png + qdarkstyle/arrow_right_disabled@2x.png qdarkstyle/arrow_right_focus.png - qdarkstyle/arrow_right.png - qdarkstyle/arrow_right_pressed@2x.png + qdarkstyle/arrow_right_focus@2x.png qdarkstyle/arrow_right_pressed.png + qdarkstyle/arrow_right_pressed@2x.png + qdarkstyle/arrow_up.png qdarkstyle/arrow_up@2x.png - qdarkstyle/arrow_up_disabled@2x.png qdarkstyle/arrow_up_disabled.png - qdarkstyle/arrow_up_focus@2x.png + qdarkstyle/arrow_up_disabled@2x.png qdarkstyle/arrow_up_focus.png - qdarkstyle/arrow_up.png - qdarkstyle/arrow_up_pressed@2x.png + qdarkstyle/arrow_up_focus@2x.png qdarkstyle/arrow_up_pressed.png + qdarkstyle/arrow_up_pressed@2x.png + qdarkstyle/base_icon.png qdarkstyle/base_icon@2x.png - qdarkstyle/base_icon_disabled@2x.png qdarkstyle/base_icon_disabled.png - qdarkstyle/base_icon_focus@2x.png + qdarkstyle/base_icon_disabled@2x.png qdarkstyle/base_icon_focus.png - qdarkstyle/base_icon.png - qdarkstyle/base_icon_pressed@2x.png + qdarkstyle/base_icon_focus@2x.png qdarkstyle/base_icon_pressed.png + qdarkstyle/base_icon_pressed@2x.png + qdarkstyle/branch_closed.png qdarkstyle/branch_closed@2x.png - qdarkstyle/branch_closed_disabled@2x.png qdarkstyle/branch_closed_disabled.png - qdarkstyle/branch_closed_focus@2x.png + qdarkstyle/branch_closed_disabled@2x.png qdarkstyle/branch_closed_focus.png - qdarkstyle/branch_closed.png - qdarkstyle/branch_closed_pressed@2x.png + qdarkstyle/branch_closed_focus@2x.png qdarkstyle/branch_closed_pressed.png + qdarkstyle/branch_closed_pressed@2x.png + qdarkstyle/branch_end.png qdarkstyle/branch_end@2x.png - qdarkstyle/branch_end_disabled@2x.png qdarkstyle/branch_end_disabled.png - qdarkstyle/branch_end_focus@2x.png + qdarkstyle/branch_end_disabled@2x.png qdarkstyle/branch_end_focus.png - qdarkstyle/branch_end.png - qdarkstyle/branch_end_pressed@2x.png + qdarkstyle/branch_end_focus@2x.png qdarkstyle/branch_end_pressed.png + qdarkstyle/branch_end_pressed@2x.png + qdarkstyle/branch_line.png qdarkstyle/branch_line@2x.png - qdarkstyle/branch_line_disabled@2x.png qdarkstyle/branch_line_disabled.png - qdarkstyle/branch_line_focus@2x.png + qdarkstyle/branch_line_disabled@2x.png qdarkstyle/branch_line_focus.png - qdarkstyle/branch_line.png - qdarkstyle/branch_line_pressed@2x.png + qdarkstyle/branch_line_focus@2x.png qdarkstyle/branch_line_pressed.png + qdarkstyle/branch_line_pressed@2x.png + qdarkstyle/branch_more.png qdarkstyle/branch_more@2x.png - qdarkstyle/branch_more_disabled@2x.png qdarkstyle/branch_more_disabled.png - qdarkstyle/branch_more_focus@2x.png + qdarkstyle/branch_more_disabled@2x.png qdarkstyle/branch_more_focus.png - qdarkstyle/branch_more.png - qdarkstyle/branch_more_pressed@2x.png + qdarkstyle/branch_more_focus@2x.png qdarkstyle/branch_more_pressed.png + qdarkstyle/branch_more_pressed@2x.png + qdarkstyle/branch_open.png qdarkstyle/branch_open@2x.png - qdarkstyle/branch_open_disabled@2x.png qdarkstyle/branch_open_disabled.png - qdarkstyle/branch_open_focus@2x.png + qdarkstyle/branch_open_disabled@2x.png qdarkstyle/branch_open_focus.png - qdarkstyle/branch_open.png - qdarkstyle/branch_open_pressed@2x.png + qdarkstyle/branch_open_focus@2x.png qdarkstyle/branch_open_pressed.png + qdarkstyle/branch_open_pressed@2x.png + qdarkstyle/checkbox_checked.png qdarkstyle/checkbox_checked@2x.png - qdarkstyle/checkbox_checked_disabled@2x.png qdarkstyle/checkbox_checked_disabled.png - qdarkstyle/checkbox_checked_focus@2x.png + qdarkstyle/checkbox_checked_disabled@2x.png qdarkstyle/checkbox_checked_focus.png - qdarkstyle/checkbox_checked.png - qdarkstyle/checkbox_checked_pressed@2x.png + qdarkstyle/checkbox_checked_focus@2x.png qdarkstyle/checkbox_checked_pressed.png + qdarkstyle/checkbox_checked_pressed@2x.png + qdarkstyle/checkbox_indeterminate.png qdarkstyle/checkbox_indeterminate@2x.png - qdarkstyle/checkbox_indeterminate_disabled@2x.png qdarkstyle/checkbox_indeterminate_disabled.png - qdarkstyle/checkbox_indeterminate_focus@2x.png + qdarkstyle/checkbox_indeterminate_disabled@2x.png qdarkstyle/checkbox_indeterminate_focus.png - qdarkstyle/checkbox_indeterminate.png - qdarkstyle/checkbox_indeterminate_pressed@2x.png + qdarkstyle/checkbox_indeterminate_focus@2x.png qdarkstyle/checkbox_indeterminate_pressed.png + qdarkstyle/checkbox_indeterminate_pressed@2x.png + qdarkstyle/checkbox_unchecked.png qdarkstyle/checkbox_unchecked@2x.png - qdarkstyle/checkbox_unchecked_disabled@2x.png qdarkstyle/checkbox_unchecked_disabled.png - qdarkstyle/checkbox_unchecked_focus@2x.png + qdarkstyle/checkbox_unchecked_disabled@2x.png qdarkstyle/checkbox_unchecked_focus.png - qdarkstyle/checkbox_unchecked.png - qdarkstyle/checkbox_unchecked_pressed@2x.png + qdarkstyle/checkbox_unchecked_focus@2x.png qdarkstyle/checkbox_unchecked_pressed.png + qdarkstyle/checkbox_unchecked_pressed@2x.png + qdarkstyle/line_horizontal.png qdarkstyle/line_horizontal@2x.png - qdarkstyle/line_horizontal_disabled@2x.png qdarkstyle/line_horizontal_disabled.png - qdarkstyle/line_horizontal_focus@2x.png + qdarkstyle/line_horizontal_disabled@2x.png qdarkstyle/line_horizontal_focus.png - qdarkstyle/line_horizontal.png - qdarkstyle/line_horizontal_pressed@2x.png + qdarkstyle/line_horizontal_focus@2x.png qdarkstyle/line_horizontal_pressed.png + qdarkstyle/line_horizontal_pressed@2x.png + qdarkstyle/line_vertical.png qdarkstyle/line_vertical@2x.png - qdarkstyle/line_vertical_disabled@2x.png qdarkstyle/line_vertical_disabled.png - qdarkstyle/line_vertical_focus@2x.png + qdarkstyle/line_vertical_disabled@2x.png qdarkstyle/line_vertical_focus.png - qdarkstyle/line_vertical.png - qdarkstyle/line_vertical_pressed@2x.png + qdarkstyle/line_vertical_focus@2x.png qdarkstyle/line_vertical_pressed.png + qdarkstyle/line_vertical_pressed@2x.png + qdarkstyle/radio_checked.png qdarkstyle/radio_checked@2x.png - qdarkstyle/radio_checked_disabled@2x.png qdarkstyle/radio_checked_disabled.png - qdarkstyle/radio_checked_focus@2x.png + qdarkstyle/radio_checked_disabled@2x.png qdarkstyle/radio_checked_focus.png - qdarkstyle/radio_checked.png - qdarkstyle/radio_checked_pressed@2x.png + qdarkstyle/radio_checked_focus@2x.png qdarkstyle/radio_checked_pressed.png + qdarkstyle/radio_checked_pressed@2x.png + qdarkstyle/radio_unchecked.png qdarkstyle/radio_unchecked@2x.png - qdarkstyle/radio_unchecked_disabled@2x.png qdarkstyle/radio_unchecked_disabled.png - qdarkstyle/radio_unchecked_focus@2x.png + qdarkstyle/radio_unchecked_disabled@2x.png qdarkstyle/radio_unchecked_focus.png - qdarkstyle/radio_unchecked.png - qdarkstyle/radio_unchecked_pressed@2x.png + qdarkstyle/radio_unchecked_focus@2x.png qdarkstyle/radio_unchecked_pressed.png + qdarkstyle/radio_unchecked_pressed@2x.png qdarkstyle/style.qss + qdarkstyle/toolbar_move_horizontal.png qdarkstyle/toolbar_move_horizontal@2x.png - qdarkstyle/toolbar_move_horizontal_disabled@2x.png qdarkstyle/toolbar_move_horizontal_disabled.png - qdarkstyle/toolbar_move_horizontal_focus@2x.png + qdarkstyle/toolbar_move_horizontal_disabled@2x.png qdarkstyle/toolbar_move_horizontal_focus.png - qdarkstyle/toolbar_move_horizontal.png - qdarkstyle/toolbar_move_horizontal_pressed@2x.png + qdarkstyle/toolbar_move_horizontal_focus@2x.png qdarkstyle/toolbar_move_horizontal_pressed.png + qdarkstyle/toolbar_move_horizontal_pressed@2x.png + qdarkstyle/toolbar_move_vertical.png qdarkstyle/toolbar_move_vertical@2x.png - qdarkstyle/toolbar_move_vertical_disabled@2x.png qdarkstyle/toolbar_move_vertical_disabled.png - qdarkstyle/toolbar_move_vertical_focus@2x.png + qdarkstyle/toolbar_move_vertical_disabled@2x.png qdarkstyle/toolbar_move_vertical_focus.png - qdarkstyle/toolbar_move_vertical.png - qdarkstyle/toolbar_move_vertical_pressed@2x.png + qdarkstyle/toolbar_move_vertical_focus@2x.png qdarkstyle/toolbar_move_vertical_pressed.png + qdarkstyle/toolbar_move_vertical_pressed@2x.png + qdarkstyle/toolbar_separator_horizontal.png qdarkstyle/toolbar_separator_horizontal@2x.png - qdarkstyle/toolbar_separator_horizontal_disabled@2x.png qdarkstyle/toolbar_separator_horizontal_disabled.png - qdarkstyle/toolbar_separator_horizontal_focus@2x.png + qdarkstyle/toolbar_separator_horizontal_disabled@2x.png qdarkstyle/toolbar_separator_horizontal_focus.png - qdarkstyle/toolbar_separator_horizontal.png - qdarkstyle/toolbar_separator_horizontal_pressed@2x.png + qdarkstyle/toolbar_separator_horizontal_focus@2x.png qdarkstyle/toolbar_separator_horizontal_pressed.png + qdarkstyle/toolbar_separator_horizontal_pressed@2x.png + qdarkstyle/toolbar_separator_vertical.png qdarkstyle/toolbar_separator_vertical@2x.png - qdarkstyle/toolbar_separator_vertical_disabled@2x.png qdarkstyle/toolbar_separator_vertical_disabled.png - qdarkstyle/toolbar_separator_vertical_focus@2x.png + qdarkstyle/toolbar_separator_vertical_disabled@2x.png qdarkstyle/toolbar_separator_vertical_focus.png - qdarkstyle/toolbar_separator_vertical.png - qdarkstyle/toolbar_separator_vertical_pressed@2x.png + qdarkstyle/toolbar_separator_vertical_focus@2x.png qdarkstyle/toolbar_separator_vertical_pressed.png + qdarkstyle/toolbar_separator_vertical_pressed@2x.png + qdarkstyle/transparent.png qdarkstyle/transparent@2x.png - qdarkstyle/transparent_disabled@2x.png qdarkstyle/transparent_disabled.png - qdarkstyle/transparent_focus@2x.png + qdarkstyle/transparent_disabled@2x.png qdarkstyle/transparent_focus.png - qdarkstyle/transparent.png - qdarkstyle/transparent_pressed@2x.png + qdarkstyle/transparent_focus@2x.png qdarkstyle/transparent_pressed.png + qdarkstyle/transparent_pressed@2x.png + qdarkstyle/window_close.png qdarkstyle/window_close@2x.png - qdarkstyle/window_close_disabled@2x.png qdarkstyle/window_close_disabled.png - qdarkstyle/window_close_focus@2x.png + qdarkstyle/window_close_disabled@2x.png qdarkstyle/window_close_focus.png - qdarkstyle/window_close.png - qdarkstyle/window_close_pressed@2x.png + qdarkstyle/window_close_focus@2x.png qdarkstyle/window_close_pressed.png + qdarkstyle/window_close_pressed@2x.png + qdarkstyle/window_grip.png qdarkstyle/window_grip@2x.png - qdarkstyle/window_grip_disabled@2x.png qdarkstyle/window_grip_disabled.png - qdarkstyle/window_grip_focus@2x.png + qdarkstyle/window_grip_disabled@2x.png qdarkstyle/window_grip_focus.png - qdarkstyle/window_grip.png - qdarkstyle/window_grip_pressed@2x.png + qdarkstyle/window_grip_focus@2x.png qdarkstyle/window_grip_pressed.png + qdarkstyle/window_grip_pressed@2x.png + qdarkstyle/window_minimize.png qdarkstyle/window_minimize@2x.png - qdarkstyle/window_minimize_disabled@2x.png qdarkstyle/window_minimize_disabled.png - qdarkstyle/window_minimize_focus@2x.png + qdarkstyle/window_minimize_disabled@2x.png qdarkstyle/window_minimize_focus.png - qdarkstyle/window_minimize.png - qdarkstyle/window_minimize_pressed@2x.png + qdarkstyle/window_minimize_focus@2x.png qdarkstyle/window_minimize_pressed.png + qdarkstyle/window_minimize_pressed@2x.png + qdarkstyle/window_undock.png qdarkstyle/window_undock@2x.png - qdarkstyle/window_undock_disabled@2x.png qdarkstyle/window_undock_disabled.png - qdarkstyle/window_undock_focus@2x.png + qdarkstyle/window_undock_disabled@2x.png qdarkstyle/window_undock_focus.png - qdarkstyle/window_undock.png - qdarkstyle/window_undock_pressed@2x.png + qdarkstyle/window_undock_focus@2x.png qdarkstyle/window_undock_pressed.png + qdarkstyle/window_undock_pressed@2x.png