compatibility_data: Added compatibility related settings to GUI (#1855)
Some checks are pending
Build and Release / reuse (push) Waiting to run
Build and Release / clang-format (push) Waiting to run
Build and Release / get-info (push) Waiting to run
Build and Release / windows-sdl (push) Blocked by required conditions
Build and Release / windows-qt (push) Blocked by required conditions
Build and Release / macos-sdl (push) Blocked by required conditions
Build and Release / macos-qt (push) Blocked by required conditions
Build and Release / linux-sdl (push) Blocked by required conditions
Build and Release / linux-qt (push) Blocked by required conditions
Build and Release / pre-release (push) Blocked by required conditions

* compatibility_data: added compatibility related settings to gui
* New game compatibility section in settings dialog
* Context menu now has a compatibility section
* Adjusted minimum size of updater section to 265

* update translations

* revert to deprecated statechanged

* fix display compatibility data option
This commit is contained in:
f8ith 2024-12-25 15:30:09 +08:00 committed by GitHub
parent a89c29c2ca
commit d55e41a19e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
11 changed files with 256 additions and 37 deletions

View file

@ -18,9 +18,10 @@ CompatibilityInfoClass::CompatibilityInfoClass()
};
CompatibilityInfoClass::~CompatibilityInfoClass() = default;
void CompatibilityInfoClass::UpdateCompatibilityDatabase(QWidget* parent) {
if (LoadCompatibilityFile())
return;
void CompatibilityInfoClass::UpdateCompatibilityDatabase(QWidget* parent, bool forced) {
if (!forced)
if (LoadCompatibilityFile())
return;
QNetworkReply* reply = FetchPage(1);
if (!WaitForReply(reply))
@ -45,7 +46,8 @@ void CompatibilityInfoClass::UpdateCompatibilityDatabase(QWidget* parent) {
QMessageBox::critical(parent, tr("Error"),
tr("Unable to update compatibility data! Try again later."));
// Try loading compatibility_file.json again
LoadCompatibilityFile();
if (!forced)
LoadCompatibilityFile();
return;
}

View file

@ -84,7 +84,7 @@ public:
CompatibilityInfoClass();
~CompatibilityInfoClass();
void UpdateCompatibilityDatabase(QWidget* parent = nullptr);
void UpdateCompatibilityDatabase(QWidget* parent = nullptr, bool forced = false);
bool LoadCompatibilityFile();
CompatibilityEntry GetCompatibilityInfo(const std::string& serial);
void ExtractCompatibilityInfo(QByteArray response);

View file

@ -3,9 +3,12 @@
#include "common/path_util.h"
#include "game_grid_frame.h"
#include "qt_gui/compatibility_info.h"
GameGridFrame::GameGridFrame(std::shared_ptr<GameInfoClass> game_info_get, QWidget* parent)
: QTableWidget(parent), m_game_info(game_info_get) {
GameGridFrame::GameGridFrame(std::shared_ptr<GameInfoClass> game_info_get,
std::shared_ptr<CompatibilityInfoClass> compat_info_get,
QWidget* parent)
: QTableWidget(parent), m_game_info(game_info_get), m_compat_info(compat_info_get) {
icon_size = Config::getIconSizeGrid();
windowWidth = parent->width();
this->setShowGrid(false);
@ -29,7 +32,7 @@ GameGridFrame::GameGridFrame(std::shared_ptr<GameInfoClass> game_info_get, QWidg
connect(this->horizontalScrollBar(), &QScrollBar::valueChanged, this,
&GameGridFrame::RefreshGridBackgroundImage);
connect(this, &QTableWidget::customContextMenuRequested, this, [=, this](const QPoint& pos) {
m_gui_context_menus.RequestGameMenu(pos, m_game_info->m_games, this, false);
m_gui_context_menus.RequestGameMenu(pos, m_game_info->m_games, m_compat_info, this, false);
});
}

View file

@ -10,6 +10,7 @@
#include "game_info.h"
#include "game_list_utils.h"
#include "gui_context_menus.h"
#include "qt_gui/compatibility_info.h"
class GameGridFrame : public QTableWidget {
Q_OBJECT
@ -29,11 +30,14 @@ private:
GameListUtils m_game_list_utils;
GuiContextMenus m_gui_context_menus;
std::shared_ptr<GameInfoClass> m_game_info;
std::shared_ptr<CompatibilityInfoClass> m_compat_info;
std::shared_ptr<QVector<GameInfo>> m_games_shared;
bool validCellSelected = false;
public:
explicit GameGridFrame(std::shared_ptr<GameInfoClass> game_info_get, QWidget* parent = nullptr);
explicit GameGridFrame(std::shared_ptr<GameInfoClass> game_info_get,
std::shared_ptr<CompatibilityInfoClass> compat_info_get,
QWidget* parent = nullptr);
void PopulateGameGrid(QVector<GameInfo> m_games, bool fromSearch);
bool IsValidCellSelected();

View file

@ -2,6 +2,7 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#include <QToolTip>
#include "common/config.h"
#include "common/logging/log.h"
#include "common/path_util.h"
#include "common/string_util.h"
@ -72,7 +73,7 @@ GameListFrame::GameListFrame(std::shared_ptr<GameInfoClass> game_info_get,
});
connect(this, &QTableWidget::customContextMenuRequested, this, [=, this](const QPoint& pos) {
m_gui_context_menus.RequestGameMenu(pos, m_game_info->m_games, this, true);
m_gui_context_menus.RequestGameMenu(pos, m_game_info->m_games, m_compat_info, this, true);
});
connect(this, &QTableWidget::cellClicked, this, [=, this](int row, int column) {
@ -80,11 +81,6 @@ GameListFrame::GameListFrame(std::shared_ptr<GameInfoClass> game_info_get,
QDesktopServices::openUrl(QUrl(m_game_info->m_games[row].compatibility.url));
}
});
// Do not show status column if it is not enabled
if (!Config::getCompatibilityEnabled()) {
this->setColumnHidden(2, true);
}
}
void GameListFrame::onCurrentCellChanged(int currentRow, int currentColumn, int previousRow,
@ -108,6 +104,8 @@ void GameListFrame::PlayBackgroundMusic(QTableWidgetItem* item) {
}
void GameListFrame::PopulateGameList() {
// Do not show status column if it is not enabled
this->setColumnHidden(2, !Config::getCompatibilityEnabled());
this->setRowCount(m_game_info->m_games.size());
ResizeIcons(icon_size);
@ -241,7 +239,7 @@ void GameListFrame::SetCompatibilityItem(int row, int column, CompatibilityEntry
break;
case CompatibilityStatus::Nothing:
color = QStringLiteral("#212121");
status_explanation = tr("Games does not initialize properly / crashes the emulator");
status_explanation = tr("Game does not initialize properly / crashes the emulator");
break;
case CompatibilityStatus::Boots:
color = QStringLiteral("#828282");

View file

@ -11,6 +11,9 @@
#include <QTreeWidgetItem>
#include "cheats_patches.h"
#include "common/config.h"
#include "common/version.h"
#include "compatibility_info.h"
#include "game_info.h"
#include "trophy_viewer.h"
@ -27,8 +30,9 @@
class GuiContextMenus : public QObject {
Q_OBJECT
public:
void RequestGameMenu(const QPoint& pos, QVector<GameInfo> m_games, QTableWidget* widget,
bool isList) {
void RequestGameMenu(const QPoint& pos, QVector<GameInfo> m_games,
std::shared_ptr<CompatibilityInfoClass> m_compat_info,
QTableWidget* widget, bool isList) {
QPoint global_pos = widget->viewport()->mapToGlobal(pos);
int itemID = 0;
if (isList) {
@ -91,6 +95,21 @@ public:
menu.addMenu(deleteMenu);
// Compatibility submenu.
QMenu* compatibilityMenu = new QMenu(tr("Compatibility..."), widget);
QAction* updateCompatibility = new QAction(tr("Update database"), widget);
QAction* viewCompatibilityReport = new QAction(tr("View report"), widget);
QAction* submitCompatibilityReport = new QAction(tr("Submit a report"), widget);
compatibilityMenu->addAction(updateCompatibility);
compatibilityMenu->addAction(viewCompatibilityReport);
compatibilityMenu->addAction(submitCompatibilityReport);
menu.addMenu(compatibilityMenu);
compatibilityMenu->setEnabled(Config::getCompatibilityEnabled());
viewCompatibilityReport->setEnabled(!m_games[itemID].compatibility.url.isEmpty());
// Show menu.
auto selected = menu.exec(global_pos);
if (!selected) {
@ -360,6 +379,31 @@ public:
}
}
}
if (selected == updateCompatibility) {
m_compat_info->UpdateCompatibilityDatabase(widget, true);
}
if (selected == viewCompatibilityReport) {
if (!m_games[itemID].compatibility.url.isEmpty())
QDesktopServices::openUrl(QUrl(m_games[itemID].compatibility.url));
}
if (selected == submitCompatibilityReport) {
QUrl url = QUrl("https://github.com/shadps4-emu/shadps4-game-compatibility/issues/new");
QUrlQuery query;
query.addQueryItem("template", QString("game_compatibility.yml"));
query.addQueryItem(
"title", QString("%1 - %2").arg(QString::fromStdString(m_games[itemID].serial),
QString::fromStdString(m_games[itemID].name)));
query.addQueryItem("game-name", QString::fromStdString(m_games[itemID].name));
query.addQueryItem("game-code", QString::fromStdString(m_games[itemID].serial));
query.addQueryItem("game-version", QString::fromStdString(m_games[itemID].version));
query.addQueryItem("emulator-version", QString(Common::VERSION));
url.setQuery(query);
QDesktopServices::openUrl(url);
}
}
int GetRowIndex(QTreeWidget* treeWidget, QTreeWidgetItem* item) {

View file

@ -140,7 +140,7 @@ void MainWindow::CreateDockWindows() {
m_dock_widget.reset(new QDockWidget(tr("Game List"), this));
m_game_list_frame.reset(new GameListFrame(m_game_info, m_compat_info, this));
m_game_list_frame->setObjectName("gamelist");
m_game_grid_frame.reset(new GameGridFrame(m_game_info, this));
m_game_grid_frame.reset(new GameGridFrame(m_game_info, m_compat_info, this));
m_game_grid_frame->setObjectName("gamegridlist");
m_elf_viewer.reset(new ElfViewer(this));
m_elf_viewer->setObjectName("elflist");
@ -253,20 +253,26 @@ void MainWindow::CreateConnects() {
&MainWindow::StartGame);
connect(ui->configureAct, &QAction::triggered, this, [this]() {
auto settingsDialog = new SettingsDialog(m_physical_devices, this);
auto settingsDialog = new SettingsDialog(m_physical_devices, m_compat_info, this);
connect(settingsDialog, &SettingsDialog::LanguageChanged, this,
&MainWindow::OnLanguageChanged);
connect(settingsDialog, &SettingsDialog::CompatibilityChanged, this,
&MainWindow::RefreshGameTable);
settingsDialog->exec();
});
connect(ui->settingsButton, &QPushButton::clicked, this, [this]() {
auto settingsDialog = new SettingsDialog(m_physical_devices, this);
auto settingsDialog = new SettingsDialog(m_physical_devices, m_compat_info, this);
connect(settingsDialog, &SettingsDialog::LanguageChanged, this,
&MainWindow::OnLanguageChanged);
connect(settingsDialog, &SettingsDialog::CompatibilityChanged, this,
&MainWindow::RefreshGameTable);
settingsDialog->exec();
});

View file

@ -6,6 +6,8 @@
#include <QHoverEvent>
#include <common/version.h>
#include "common/config.h"
#include "qt_gui/compatibility_info.h"
#ifdef ENABLE_DISCORD_RPC
#include "common/discord_rpc_handler.h"
#endif
@ -54,7 +56,9 @@ QStringList languageNames = {"Arabic",
const QVector<int> languageIndexes = {21, 23, 14, 6, 18, 1, 12, 22, 2, 4, 25, 24, 29, 5, 0, 9,
15, 16, 17, 7, 26, 8, 11, 20, 3, 13, 27, 10, 19, 30, 28};
SettingsDialog::SettingsDialog(std::span<const QString> physical_devices, QWidget* parent)
SettingsDialog::SettingsDialog(std::span<const QString> physical_devices,
std::shared_ptr<CompatibilityInfoClass> m_compat_info,
QWidget* parent)
: QDialog(parent), ui(new Ui::SettingsDialog) {
ui->setupUi(this);
ui->tabWidgetSettings->setUsesScrollButtons(false);
@ -140,6 +144,16 @@ SettingsDialog::SettingsDialog(std::span<const QString> physical_devices, QWidge
ui->updaterGroupBox->setVisible(false);
ui->GUIgroupBox->setMaximumSize(265, 16777215);
#endif
connect(ui->updateCompatibilityButton, &QPushButton::clicked, this,
[this, parent, m_compat_info]() {
m_compat_info->UpdateCompatibilityDatabase(this, true);
emit CompatibilityChanged();
});
connect(ui->enableCompatibilityCheckBox, &QCheckBox::stateChanged, this, [this](int state) {
Config::setCompatibilityEnabled(state);
emit CompatibilityChanged();
});
}
// Input TAB
@ -195,6 +209,9 @@ SettingsDialog::SettingsDialog(std::span<const QString> physical_devices, QWidge
#endif
ui->GUIgroupBox->installEventFilter(this);
ui->disableTrophycheckBox->installEventFilter(this);
ui->enableCompatibilityCheckBox->installEventFilter(this);
ui->checkCompatibilityOnStartupCheckBox->installEventFilter(this);
ui->updateCompatibilityButton->installEventFilter(this);
// Input
ui->hideCursorGroupBox->installEventFilter(this);
@ -285,6 +302,10 @@ void SettingsDialog::LoadValuesFromConfig() {
ui->vkSyncValidationCheckBox->setChecked(
toml::find_or<bool>(data, "Vulkan", "validation_sync", false));
ui->rdocCheckBox->setChecked(toml::find_or<bool>(data, "Vulkan", "rdocEnable", false));
ui->enableCompatibilityCheckBox->setChecked(
toml::find_or<bool>(data, "General", "compatibilityEnabled", false));
ui->checkCompatibilityOnStartupCheckBox->setChecked(
toml::find_or<bool>(data, "General", "checkCompatibilityOnStartup", false));
#ifdef ENABLE_UPDATER
ui->updateCheckBox->setChecked(toml::find_or<bool>(data, "General", "autoUpdate", false));
@ -402,6 +423,12 @@ void SettingsDialog::updateNoteTextEdit(const QString& elementName) {
text = tr("GUIgroupBox");
} else if (elementName == "disableTrophycheckBox") {
text = tr("disableTrophycheckBox");
} else if (elementName == "enableCompatibilityCheckBox") {
text = tr("enableCompatibilityCheckBox");
} else if (elementName == "checkCompatibilityOnStartupCheckBox") {
text = tr("checkCompatibilityOnStartupCheckBox");
} else if (elementName == "updateCompatibilityButton") {
text = tr("updateCompatibilityButton");
}
// Input
@ -515,6 +542,8 @@ void SettingsDialog::UpdateSettings() {
Config::setRdocEnabled(ui->rdocCheckBox->isChecked());
Config::setAutoUpdate(ui->updateCheckBox->isChecked());
Config::setUpdateChannel(ui->updateComboBox->currentText().toStdString());
Config::setCompatibilityEnabled(ui->enableCompatibilityCheckBox->isChecked());
Config::setCheckCompatibilityOnStartup(ui->checkCompatibilityOnStartupCheckBox->isChecked());
#ifdef ENABLE_DISCORD_RPC
auto* rpc = Common::Singleton<DiscordRPCHandler::RPC>::Instance();

View file

@ -3,6 +3,7 @@
#pragma once
#include <memory>
#include <span>
#include <QDialog>
#include <QGroupBox>
@ -10,6 +11,7 @@
#include "common/config.h"
#include "common/path_util.h"
#include "qt_gui/compatibility_info.h"
namespace Ui {
class SettingsDialog;
@ -18,7 +20,9 @@ class SettingsDialog;
class SettingsDialog : public QDialog {
Q_OBJECT
public:
explicit SettingsDialog(std::span<const QString> physical_devices, QWidget* parent = nullptr);
explicit SettingsDialog(std::span<const QString> physical_devices,
std::shared_ptr<CompatibilityInfoClass> m_compat_info,
QWidget* parent = nullptr);
~SettingsDialog();
bool eventFilter(QObject* obj, QEvent* event) override;
@ -28,6 +32,7 @@ public:
signals:
void LanguageChanged(const std::string& locale);
void CompatibilityChanged();
private:
void LoadValuesFromConfig();

View file

@ -306,7 +306,7 @@
</property>
<property name="minimumSize">
<size>
<width>275</width>
<width>265</width>
<height>0</height>
</size>
</property>
@ -574,25 +574,88 @@
</layout>
</item>
<item>
<layout class="QVBoxLayout" name="EmptyTabLayoutRight">
<item>
<spacer name="emptyHorizontalSpacer">
<property name="orientation">
<enum>Qt::Orientation::Horizontal</enum>
<layout class="QVBoxLayout" name="CompatTabLayoutRight" stretch="0">
<item alignment="Qt::AlignmentFlag::AlignTop">
<widget class="QGroupBox" name="CompatgroupBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="sizeHint" stdset="0">
<property name="minimumSize">
<size>
<width>40</width>
<height>20</height>
<width>0</width>
<height>0</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout>
<property name="title">
<string>Game Compatibility</string>
</property>
<layout class="QVBoxLayout" name="CompatLayout">
<property name="topMargin">
<number>1</number>
</property>
<property name="bottomMargin">
<number>11</number>
</property>
<item>
<widget class="QCheckBox" name="enableCompatibilityCheckBox">
<property name="text">
<string>Display Compatibility Data</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkCompatibilityOnStartupCheckBox">
<property name="text">
<string>Update Compatibility Database On Startup</string>
</property>
</widget>
</item>
<item>
<layout class="QVBoxLayout" name="UpdateCompatLayout">
<property name="topMargin">
<number>1</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QPushButton" name="updateCompatibilityButton">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>197</width>
<height>28</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>Update Compatibility Database</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
</layout>
</item>
</layout>
</item>
</layout>
</widget>
<widget class="QWidget" name="inputTab">
<attribute name="title">

View file

@ -677,6 +677,21 @@
<source>Play title music</source>
<translation>Play title music</translation>
</message>
<message>
<location filename="../settings_dialog.ui"/>
<source>Update Compatibility Database On Startup</source>
<translation>Update Compatibility Database On Startup</translation>
</message>
<message>
<location filename="../settings_dialog.ui"/>
<source>Display Compatibility Data</source>
<translation>Display Compatibility Data</translation>
</message>
<message>
<location filename="../settings_dialog.ui"/>
<source>Update Compatibility Database</source>
<translation>Update Compatibility Database</translation>
</message>
<message>
<location filename="../settings_dialog.ui" line="394"/>
<source>Volume</source>
@ -1221,6 +1236,21 @@
<source>backButtonBehaviorGroupBox</source>
<translation>Back Button Behavior:\nSets the controller's back button to emulate tapping the specified position on the PS4 touchpad.</translation>
</message>
<message>
<location filename="../settings_dialog.cpp"/>
<source>enableCompatibilityCheckBox</source>
<translation>Display Compatibility Data:\nDisplays game compatibility information in table view. Enable "Update Compatibility On Startup" to get up-to-date information.</translation>
</message>
<message>
<location filename="../settings_dialog.cpp"/>
<source>checkCompatibilityOnStartupCheckBox</source>
<translation>Update Compatibility On Startup:\nAutomatically update the compatibility database when shadPS4 starts.</translation>
</message>
<message>
<location filename="../settings_dialog.cpp"/>
<source>updateCompatibilityButton</source>
<translation>Update Compatibility Database:\nImmediately update the compatibility database.</translation>
</message>
<message>
<location filename="../settings_dialog.cpp" line="70"/>
<source>Never</source>
@ -1334,6 +1364,11 @@
<source>Serial</source>
<translation>Serial</translation>
</message>
<message>
<location filename="../game_list_frame.cpp"/>
<source>Compatibility</source>
<translation>Compatibility</translation>
</message>
<message>
<location filename="../game_list_frame.cpp" line="34"/>
<source>Region</source>
@ -1369,6 +1404,36 @@
<source>Never Played</source>
<translation>Never Played</translation>
</message>
<message>
<location filename="../game_list_frame.cpp"/>
<source>Compatibility is untested</source>
<translation>Compatibility is untested</translation>
</message>
<message>
<location filename="../game_list_frame.cpp"/>
<source>Game does not initialize properly / crashes the emulator</source>
<translation>Game does not initialize properly / crashes the emulator</translation>
</message>
<message>
<location filename="../game_list_frame.cpp"/>
<source>Game boots, but only displays a blank screen</source>
<translation>Game boots, but only displays a blank screen</translation>
</message>
<message>
<location filename="../game_list_frame.cpp"/>
<source>Game displays an image but does not go past the menu</source>
<translation>Game displays an image but does not go past the menu</translation>
</message>
<message>
<location filename="../game_list_frame.cpp"/>
<source>Game has game-breaking glitches or unplayable performance</source>
<translation>Game has game-breaking glitches or unplayable performance</translation>
</message>
<message>
<location filename="../game_list_frame.cpp"/>
<source>Game can be completed with playable performance and no major glitches</source>
<translation>Game can be completed with playable performance and no major glitches</translation>
</message>
</context>
<context>
<name>CheckUpdate</name>