patch_manager: add option to only show owned games

and remove the app version level from the gui
This commit is contained in:
Megamouse 2020-06-26 18:31:42 +02:00
parent 12dded403f
commit 695cfead16
6 changed files with 101 additions and 63 deletions

View File

@ -2230,3 +2230,8 @@ void game_list_frame::SetShowCompatibilityInGrid(bool show)
RepaintIcons();
m_gui_settings->SetValue(gui::gl_draw_compat, show);
}
QList<game_info> game_list_frame::GetGameInfo() const
{
return m_game_data;
}

View File

@ -69,6 +69,8 @@ public:
void SetShowHidden(bool show);
QList<game_info> GetGameInfo() const;
public Q_SLOTS:
void BatchCreatePPUCaches();
void BatchRemovePPUCaches();

View File

@ -1535,7 +1535,18 @@ void main_window::CreateConnects()
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();
});

View File

@ -45,13 +45,13 @@ enum node_level : int
{
title_level,
serial_level,
app_version_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)
, m_gui_settings(gui_settings)
, m_owned_games(std::move(games))
, ui(new Ui::patch_manager_dialog)
{
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::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->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_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::clicked, [this](QAbstractButton* button)
{
@ -103,6 +102,7 @@ void patch_manager_dialog::refresh(bool restore_layout)
{
load_patches();
populate_tree();
filter_patches(ui->patch_filter->text());
if (restore_layout)
{
@ -212,16 +212,22 @@ void patch_manager_dialog::populate_tree()
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
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
if (!serial_level_item)
{
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, 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, persistance_role, true);
@ -229,28 +235,6 @@ void patch_manager_dialog::populate_tree()
}
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
const QString q_description = QString::fromStdString(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);
// 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)
{
@ -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, 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.
// @return number of visible children of item, including item
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;
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
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
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);
}
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
item->setHidden(visible_items <= 0);
return visible_items;
@ -391,14 +402,10 @@ void patch_manager_dialog::on_item_selected(QTreeWidgetItem *current, QTreeWidge
}
[[fallthrough]];
}
case node_level::app_version_level:
{
info.app_version = current->data(0, app_version_role).toString();
[[fallthrough]];
}
case node_level::serial_level:
{
info.serial = current->data(0, serial_role).toString();
info.app_version = current->data(0, app_version_role).toString();
[[fallthrough]];
}
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);
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)
{
QAction* collapse_children = new QAction("Collapse Children");
QAction* collapse_children = new QAction(tr("Collapse Children"));
menu->addAction(collapse_children);
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);
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);
QAction* open_filepath = new QAction("Show Patch File");
QAction* open_filepath = new QAction(tr("Show Patch File"));
menu->addAction(open_filepath);
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();
QAction* remove_patch = new QAction("Remove Patch");
QAction* remove_patch = new QAction(tr("Remove Patch"));
menu->addAction(remove_patch);
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;
}
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)
{
if (is_valid_file(*event->mimeData()))

View File

@ -31,7 +31,7 @@ class patch_manager_dialog : public QDialog
};
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();
int exec() override;
@ -42,6 +42,7 @@ private Q_SLOTS:
void on_item_changed(QTreeWidgetItem *item, int column);
void on_custom_context_menu_requested(const QPoint& pos);
void on_legacy_patches_enabled(int state);
void on_show_owned_games_only(int state);
private:
void refresh(bool restore_layout = false);
@ -53,6 +54,9 @@ private:
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;
bool m_legacy_patches_enabled = false;

View File

@ -39,6 +39,13 @@
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="cb_owned_games_only">
<property name="text">
<string>Only show owned games</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="cb_enable_legacy_patches">
<property name="text">
@ -46,20 +53,6 @@
</property>
</widget>
</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>
</item>
<item>