mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-07-10 00:41:26 +12:00
patch_manager: add option to only show owned games
and remove the app version level from the gui
This commit is contained in:
parent
12dded403f
commit
695cfead16
6 changed files with 101 additions and 63 deletions
|
@ -2230,3 +2230,8 @@ void game_list_frame::SetShowCompatibilityInGrid(bool show)
|
||||||
RepaintIcons();
|
RepaintIcons();
|
||||||
m_gui_settings->SetValue(gui::gl_draw_compat, show);
|
m_gui_settings->SetValue(gui::gl_draw_compat, show);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QList<game_info> game_list_frame::GetGameInfo() const
|
||||||
|
{
|
||||||
|
return m_game_data;
|
||||||
|
}
|
||||||
|
|
|
@ -69,6 +69,8 @@ public:
|
||||||
|
|
||||||
void SetShowHidden(bool show);
|
void SetShowHidden(bool show);
|
||||||
|
|
||||||
|
QList<game_info> GetGameInfo() const;
|
||||||
|
|
||||||
public Q_SLOTS:
|
public Q_SLOTS:
|
||||||
void BatchCreatePPUCaches();
|
void BatchCreatePPUCaches();
|
||||||
void BatchRemovePPUCaches();
|
void BatchRemovePPUCaches();
|
||||||
|
|
|
@ -1535,7 +1535,18 @@ void main_window::CreateConnects()
|
||||||
|
|
||||||
connect(ui->actionManage_Game_Patches, &QAction::triggered, [this]
|
connect(ui->actionManage_Game_Patches, &QAction::triggered, [this]
|
||||||
{
|
{
|
||||||
patch_manager_dialog patch_manager(m_gui_settings, this);
|
std::unordered_map<std::string, std::set<std::string>> games;
|
||||||
|
if (m_game_list_frame)
|
||||||
|
{
|
||||||
|
for (const auto game : m_game_list_frame->GetGameInfo())
|
||||||
|
{
|
||||||
|
if (game)
|
||||||
|
{
|
||||||
|
games[game->info.serial].insert(game->info.app_ver);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
patch_manager_dialog patch_manager(m_gui_settings, games, this);
|
||||||
patch_manager.exec();
|
patch_manager.exec();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -45,13 +45,13 @@ enum node_level : int
|
||||||
{
|
{
|
||||||
title_level,
|
title_level,
|
||||||
serial_level,
|
serial_level,
|
||||||
app_version_level,
|
|
||||||
patch_level
|
patch_level
|
||||||
};
|
};
|
||||||
|
|
||||||
patch_manager_dialog::patch_manager_dialog(std::shared_ptr<gui_settings> gui_settings, QWidget* parent)
|
patch_manager_dialog::patch_manager_dialog(std::shared_ptr<gui_settings> gui_settings, std::unordered_map<std::string, std::set<std::string>> games, QWidget* parent)
|
||||||
: QDialog(parent)
|
: QDialog(parent)
|
||||||
, m_gui_settings(gui_settings)
|
, m_gui_settings(gui_settings)
|
||||||
|
, m_owned_games(std::move(games))
|
||||||
, ui(new Ui::patch_manager_dialog)
|
, ui(new Ui::patch_manager_dialog)
|
||||||
{
|
{
|
||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
|
@ -65,9 +65,8 @@ patch_manager_dialog::patch_manager_dialog(std::shared_ptr<gui_settings> gui_set
|
||||||
connect(ui->patch_tree, &QTreeWidget::currentItemChanged, this, &patch_manager_dialog::on_item_selected);
|
connect(ui->patch_tree, &QTreeWidget::currentItemChanged, this, &patch_manager_dialog::on_item_selected);
|
||||||
connect(ui->patch_tree, &QTreeWidget::itemChanged, this, &patch_manager_dialog::on_item_changed);
|
connect(ui->patch_tree, &QTreeWidget::itemChanged, this, &patch_manager_dialog::on_item_changed);
|
||||||
connect(ui->patch_tree, &QTreeWidget::customContextMenuRequested, this, &patch_manager_dialog::on_custom_context_menu_requested);
|
connect(ui->patch_tree, &QTreeWidget::customContextMenuRequested, this, &patch_manager_dialog::on_custom_context_menu_requested);
|
||||||
connect(ui->pb_expand_all, &QAbstractButton::clicked, ui->patch_tree, &QTreeWidget::expandAll);
|
|
||||||
connect(ui->pb_collapse_all, &QAbstractButton::clicked, ui->patch_tree, &QTreeWidget::collapseAll);
|
|
||||||
connect(ui->cb_enable_legacy_patches, &QCheckBox::stateChanged, this, &patch_manager_dialog::on_legacy_patches_enabled);
|
connect(ui->cb_enable_legacy_patches, &QCheckBox::stateChanged, this, &patch_manager_dialog::on_legacy_patches_enabled);
|
||||||
|
connect(ui->cb_owned_games_only, &QCheckBox::stateChanged, this, &patch_manager_dialog::on_show_owned_games_only);
|
||||||
connect(ui->buttonBox, &QDialogButtonBox::rejected, this, &QWidget::close);
|
connect(ui->buttonBox, &QDialogButtonBox::rejected, this, &QWidget::close);
|
||||||
connect(ui->buttonBox, &QDialogButtonBox::clicked, [this](QAbstractButton* button)
|
connect(ui->buttonBox, &QDialogButtonBox::clicked, [this](QAbstractButton* button)
|
||||||
{
|
{
|
||||||
|
@ -103,6 +102,7 @@ void patch_manager_dialog::refresh(bool restore_layout)
|
||||||
{
|
{
|
||||||
load_patches();
|
load_patches();
|
||||||
populate_tree();
|
populate_tree();
|
||||||
|
filter_patches(ui->patch_filter->text());
|
||||||
|
|
||||||
if (restore_layout)
|
if (restore_layout)
|
||||||
{
|
{
|
||||||
|
@ -212,16 +212,22 @@ void patch_manager_dialog::populate_tree()
|
||||||
|
|
||||||
const QString q_serial = QString::fromStdString(serial);
|
const QString q_serial = QString::fromStdString(serial);
|
||||||
|
|
||||||
|
for (const auto& [app_version, enabled] : app_versions)
|
||||||
|
{
|
||||||
|
const QString q_app_version = QString::fromStdString(app_version);
|
||||||
|
const QString q_serial_and_version = q_serial + QStringLiteral(" v.") + q_app_version;
|
||||||
|
|
||||||
// Find out if there is a node item for this serial
|
// Find out if there is a node item for this serial
|
||||||
QTreeWidgetItem* serial_level_item = gui::utils::find_child(title_level_item, q_serial);
|
QTreeWidgetItem* serial_level_item = gui::utils::find_child(title_level_item, q_serial_and_version);
|
||||||
|
|
||||||
// Add a node item for this serial if it doesn't exist yet
|
// Add a node item for this serial if it doesn't exist yet
|
||||||
if (!serial_level_item)
|
if (!serial_level_item)
|
||||||
{
|
{
|
||||||
serial_level_item = new QTreeWidgetItem();
|
serial_level_item = new QTreeWidgetItem();
|
||||||
serial_level_item->setText(0, q_serial);
|
serial_level_item->setText(0, q_serial_and_version);
|
||||||
serial_level_item->setData(0, title_role, q_title);
|
serial_level_item->setData(0, title_role, q_title);
|
||||||
serial_level_item->setData(0, serial_role, q_serial);
|
serial_level_item->setData(0, serial_role, q_serial);
|
||||||
|
serial_level_item->setData(0, app_version_role, q_app_version);
|
||||||
serial_level_item->setData(0, node_level_role, node_level::serial_level);
|
serial_level_item->setData(0, node_level_role, node_level::serial_level);
|
||||||
serial_level_item->setData(0, persistance_role, true);
|
serial_level_item->setData(0, persistance_role, true);
|
||||||
|
|
||||||
|
@ -229,28 +235,6 @@ void patch_manager_dialog::populate_tree()
|
||||||
}
|
}
|
||||||
assert(serial_level_item);
|
assert(serial_level_item);
|
||||||
|
|
||||||
for (const auto& [app_version, enabled] : app_versions)
|
|
||||||
{
|
|
||||||
const QString q_app_version = QString::fromStdString(app_version);
|
|
||||||
|
|
||||||
// Find out if there is a node item for this app version
|
|
||||||
QTreeWidgetItem* app_version_level_item = gui::utils::find_child(serial_level_item, q_app_version);
|
|
||||||
|
|
||||||
// Add a node item for this app version if it doesn't exist yet
|
|
||||||
if (!app_version_level_item)
|
|
||||||
{
|
|
||||||
app_version_level_item = new QTreeWidgetItem();
|
|
||||||
app_version_level_item->setText(0, q_app_version);
|
|
||||||
app_version_level_item->setData(0, title_role, q_title);
|
|
||||||
app_version_level_item->setData(0, serial_role, q_serial);
|
|
||||||
app_version_level_item->setData(0, app_version_role, q_app_version);
|
|
||||||
app_version_level_item->setData(0, node_level_role, node_level::app_version_level);
|
|
||||||
app_version_level_item->setData(0, persistance_role, true);
|
|
||||||
|
|
||||||
serial_level_item->addChild(app_version_level_item);
|
|
||||||
}
|
|
||||||
assert(app_version_level_item);
|
|
||||||
|
|
||||||
// Add a checkable leaf item for this patch
|
// Add a checkable leaf item for this patch
|
||||||
const QString q_description = QString::fromStdString(description);
|
const QString q_description = QString::fromStdString(description);
|
||||||
QString visible_description = q_description;
|
QString visible_description = q_description;
|
||||||
|
@ -258,7 +242,7 @@ void patch_manager_dialog::populate_tree()
|
||||||
const auto match_criteria = QList<QPair<int, QVariant>>() << QPair(description_role, q_description) << QPair(persistance_role, true);
|
const auto match_criteria = QList<QPair<int, QVariant>>() << QPair(description_role, q_description) << QPair(persistance_role, true);
|
||||||
|
|
||||||
// Add counter to leafs if the name already exists due to different hashes of the same game (PPU, SPU, PRX, OVL)
|
// Add counter to leafs if the name already exists due to different hashes of the same game (PPU, SPU, PRX, OVL)
|
||||||
if (const auto matches = gui::utils::find_children_by_data(app_version_level_item, match_criteria, false); matches.count() > 0)
|
if (const auto matches = gui::utils::find_children_by_data(serial_level_item, match_criteria, false); matches.count() > 0)
|
||||||
{
|
{
|
||||||
if (auto only_match = matches.count() == 1 ? matches[0] : nullptr)
|
if (auto only_match = matches.count() == 1 ? matches[0] : nullptr)
|
||||||
{
|
{
|
||||||
|
@ -279,7 +263,7 @@ void patch_manager_dialog::populate_tree()
|
||||||
patch_level_item->setData(0, node_level_role, node_level::patch_level);
|
patch_level_item->setData(0, node_level_role, node_level::patch_level);
|
||||||
patch_level_item->setData(0, persistance_role, true);
|
patch_level_item->setData(0, persistance_role, true);
|
||||||
|
|
||||||
app_version_level_item->addChild(patch_level_item);
|
serial_level_item->addChild(patch_level_item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -315,13 +299,31 @@ void patch_manager_dialog::filter_patches(const QString& term)
|
||||||
// Recursive function to show all matching items and their children.
|
// Recursive function to show all matching items and their children.
|
||||||
// @return number of visible children of item, including item
|
// @return number of visible children of item, including item
|
||||||
std::function<int(QTreeWidgetItem*, bool)> show_matches;
|
std::function<int(QTreeWidgetItem*, bool)> show_matches;
|
||||||
show_matches = [&show_matches, search_text = term.toLower()](QTreeWidgetItem* item, bool parent_visible) -> int
|
show_matches = [this, &show_matches, search_text = term.toLower()](QTreeWidgetItem* item, bool parent_visible) -> int
|
||||||
{
|
{
|
||||||
if (!item) return 0;
|
if (!item) return 0;
|
||||||
|
|
||||||
|
const node_level level = static_cast<node_level>(item->data(0, node_level_role).toInt());
|
||||||
|
|
||||||
|
// Hide nodes that aren't in the game list
|
||||||
|
if (m_show_owned_games_only)
|
||||||
|
{
|
||||||
|
if (level == node_level::serial_level)
|
||||||
|
{
|
||||||
|
const std::string serial = item->data(0, serial_role).toString().toStdString();
|
||||||
|
const std::string app_version = item->data(0, app_version_role).toString().toStdString();
|
||||||
|
|
||||||
|
if (m_owned_games.find(serial) == m_owned_games.end() || !m_owned_games.at(serial).contains(app_version))
|
||||||
|
{
|
||||||
|
item->setHidden(true);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Only try to match if the parent is not visible
|
// Only try to match if the parent is not visible
|
||||||
parent_visible = parent_visible || item->text(0).toLower().contains(search_text);
|
parent_visible = parent_visible || item->text(0).toLower().contains(search_text);
|
||||||
int visible_items = parent_visible ? 1 : 0;
|
int visible_items = 0;
|
||||||
|
|
||||||
// Get the number of visible children recursively
|
// Get the number of visible children recursively
|
||||||
for (int i = 0; i < item->childCount(); i++)
|
for (int i = 0; i < item->childCount(); i++)
|
||||||
|
@ -329,6 +331,15 @@ void patch_manager_dialog::filter_patches(const QString& term)
|
||||||
visible_items += show_matches(item->child(i), parent_visible);
|
visible_items += show_matches(item->child(i), parent_visible);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (parent_visible)
|
||||||
|
{
|
||||||
|
// Only show the title node if it has visible children when filtering for game list entries
|
||||||
|
if (!m_show_owned_games_only || level != node_level::title_level || visible_items > 0)
|
||||||
|
{
|
||||||
|
visible_items++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Only show item if itself or any of its children is visible
|
// Only show item if itself or any of its children is visible
|
||||||
item->setHidden(visible_items <= 0);
|
item->setHidden(visible_items <= 0);
|
||||||
return visible_items;
|
return visible_items;
|
||||||
|
@ -391,14 +402,10 @@ void patch_manager_dialog::on_item_selected(QTreeWidgetItem *current, QTreeWidge
|
||||||
}
|
}
|
||||||
[[fallthrough]];
|
[[fallthrough]];
|
||||||
}
|
}
|
||||||
case node_level::app_version_level:
|
|
||||||
{
|
|
||||||
info.app_version = current->data(0, app_version_role).toString();
|
|
||||||
[[fallthrough]];
|
|
||||||
}
|
|
||||||
case node_level::serial_level:
|
case node_level::serial_level:
|
||||||
{
|
{
|
||||||
info.serial = current->data(0, serial_role).toString();
|
info.serial = current->data(0, serial_role).toString();
|
||||||
|
info.app_version = current->data(0, app_version_role).toString();
|
||||||
[[fallthrough]];
|
[[fallthrough]];
|
||||||
}
|
}
|
||||||
case node_level::title_level:
|
case node_level::title_level:
|
||||||
|
@ -473,9 +480,19 @@ void patch_manager_dialog::on_custom_context_menu_requested(const QPoint &pos)
|
||||||
|
|
||||||
QMenu* menu = new QMenu(this);
|
QMenu* menu = new QMenu(this);
|
||||||
|
|
||||||
|
QAction* collapse_all = new QAction(tr("Collapse All"));
|
||||||
|
menu->addAction(collapse_all);
|
||||||
|
connect(collapse_all, &QAction::triggered, ui->patch_tree, &QTreeWidget::collapseAll);
|
||||||
|
|
||||||
|
QAction* expand_all = new QAction(tr("Expand All"));
|
||||||
|
menu->addAction(expand_all);
|
||||||
|
connect(expand_all, &QAction::triggered, ui->patch_tree, &QTreeWidget::expandAll);
|
||||||
|
|
||||||
|
menu->addSeparator();
|
||||||
|
|
||||||
if (item->childCount() > 0)
|
if (item->childCount() > 0)
|
||||||
{
|
{
|
||||||
QAction* collapse_children = new QAction("Collapse Children");
|
QAction* collapse_children = new QAction(tr("Collapse Children"));
|
||||||
menu->addAction(collapse_children);
|
menu->addAction(collapse_children);
|
||||||
connect(collapse_children, &QAction::triggered, this, [&item](bool)
|
connect(collapse_children, &QAction::triggered, this, [&item](bool)
|
||||||
{
|
{
|
||||||
|
@ -485,7 +502,7 @@ void patch_manager_dialog::on_custom_context_menu_requested(const QPoint &pos)
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
QAction* expand_children = new QAction("Expand Children");
|
QAction* expand_children = new QAction(tr("Expand Children"));
|
||||||
menu->addAction(expand_children);
|
menu->addAction(expand_children);
|
||||||
connect(expand_children, &QAction::triggered, this, [&item](bool)
|
connect(expand_children, &QAction::triggered, this, [&item](bool)
|
||||||
{
|
{
|
||||||
|
@ -509,7 +526,7 @@ void patch_manager_dialog::on_custom_context_menu_requested(const QPoint &pos)
|
||||||
{
|
{
|
||||||
const auto info = container.patch_info_map.at(description);
|
const auto info = container.patch_info_map.at(description);
|
||||||
|
|
||||||
QAction* open_filepath = new QAction("Show Patch File");
|
QAction* open_filepath = new QAction(tr("Show Patch File"));
|
||||||
menu->addAction(open_filepath);
|
menu->addAction(open_filepath);
|
||||||
connect(open_filepath, &QAction::triggered, this, [info](bool)
|
connect(open_filepath, &QAction::triggered, this, [info](bool)
|
||||||
{
|
{
|
||||||
|
@ -520,7 +537,7 @@ void patch_manager_dialog::on_custom_context_menu_requested(const QPoint &pos)
|
||||||
{
|
{
|
||||||
menu->addSeparator();
|
menu->addSeparator();
|
||||||
|
|
||||||
QAction* remove_patch = new QAction("Remove Patch");
|
QAction* remove_patch = new QAction(tr("Remove Patch"));
|
||||||
menu->addAction(remove_patch);
|
menu->addAction(remove_patch);
|
||||||
connect(remove_patch, &QAction::triggered, this, [info, this](bool)
|
connect(remove_patch, &QAction::triggered, this, [info, this](bool)
|
||||||
{
|
{
|
||||||
|
@ -661,6 +678,12 @@ void patch_manager_dialog::on_legacy_patches_enabled(int state)
|
||||||
m_legacy_patches_enabled = state == Qt::CheckState::Checked;
|
m_legacy_patches_enabled = state == Qt::CheckState::Checked;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void patch_manager_dialog::on_show_owned_games_only(int state)
|
||||||
|
{
|
||||||
|
m_show_owned_games_only = state == Qt::CheckState::Checked;
|
||||||
|
filter_patches(ui->patch_filter->text());
|
||||||
|
}
|
||||||
|
|
||||||
void patch_manager_dialog::dragEnterEvent(QDragEnterEvent* event)
|
void patch_manager_dialog::dragEnterEvent(QDragEnterEvent* event)
|
||||||
{
|
{
|
||||||
if (is_valid_file(*event->mimeData()))
|
if (is_valid_file(*event->mimeData()))
|
||||||
|
|
|
@ -31,7 +31,7 @@ class patch_manager_dialog : public QDialog
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit patch_manager_dialog(std::shared_ptr<gui_settings> gui_settings, QWidget* parent = nullptr);
|
explicit patch_manager_dialog(std::shared_ptr<gui_settings> gui_settings, std::unordered_map<std::string, std::set<std::string>> games, QWidget* parent = nullptr);
|
||||||
~patch_manager_dialog();
|
~patch_manager_dialog();
|
||||||
|
|
||||||
int exec() override;
|
int exec() override;
|
||||||
|
@ -42,6 +42,7 @@ private Q_SLOTS:
|
||||||
void on_item_changed(QTreeWidgetItem *item, int column);
|
void on_item_changed(QTreeWidgetItem *item, int column);
|
||||||
void on_custom_context_menu_requested(const QPoint& pos);
|
void on_custom_context_menu_requested(const QPoint& pos);
|
||||||
void on_legacy_patches_enabled(int state);
|
void on_legacy_patches_enabled(int state);
|
||||||
|
void on_show_owned_games_only(int state);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void refresh(bool restore_layout = false);
|
void refresh(bool restore_layout = false);
|
||||||
|
@ -53,6 +54,9 @@ private:
|
||||||
|
|
||||||
std::shared_ptr<gui_settings> m_gui_settings;
|
std::shared_ptr<gui_settings> m_gui_settings;
|
||||||
|
|
||||||
|
std::unordered_map<std::string, std::set<std::string>> m_owned_games;
|
||||||
|
bool m_show_owned_games_only = false;
|
||||||
|
|
||||||
patch_engine::patch_map m_map;
|
patch_engine::patch_map m_map;
|
||||||
bool m_legacy_patches_enabled = false;
|
bool m_legacy_patches_enabled = false;
|
||||||
|
|
||||||
|
|
|
@ -39,6 +39,13 @@
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QCheckBox" name="cb_owned_games_only">
|
||||||
|
<property name="text">
|
||||||
|
<string>Only show owned games</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QCheckBox" name="cb_enable_legacy_patches">
|
<widget class="QCheckBox" name="cb_enable_legacy_patches">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
|
@ -46,20 +53,6 @@
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
|
||||||
<widget class="QPushButton" name="pb_collapse_all">
|
|
||||||
<property name="text">
|
|
||||||
<string>Collapse All</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QPushButton" name="pb_expand_all">
|
|
||||||
<property name="text">
|
|
||||||
<string>Expand All</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue