diff --git a/pcsx2-qt/Debugger/Breakpoints/BreakpointModel.cpp b/pcsx2-qt/Debugger/Breakpoints/BreakpointModel.cpp index 6ae76dd410..1e28da0752 100644 --- a/pcsx2-qt/Debugger/Breakpoints/BreakpointModel.cpp +++ b/pcsx2-qt/Debugger/Breakpoints/BreakpointModel.cpp @@ -565,6 +565,15 @@ void BreakpointModel::refreshData() } void BreakpointModel::loadBreakpointFromFieldList(QStringList fields) +{ + std::optional bp = getBreakpointFromFieldList(fields); + if (bp.has_value()) + { + insertBreakpointRows(0, 1, {bp.value()}); + } +} + +std::optional BreakpointModel::getBreakpointFromFieldList(QStringList fields) { std::string error; @@ -572,7 +581,7 @@ void BreakpointModel::loadBreakpointFromFieldList(QStringList fields) if (fields.size() != BreakpointColumns::COLUMN_COUNT) { Console.WriteLn("Debugger Breakpoint Model: Invalid number of columns, skipping"); - return; + return {}; } const int type = fields[BreakpointColumns::TYPE].toUInt(&ok); @@ -580,7 +589,7 @@ void BreakpointModel::loadBreakpointFromFieldList(QStringList fields) { Console.WriteLn("Debugger Breakpoint Model: Failed to parse type '%s', skipping", fields[BreakpointColumns::TYPE].toUtf8().constData()); - return; + return {}; } // This is how we differentiate between breakpoints and memchecks @@ -594,7 +603,7 @@ void BreakpointModel::loadBreakpointFromFieldList(QStringList fields) { Console.WriteLn("Debugger Breakpoint Model: Failed to parse address '%s', skipping", fields[BreakpointColumns::OFFSET].toUtf8().constData()); - return; + return {}; } // Condition @@ -608,7 +617,7 @@ void BreakpointModel::loadBreakpointFromFieldList(QStringList fields) { Console.WriteLn("Debugger Breakpoint Model: Failed to parse cond '%s', skipping", fields[BreakpointModel::CONDITION].toUtf8().constData()); - return; + return {}; } bp.cond.expression = expr; bp.cond.expressionString = fields[BreakpointColumns::CONDITION].toStdString(); @@ -620,7 +629,7 @@ void BreakpointModel::loadBreakpointFromFieldList(QStringList fields) { Console.WriteLn("Debugger Breakpoint Model: Failed to parse enable flag '%s', skipping", fields[BreakpointColumns::ENABLED].toUtf8().constData()); - return; + return {}; } // Description @@ -629,7 +638,7 @@ void BreakpointModel::loadBreakpointFromFieldList(QStringList fields) bp.description = fields[BreakpointColumns::DESCRIPTION].toStdString(); } - insertBreakpointRows(0, 1, {bp}); + return bp; } else { @@ -639,18 +648,17 @@ void BreakpointModel::loadBreakpointFromFieldList(QStringList fields) { Console.WriteLn("Debugger Breakpoint Model: Failed to parse cond type '%s', skipping", fields[BreakpointColumns::TYPE].toUtf8().constData()); - return; + return {}; } mc.memCond = static_cast(type); // Address - QString test = fields[BreakpointColumns::OFFSET]; mc.start = fields[BreakpointColumns::OFFSET].toUInt(&ok, 16); if (!ok) { Console.WriteLn("Debugger Breakpoint Model: Failed to parse address '%s', skipping", fields[BreakpointColumns::OFFSET].toUtf8().constData()); - return; + return {}; } // Size @@ -659,7 +667,7 @@ void BreakpointModel::loadBreakpointFromFieldList(QStringList fields) { Console.WriteLn("Debugger Breakpoint Model: Failed to parse length '%s', skipping", fields[BreakpointColumns::SIZE_LABEL].toUtf8().constData()); - return; + return {}; } // Condition @@ -673,7 +681,7 @@ void BreakpointModel::loadBreakpointFromFieldList(QStringList fields) { Console.WriteLn("Debugger Breakpoint Model: Failed to parse cond '%s', skipping", fields[BreakpointColumns::CONDITION].toUtf8().constData()); - return; + return {}; } mc.cond.expression = expr; mc.cond.expressionString = fields[BreakpointColumns::CONDITION].toStdString(); @@ -685,7 +693,7 @@ void BreakpointModel::loadBreakpointFromFieldList(QStringList fields) { Console.WriteLn("Debugger Breakpoint Model: Failed to parse result flag '%s', skipping", fields[BreakpointColumns::ENABLED].toUtf8().constData()); - return; + return {}; } mc.result = static_cast(result); @@ -695,7 +703,7 @@ void BreakpointModel::loadBreakpointFromFieldList(QStringList fields) mc.description = fields[BreakpointColumns::DESCRIPTION].toStdString(); } - insertBreakpointRows(0, 1, {mc}); + return mc; } } diff --git a/pcsx2-qt/Debugger/Breakpoints/BreakpointModel.h b/pcsx2-qt/Debugger/Breakpoints/BreakpointModel.h index 307ce9d3c2..7612334609 100644 --- a/pcsx2-qt/Debugger/Breakpoints/BreakpointModel.h +++ b/pcsx2-qt/Debugger/Breakpoints/BreakpointModel.h @@ -6,6 +6,8 @@ #include #include +#include + #include "DebugTools/DebugInterface.h" #include "DebugTools/Breakpoints.h" @@ -57,6 +59,7 @@ public: bool removeRows(int row, int count, const QModelIndex& index = QModelIndex()) override; bool insertBreakpointRows(int row, int count, std::vector breakpoints, const QModelIndex& index = QModelIndex()); void loadBreakpointFromFieldList(QStringList breakpointFields); + std::optional getBreakpointFromFieldList(QStringList fields); BreakpointMemcheck at(int row) const { return m_breakpoints.at(row); }; diff --git a/pcsx2-qt/Debugger/Breakpoints/BreakpointView.cpp b/pcsx2-qt/Debugger/Breakpoints/BreakpointView.cpp index 87daaa3c6e..73122b29bd 100644 --- a/pcsx2-qt/Debugger/Breakpoints/BreakpointView.cpp +++ b/pcsx2-qt/Debugger/Breakpoints/BreakpointView.cpp @@ -122,7 +122,6 @@ void BreakpointView::openContextMenu(QPoint pos) { QAction* actionLoad = menu->addAction(tr("Load from Settings")); connect(actionLoad, &QAction::triggered, [this]() { - m_model->clear(); DebuggerSettingsManager::loadGameSettings(m_model); }); diff --git a/pcsx2-qt/Debugger/DebuggerSettingsManager.cpp b/pcsx2-qt/Debugger/DebuggerSettingsManager.cpp index 6cc20e150b..a0dce90894 100644 --- a/pcsx2-qt/Debugger/DebuggerSettingsManager.cpp +++ b/pcsx2-qt/Debugger/DebuggerSettingsManager.cpp @@ -54,7 +54,8 @@ void DebuggerSettingsManager::loadGameSettings(BreakpointModel* bpModel) if (path.empty()) return; - const QJsonValue breakpointsValue = loadGameSettingsJSON().value("Breakpoints"); + const QJsonObject breakpointsFile = loadGameSettingsJSON(); + const QJsonValue breakpointsValue = breakpointsFile.value("Breakpoints"); const QString valueToLoad = breakpointsValue.toString(); if (breakpointsValue.isUndefined() || !breakpointsValue.isArray()) { @@ -67,13 +68,14 @@ void DebuggerSettingsManager::loadGameSettings(BreakpointModel* bpModel) // missing a description. This code will add in an empty description so that the previous // version, 0.00, is compatible with 0.01. bool isMissingDescription = false; - const QJsonValue savedVersionValue = loadGameSettingsJSON().value("Version"); + const QJsonValue savedVersionValue = breakpointsFile.value("Version"); if (!savedVersionValue.isUndefined()) { isMissingDescription = savedVersionValue.toString().toStdString() == "0.00"; } const QJsonArray breakpointsArray = breakpointsValue.toArray(); + std::vector breakpoints; for (u32 row = 0; row < breakpointsArray.size(); row++) { const QJsonValue rowValue = breakpointsArray.at(row); @@ -97,7 +99,31 @@ void DebuggerSettingsManager::loadGameSettings(BreakpointModel* bpModel) QString headerColKey = bpModel->headerData(col, Qt::Horizontal, Qt::UserRole).toString(); fields << rowObject.value(headerColKey).toString(); } - bpModel->loadBreakpointFromFieldList(fields); + std::optional breakpoint = bpModel->getBreakpointFromFieldList(fields); + if (breakpoint.has_value()) + { + breakpoints.push_back(breakpoint.value()); + } + } + + if (breakpointsArray.empty()) + { + if (bpModel->rowCount() > 0) + { + bpModel->removeRows(0, bpModel->rowCount()); + } + } + else if (!breakpointsArray.empty() && breakpoints.empty()) + { + Console.WriteLn("Debugger Settings Manager: Parsing failed for every entry, preserving current breakpoints."); + } + else + { + if (bpModel->rowCount() > 0) + { + bpModel->removeRows(0, bpModel->rowCount()); + } + bpModel->insertBreakpointRows(0, breakpoints.size(), breakpoints); } }