summaryrefslogtreecommitdiff
path: root/Source/Core
diff options
context:
space:
mode:
authorAdmiral H. Curtiss <pikachu025@gmail.com>2024-06-17 22:36:04 +0200
committerGitHub <noreply@github.com>2024-06-17 22:36:04 +0200
commit69fc754c656a35a1359070c19301dab10819d03c (patch)
tree459cbfe1f458b7e54356306f644c493b6d95f211 /Source/Core
parent0c2b8fd58787b1aa9e5ee250f885c2691aef492a (diff)
parenteb26937a937c923c06733e90d822a53a354c58c9 (diff)
Merge pull request #12799 from mitaclaw/branch-watch-tool-fixes-3
Branch Watch Tool: Add Set Breakpoints Submenu
Diffstat (limited to 'Source/Core')
-rw-r--r--Source/Core/DolphinQt/Debugger/BranchWatchDialog.cpp339
-rw-r--r--Source/Core/DolphinQt/Debugger/BranchWatchDialog.h31
-rw-r--r--Source/Core/DolphinQt/Debugger/BranchWatchTableModel.cpp12
-rw-r--r--Source/Core/DolphinQt/Debugger/BranchWatchTableModel.h1
4 files changed, 256 insertions, 127 deletions
diff --git a/Source/Core/DolphinQt/Debugger/BranchWatchDialog.cpp b/Source/Core/DolphinQt/Debugger/BranchWatchDialog.cpp
index e6c3e7341e..f16afbf51f 100644
--- a/Source/Core/DolphinQt/Debugger/BranchWatchDialog.cpp
+++ b/Source/Core/DolphinQt/Debugger/BranchWatchDialog.cpp
@@ -5,6 +5,7 @@
#include <algorithm>
#include <optional>
+#include <ranges>
#include <utility>
#include <QApplication>
@@ -46,6 +47,7 @@
#include "DolphinQt/QtUtils/DolphinFileDialog.h"
#include "DolphinQt/QtUtils/ModalMessageBox.h"
#include "DolphinQt/QtUtils/SetWindowDecorations.h"
+#include "DolphinQt/Resources.h"
#include "DolphinQt/Settings.h"
class BranchWatchProxyModel final : public QSortFilterProxyModel
@@ -99,7 +101,6 @@ public:
this->*member = std::nullopt;
invalidateRowsFilter();
}
- void OnDelete(QModelIndexList index_list);
bool IsBranchTypeAllowed(UGeckoInstruction inst) const;
void SetInspected(const QModelIndex& index);
@@ -155,13 +156,6 @@ bool BranchWatchProxyModel::filterAcceptsRow(int source_row, const QModelIndex&)
return true;
}
-void BranchWatchProxyModel::OnDelete(QModelIndexList index_list)
-{
- std::transform(index_list.begin(), index_list.end(), index_list.begin(),
- [this](const QModelIndex& index) { return mapToSource(index); });
- sourceModel()->OnDelete(std::move(index_list));
-}
-
static constexpr bool BranchSavesLR(UGeckoInstruction inst)
{
DEBUG_ASSERT(inst.OPCD == 18 || inst.OPCD == 16 ||
@@ -497,9 +491,13 @@ BranchWatchDialog::BranchWatchDialog(Core::System& system, Core::BranchWatch& br
return group_box;
}());
+ UpdateIcons();
+
connect(m_timer = new QTimer, &QTimer::timeout, this, &BranchWatchDialog::OnTimeout);
connect(&Settings::Instance(), &Settings::EmulationStateChanged, this,
&BranchWatchDialog::OnEmulationStateChanged);
+ connect(&Settings::Instance(), &Settings::ThemeChanged, this,
+ &BranchWatchDialog::OnThemeChanged);
connect(m_table_proxy, &BranchWatchProxyModel::layoutChanged, this,
&BranchWatchDialog::UpdateStatus);
@@ -701,13 +699,19 @@ void BranchWatchDialog::OnEmulationStateChanged(Core::State new_state)
Update();
}
+void BranchWatchDialog::OnThemeChanged()
+{
+ UpdateIcons();
+}
+
void BranchWatchDialog::OnHelp()
{
ModalMessageBox::information(
this, tr("Branch Watch Tool Help (1/4)"),
tr("Branch Watch is a code-searching tool that can isolate branches tracked by the emulated "
"CPU by testing candidate branches with simple criteria. If you are familiar with Cheat "
- "Engine's Ultimap, Branch Watch is similar to that.\n\n"
+ "Engine's Ultimap, Branch Watch is similar to that."
+ "\n\n"
"Press the \"Start Branch Watch\" button to activate Branch Watch. Branch Watch persists "
"across emulation sessions, and a snapshot of your progress can be saved to and loaded "
"from the User Directory to persist after Dolphin Emulator is closed. \"Save As...\" and "
@@ -730,7 +734,8 @@ void BranchWatchDialog::OnHelp()
"taken since the last time it was checked. It is also possible to reduce the candidates "
"by determining whether a branch instruction has or has not been overwritten since it was "
"first hit. Filter the candidates by branch kind, branch condition, origin or destination "
- "address, and origin or destination symbol name.\n\n"
+ "address, and origin or destination symbol name."
+ "\n\n"
"After enough passes and experimentation, you may be able to find function calls and "
"conditional code paths that are only taken when an action is performed in the emulated "
"software."));
@@ -738,17 +743,27 @@ void BranchWatchDialog::OnHelp()
this, tr("Branch Watch Tool Help (4/4)"),
tr("Rows in the table can be left-clicked on the origin, destination, and symbol columns to "
"view the associated address in Code View. Right-clicking the selected row(s) will bring "
- "up a context menu.\n\n"
+ "up a context menu."
+ "\n\n"
+ "If the origin, destination, or symbol columns are right-clicked, an action copy the "
+ "relevant address(es) to the clipboard will be available, and an action to set a "
+ "breakpoint at the relevant address(es) will be available. Note that, for the origin / "
+ "destination symbol columns, these actions will only be enabled if every row in the "
+ "selection has a symbol."
+ "\n\n"
"If the origin column of a row selection is right-clicked, an action to replace the "
- "branch instruction at the origin(s) with a NOP instruction (No Operation), and an action "
- "to copy the address(es) to the clipboard will be available.\n\n"
+ "branch instruction at the origin(s) with a NOP instruction (No Operation) will be "
+ "available."
+ "\n\n"
"If the destination column of a row selection is right-clicked, an action to replace the "
"instruction at the destination(s) with a BLR instruction (Branch to Link Register) will "
- "be available, but only if the branch instruction at every origin saves the link "
- "register, and an action to copy the address(es) to the clipboard will be available.\n\n"
+ "be available, but will only be enabled if the branch instruction at every origin updates "
+ "the link register."
+ "\n\n"
"If the origin / destination symbol column of a row selection is right-clicked, an action "
- "to replace the instruction(s) at the start of the symbol with a BLR instruction will be "
- "available, but only if every origin / destination symbol is found.\n\n"
+ "to replace the instruction at the start of the symbol(s) with a BLR instruction will be "
+ "available, but will only be enabled if every row in the selection has a symbol."
+ "\n\n"
"All context menus have the action to delete the selected row(s) from the candidates."));
}
@@ -801,68 +816,18 @@ void BranchWatchDialog::OnTableClicked(const QModelIndex& index)
void BranchWatchDialog::OnTableContextMenu(const QPoint& pos)
{
+ if (m_table_view->horizontalHeader()->hiddenSectionCount() == Column::NumberOfColumns)
+ {
+ m_mnu_column_visibility->exec(m_table_view->viewport()->mapToGlobal(pos));
+ return;
+ }
const QModelIndex index = m_table_view->indexAt(pos);
if (!index.isValid())
return;
- QModelIndexList index_list = m_table_view->selectionModel()->selectedRows(index.column());
-
- QMenu* const menu = new QMenu;
- menu->setAttribute(Qt::WA_DeleteOnClose, true);
-
- menu->addAction(tr("&Delete"), [this, index_list]() { OnTableDelete(std::move(index_list)); });
- switch (index.column())
- {
- case Column::Origin:
- {
- QAction* const action = menu->addAction(tr("Insert &NOP"));
- if (Core::GetState(m_system) != Core::State::Uninitialized)
- connect(action, &QAction::triggered,
- [this, index_list]() { OnTableSetNOP(std::move(index_list)); });
- else
- action->setEnabled(false);
- menu->addAction(tr("&Copy Address"), [this, index_list = std::move(index_list)]() {
- OnTableCopyAddress(std::move(index_list));
- });
- break;
- }
- case Column::Destination:
- {
- QAction* const action = menu->addAction(tr("Insert &BLR"));
- const bool enable_action =
- Core::GetState(m_system) != Core::State::Uninitialized &&
- std::all_of(index_list.begin(), index_list.end(), [this](const QModelIndex& idx) {
- const QModelIndex sibling = idx.siblingAtColumn(Column::Instruction);
- return BranchSavesLR(m_table_proxy->data(sibling, UserRole::ClickRole).value<u32>());
- });
- if (enable_action)
- connect(action, &QAction::triggered,
- [this, index_list]() { OnTableSetBLR(std::move(index_list)); });
- else
- action->setEnabled(false);
- menu->addAction(tr("&Copy Address"), [this, index_list = std::move(index_list)]() {
- OnTableCopyAddress(std::move(index_list));
- });
- break;
- }
- case Column::OriginSymbol:
- case Column::DestinSymbol:
- {
- QAction* const action = menu->addAction(tr("Insert &BLR at start"));
- const bool enable_action =
- Core::GetState(m_system) != Core::State::Uninitialized &&
- std::all_of(index_list.begin(), index_list.end(), [this](const QModelIndex& idx) {
- return m_table_proxy->data(idx, UserRole::ClickRole).isValid();
- });
- if (enable_action)
- connect(action, &QAction::triggered, [this, index_list = std::move(index_list)]() {
- OnTableSetBLR(std::move(index_list));
- });
- else
- action->setEnabled(false);
- break;
- }
- }
- menu->exec(m_table_view->viewport()->mapToGlobal(pos));
+ m_index_list_temp = m_table_view->selectionModel()->selectedRows(index.column());
+ GetTableContextMenu(index)->exec(m_table_view->viewport()->mapToGlobal(pos));
+ m_index_list_temp.clear();
+ m_index_list_temp.shrink_to_fit();
}
void BranchWatchDialog::OnTableHeaderContextMenu(const QPoint& pos)
@@ -870,67 +835,72 @@ void BranchWatchDialog::OnTableHeaderContextMenu(const QPoint& pos)
m_mnu_column_visibility->exec(m_table_view->horizontalHeader()->mapToGlobal(pos));
}
-void BranchWatchDialog::OnTableDelete(QModelIndexList index_list)
+void BranchWatchDialog::OnTableDelete()
{
- m_table_proxy->OnDelete(std::move(index_list));
+ std::ranges::transform(
+ m_index_list_temp, m_index_list_temp.begin(),
+ [this](const QModelIndex& index) { return m_table_proxy->mapToSource(index); });
+ std::ranges::sort(m_index_list_temp, std::less{});
+ for (const auto& index : std::ranges::reverse_view{m_index_list_temp})
+ {
+ if (!index.isValid())
+ continue;
+ m_table_model->removeRow(index.row());
+ }
UpdateStatus();
}
void BranchWatchDialog::OnTableDeleteKeypress()
{
- OnTableDelete(m_table_view->selectionModel()->selectedRows());
+ m_index_list_temp = m_table_view->selectionModel()->selectedRows();
+ OnTableDelete();
+ m_index_list_temp.clear();
+ m_index_list_temp.shrink_to_fit();
}
-void BranchWatchDialog::OnTableSetBLR(QModelIndexList index_list)
+void BranchWatchDialog::OnTableSetBLR()
{
- for (const QModelIndex& index : index_list)
- {
- m_system.GetPowerPC().GetDebugInterface().SetPatch(
- Core::CPUThreadGuard{m_system},
- m_table_proxy->data(index, UserRole::ClickRole).value<u32>(), 0x4e800020);
- m_table_proxy->SetInspected(index);
- }
- // TODO: This is not ideal. What I need is a signal for when memory has been changed by the GUI,
- // but I cannot find one. UpdateDisasmDialog comes close, but does too much in one signal. For
- // example, CodeViewWidget will scroll to the current PC when UpdateDisasmDialog is signaled. This
- // seems like a pervasive issue. For example, modifying an instruction in the CodeViewWidget will
- // not reflect in the MemoryViewWidget, and vice versa. Neither of these widgets changing memory
- // will reflect in the JITWidget, either. At the very least, we can make sure the CodeWidget
- // is updated in an acceptable way.
- m_code_widget->Update();
+ SetStubPatches(0x4e800020);
}
-void BranchWatchDialog::OnTableSetNOP(QModelIndexList index_list)
+void BranchWatchDialog::OnTableSetNOP()
{
- for (const QModelIndex& index : index_list)
- {
- m_system.GetPowerPC().GetDebugInterface().SetPatch(
- Core::CPUThreadGuard{m_system},
- m_table_proxy->data(index, UserRole::ClickRole).value<u32>(), 0x60000000);
- m_table_proxy->SetInspected(index);
- }
- // Same issue as OnSetBLR.
- m_code_widget->Update();
+ SetStubPatches(0x60000000);
}
-void BranchWatchDialog::OnTableCopyAddress(QModelIndexList index_list)
+void BranchWatchDialog::OnTableCopyAddress()
{
- auto iter = index_list.begin();
- if (iter == index_list.end())
+ auto iter = m_index_list_temp.begin();
+ if (iter == m_index_list_temp.end())
return;
QString text;
- text.reserve(index_list.size() * 9 - 1);
+ text.reserve(m_index_list_temp.size() * 9 - 1);
while (true)
{
text.append(QString::number(m_table_proxy->data(*iter, UserRole::ClickRole).value<u32>(), 16));
- if (++iter == index_list.end())
+ if (++iter == m_index_list_temp.end())
break;
text.append(QChar::fromLatin1('\n'));
}
QApplication::clipboard()->setText(text);
}
+void BranchWatchDialog::OnTableSetBreakpointBreak()
+{
+ SetBreakpoints(true, false);
+}
+
+void BranchWatchDialog::OnTableSetBreakpointLog()
+{
+ SetBreakpoints(false, true);
+}
+
+void BranchWatchDialog::OnTableSetBreakpointBoth()
+{
+ SetBreakpoints(true, true);
+}
+
void BranchWatchDialog::SaveSettings()
{
auto& settings = Settings::GetQSettings();
@@ -983,6 +953,12 @@ void BranchWatchDialog::UpdateStatus()
}
}
+void BranchWatchDialog::UpdateIcons()
+{
+ m_icn_full = Resources::GetThemeIcon("debugger_breakpoint");
+ m_icn_partial = Resources::GetThemeIcon("stop");
+}
+
void BranchWatchDialog::Save(const Core::CPUThreadGuard& guard, const std::string& filepath)
{
File::IOFile file(filepath, "w");
@@ -1019,3 +995,146 @@ void BranchWatchDialog::AutoSave(const Core::CPUThreadGuard& guard)
return;
Save(guard, m_autosave_filepath ? m_autosave_filepath.value() : GetSnapshotDefaultFilepath());
}
+
+void BranchWatchDialog::SetStubPatches(u32 value) const
+{
+ auto& debug_interface = m_system.GetPowerPC().GetDebugInterface();
+ for (const Core::CPUThreadGuard guard(m_system); const QModelIndex& index : m_index_list_temp)
+ {
+ debug_interface.SetPatch(guard, m_table_proxy->data(index, UserRole::ClickRole).value<u32>(),
+ value);
+ m_table_proxy->SetInspected(index);
+ }
+ // TODO: This is not ideal. What I need is a signal for when memory has been changed by the GUI,
+ // but I cannot find one. UpdateDisasmDialog comes close, but does too much in one signal. For
+ // example, CodeViewWidget will scroll to the current PC when UpdateDisasmDialog is signaled. This
+ // seems like a pervasive issue. For example, modifying an instruction in the CodeViewWidget will
+ // not reflect in the MemoryViewWidget, and vice versa. Neither of these widgets changing memory
+ // will reflect in the JITWidget, either. At the very least, we can make sure the CodeWidget
+ // is updated in an acceptable way.
+ m_code_widget->Update();
+}
+
+void BranchWatchDialog::SetBreakpoints(bool break_on_hit, bool log_on_hit) const
+{
+ auto& breakpoints = m_system.GetPowerPC().GetBreakPoints();
+ for (const QModelIndex& index : m_index_list_temp)
+ {
+ const u32 address = m_table_proxy->data(index, UserRole::ClickRole).value<u32>();
+ breakpoints.Add(address, false, break_on_hit, log_on_hit, {});
+ }
+ emit m_code_widget->BreakpointsChanged();
+ m_code_widget->Update();
+}
+
+QMenu* BranchWatchDialog::GetTableContextMenu(const QModelIndex& index)
+{
+ if (m_mnu_table_context == nullptr)
+ {
+ m_mnu_table_context = new QMenu(this);
+ m_mnu_table_context->addAction(tr("&Delete"), this, &BranchWatchDialog::OnTableDelete);
+ m_act_insert_nop =
+ m_mnu_table_context->addAction(tr("Insert &NOP"), this, &BranchWatchDialog::OnTableSetNOP);
+ m_act_insert_blr =
+ m_mnu_table_context->addAction(tr("Insert &BLR"), this, &BranchWatchDialog::OnTableSetBLR);
+ m_act_copy_address = m_mnu_table_context->addAction(tr("&Copy Address"), this,
+ &BranchWatchDialog::OnTableCopyAddress);
+
+ m_mnu_set_breakpoint = new QMenu(tr("Set Brea&kpoint"));
+ m_act_break_on_hit = m_mnu_set_breakpoint->addAction(
+ tr("&Break On Hit"), this, &BranchWatchDialog::OnTableSetBreakpointBreak);
+ m_act_log_on_hit = m_mnu_set_breakpoint->addAction(tr("&Log On Hit"), this,
+ &BranchWatchDialog::OnTableSetBreakpointLog);
+ m_act_both_on_hit = m_mnu_set_breakpoint->addAction(
+ tr("Break &And Log On Hit"), this, &BranchWatchDialog::OnTableSetBreakpointBoth);
+ m_mnu_table_context->addMenu(m_mnu_set_breakpoint);
+ }
+
+ const bool core_initialized = Core::GetState(m_system) != Core::State::Uninitialized;
+
+ bool supported_column = true;
+ switch (index.column())
+ {
+ case Column::Origin:
+ m_act_insert_blr->setVisible(false);
+ m_act_insert_nop->setVisible(true);
+ m_act_insert_nop->setEnabled(core_initialized);
+ m_act_copy_address->setEnabled(true);
+ m_mnu_set_breakpoint->setEnabled(true);
+ break;
+ case Column::Destination:
+ {
+ m_act_insert_nop->setVisible(false);
+ m_act_insert_blr->setVisible(true);
+ const bool all_branches_save_lr =
+ core_initialized &&
+ std::all_of(
+ m_index_list_temp.begin(), m_index_list_temp.end(), [this](const QModelIndex& idx) {
+ const QModelIndex sibling = idx.siblingAtColumn(Column::Instruction);
+ return BranchSavesLR(m_table_proxy->data(sibling, UserRole::ClickRole).value<u32>());
+ });
+ m_act_insert_blr->setEnabled(all_branches_save_lr);
+ m_act_copy_address->setEnabled(true);
+ m_mnu_set_breakpoint->setEnabled(true);
+ break;
+ }
+ case Column::OriginSymbol:
+ case Column::DestinSymbol:
+ {
+ m_act_insert_nop->setVisible(false);
+ m_act_insert_blr->setVisible(true);
+ const bool all_symbols_valid =
+ core_initialized &&
+ std::all_of(m_index_list_temp.begin(), m_index_list_temp.end(),
+ [this](const QModelIndex& idx) {
+ return m_table_proxy->data(idx, UserRole::ClickRole).isValid();
+ });
+ m_act_insert_blr->setEnabled(all_symbols_valid);
+ m_act_copy_address->setEnabled(all_symbols_valid);
+ m_mnu_set_breakpoint->setEnabled(all_symbols_valid);
+ break;
+ }
+ default:
+ m_act_insert_nop->setVisible(false);
+ m_act_insert_blr->setVisible(false);
+ supported_column = false;
+ break;
+ }
+ m_act_copy_address->setVisible(supported_column);
+ m_mnu_set_breakpoint->menuAction()->setVisible(supported_column);
+ // Setting breakpoints while nothing is being emulated is discouraged in the UI.
+ m_mnu_set_breakpoint->setEnabled(core_initialized);
+
+ if (core_initialized && supported_column)
+ {
+ qsizetype bp_break_count = 0, bp_log_count = 0, bp_both_count = 0;
+ for (auto& breakpoints = m_system.GetPowerPC().GetBreakPoints();
+ const QModelIndex& idx : m_index_list_temp)
+ {
+ if (const TBreakPoint* bp =
+ breakpoints.GetBreakpoint(m_table_proxy->data(idx, UserRole::ClickRole).value<u32>()))
+ {
+ if (bp->is_temporary)
+ continue;
+ if (bp->break_on_hit && bp->log_on_hit)
+ {
+ bp_both_count += 1;
+ continue;
+ }
+ bp_break_count += bp->break_on_hit;
+ bp_log_count += bp->log_on_hit;
+ }
+ }
+ m_act_break_on_hit->setIconVisibleInMenu(bp_break_count != 0);
+ m_act_break_on_hit->setIcon(bp_break_count == m_index_list_temp.size() ? m_icn_full :
+ m_icn_partial);
+ m_act_log_on_hit->setIconVisibleInMenu(bp_log_count != 0);
+ m_act_log_on_hit->setIcon(bp_log_count == m_index_list_temp.size() ? m_icn_full :
+ m_icn_partial);
+ m_act_both_on_hit->setIconVisibleInMenu(bp_both_count != 0);
+ m_act_both_on_hit->setIcon(bp_both_count == m_index_list_temp.size() ? m_icn_full :
+ m_icn_partial);
+ }
+
+ return m_mnu_table_context;
+}
diff --git a/Source/Core/DolphinQt/Debugger/BranchWatchDialog.h b/Source/Core/DolphinQt/Debugger/BranchWatchDialog.h
index b45f4c8563..05a8c82432 100644
--- a/Source/Core/DolphinQt/Debugger/BranchWatchDialog.h
+++ b/Source/Core/DolphinQt/Debugger/BranchWatchDialog.h
@@ -7,8 +7,11 @@
#include <string>
#include <QDialog>
+#include <QIcon>
#include <QModelIndexList>
+#include "Common/CommonTypes.h"
+
namespace Core
{
class BranchWatch;
@@ -77,6 +80,7 @@ private:
void OnWipeInspection();
void OnTimeout();
void OnEmulationStateChanged(Core::State new_state);
+ void OnThemeChanged();
void OnHelp();
void OnToggleAutoSave(bool checked);
void OnHideShowControls(bool checked);
@@ -85,11 +89,14 @@ private:
void OnTableClicked(const QModelIndex& index);
void OnTableContextMenu(const QPoint& pos);
void OnTableHeaderContextMenu(const QPoint& pos);
- void OnTableDelete(QModelIndexList index_list);
+ void OnTableDelete();
void OnTableDeleteKeypress();
- void OnTableSetBLR(QModelIndexList index_list);
- void OnTableSetNOP(QModelIndexList index_list);
- void OnTableCopyAddress(QModelIndexList index_list);
+ void OnTableSetBLR();
+ void OnTableSetNOP();
+ void OnTableCopyAddress();
+ void OnTableSetBreakpointBreak();
+ void OnTableSetBreakpointLog();
+ void OnTableSetBreakpointBoth();
void SaveSettings();
@@ -99,9 +106,14 @@ public:
private:
void UpdateStatus();
+ void UpdateIcons();
void Save(const Core::CPUThreadGuard& guard, const std::string& filepath);
void Load(const Core::CPUThreadGuard& guard, const std::string& filepath);
void AutoSave(const Core::CPUThreadGuard& guard);
+ void SetStubPatches(u32 value) const;
+ void SetBreakpoints(bool break_on_hit, bool log_on_hit) const;
+
+ [[nodiscard]] QMenu* GetTableContextMenu(const QModelIndex& index);
Core::System& m_system;
Core::BranchWatch& m_branch_watch;
@@ -110,6 +122,14 @@ private:
QPushButton *m_btn_start_pause, *m_btn_clear_watch, *m_btn_path_was_taken, *m_btn_path_not_taken,
*m_btn_was_overwritten, *m_btn_not_overwritten, *m_btn_wipe_recent_hits;
QAction* m_act_autosave;
+ QAction* m_act_insert_nop;
+ QAction* m_act_insert_blr;
+ QAction* m_act_copy_address;
+ QMenu* m_mnu_set_breakpoint;
+ QAction* m_act_break_on_hit;
+ QAction* m_act_log_on_hit;
+ QAction* m_act_both_on_hit;
+ QMenu* m_mnu_table_context = nullptr;
QMenu* m_mnu_column_visibility;
QToolBar* m_control_toolbar;
@@ -119,5 +139,8 @@ private:
QStatusBar* m_status_bar;
QTimer* m_timer;
+ QIcon m_icn_full, m_icn_partial;
+
+ QModelIndexList m_index_list_temp;
std::optional<std::string> m_autosave_filepath;
};
diff --git a/Source/Core/DolphinQt/Debugger/BranchWatchTableModel.cpp b/Source/Core/DolphinQt/Debugger/BranchWatchTableModel.cpp
index e4d8dd21a2..a377f82c4e 100644
--- a/Source/Core/DolphinQt/Debugger/BranchWatchTableModel.cpp
+++ b/Source/Core/DolphinQt/Debugger/BranchWatchTableModel.cpp
@@ -145,18 +145,6 @@ void BranchWatchTableModel::OnWipeInspection()
roles);
}
-void BranchWatchTableModel::OnDelete(QModelIndexList index_list)
-{
- std::sort(index_list.begin(), index_list.end());
- // TODO C++20: std::ranges::reverse_view
- for (auto iter = index_list.rbegin(); iter != index_list.rend(); ++iter)
- {
- if (!iter->isValid())
- continue;
- removeRow(iter->row());
- }
-}
-
void BranchWatchTableModel::Save(const Core::CPUThreadGuard& guard, std::FILE* file) const
{
m_branch_watch.Save(guard, file);
diff --git a/Source/Core/DolphinQt/Debugger/BranchWatchTableModel.h b/Source/Core/DolphinQt/Debugger/BranchWatchTableModel.h
index aad2fd783a..500a8ca53c 100644
--- a/Source/Core/DolphinQt/Debugger/BranchWatchTableModel.h
+++ b/Source/Core/DolphinQt/Debugger/BranchWatchTableModel.h
@@ -97,7 +97,6 @@ public:
void OnBranchNotOverwritten(const Core::CPUThreadGuard& guard);
void OnWipeRecentHits();
void OnWipeInspection();
- void OnDelete(QModelIndexList index_list);
void Save(const Core::CPUThreadGuard& guard, std::FILE* file) const;
void Load(const Core::CPUThreadGuard& guard, std::FILE* file);