2023-12-22 11:57:49 +00:00
// SPDX-FileCopyrightText: 2002-2023 PCSX2 Dev Team
// SPDX-License-Identifier: LGPL-3.0+
2023-01-03 05:27:05 +00:00
# include "BreakpointModel.h"
# include "DebugTools/DebugInterface.h"
# include "DebugTools/Breakpoints.h"
# include "DebugTools/DisassemblyManager.h"
2024-01-19 01:15:40 +00:00
# include "common/Console.h"
2023-01-03 05:27:05 +00:00
# include "QtHost.h"
# include "QtUtils.h"
# include <QtWidgets/QMessageBox>
# include <algorithm>
BreakpointModel : : BreakpointModel ( DebugInterface & cpu , QObject * parent )
: QAbstractTableModel ( parent )
, m_cpu ( cpu )
{
}
int BreakpointModel : : rowCount ( const QModelIndex & ) const
{
return m_breakpoints . size ( ) ;
}
int BreakpointModel : : columnCount ( const QModelIndex & ) const
{
return BreakpointColumns : : COLUMN_COUNT ;
}
QVariant BreakpointModel : : data ( const QModelIndex & index , int role ) const
{
if ( role = = Qt : : DisplayRole )
{
auto bp_mc = m_breakpoints . at ( index . row ( ) ) ;
if ( const auto * bp = std : : get_if < BreakPoint > ( & bp_mc ) )
{
switch ( index . column ( ) )
{
2023-10-26 22:46:41 +00:00
case BreakpointColumns : : ENABLED :
return " " ;
2023-01-03 05:27:05 +00:00
case BreakpointColumns : : TYPE :
return tr ( " Execute " ) ;
case BreakpointColumns : : OFFSET :
return QtUtils : : FilledQStringFromValue ( bp - > addr , 16 ) ;
case BreakpointColumns : : SIZE_LABEL :
2023-10-25 22:00:54 +00:00
return m_cpu . GetSymbolMap ( ) . GetLabelName ( bp - > addr ) . c_str ( ) ;
2023-01-03 05:27:05 +00:00
case BreakpointColumns : : OPCODE :
// Note: Fix up the disassemblymanager so we can use it here, instead of calling a function through the disassemblyview (yuck)
return m_cpu . disasm ( bp - > addr , true ) . c_str ( ) ;
case BreakpointColumns : : CONDITION :
2023-10-26 22:26:16 +00:00
return bp - > hasCond ? QString : : fromLocal8Bit ( bp - > cond . expressionString ) : " " ;
2023-01-03 05:27:05 +00:00
case BreakpointColumns : : HITS :
return tr ( " -- " ) ;
}
}
else if ( const auto * mc = std : : get_if < MemCheck > ( & bp_mc ) )
{
switch ( index . column ( ) )
{
2023-10-26 22:46:41 +00:00
case BreakpointColumns : : ENABLED :
return ( mc - > result & MEMCHECK_BREAK ) ? tr ( " Enabled " ) : tr ( " Disabled " ) ;
2023-01-03 05:27:05 +00:00
case BreakpointColumns : : TYPE :
{
QString type ( " " ) ;
type + = ( mc - > cond & MEMCHECK_READ ) ? tr ( " Read " ) : " " ;
2023-07-27 00:06:47 +00:00
type + = ( ( mc - > cond & MEMCHECK_READWRITE ) = = MEMCHECK_READWRITE ) ? " , " : " " ;
2023-03-18 21:14:55 +00:00
//: (C) = changes, as in "look for changes".
2023-01-03 05:27:05 +00:00
type + = ( mc - > cond & MEMCHECK_WRITE ) ? ( mc - > cond & MEMCHECK_WRITE_ONCHANGE ) ? tr ( " Write(C) " ) : tr ( " Write " ) : " " ;
return type ;
}
case BreakpointColumns : : OFFSET :
return QtUtils : : FilledQStringFromValue ( mc - > start , 16 ) ;
case BreakpointColumns : : SIZE_LABEL :
return QString : : number ( mc - > end - mc - > start , 16 ) ;
case BreakpointColumns : : OPCODE :
return tr ( " -- " ) ; // Our address is going to point to memory, no purpose in printing the op
case BreakpointColumns : : CONDITION :
return tr ( " -- " ) ; // No condition on memchecks
case BreakpointColumns : : HITS :
return QString : : number ( mc - > numHits ) ;
}
}
}
2023-10-15 00:54:39 +00:00
else if ( role = = BreakpointModel : : DataRole )
2023-01-07 06:23:15 +00:00
{
auto bp_mc = m_breakpoints . at ( index . row ( ) ) ;
if ( const auto * bp = std : : get_if < BreakPoint > ( & bp_mc ) )
{
switch ( index . column ( ) )
{
2023-10-26 22:46:41 +00:00
case BreakpointColumns : : ENABLED :
return static_cast < int > ( bp - > enabled ) ;
2023-01-07 06:23:15 +00:00
case BreakpointColumns : : TYPE :
2023-10-09 22:27:24 +00:00
return MEMCHECK_INVALID ;
2023-01-07 06:23:15 +00:00
case BreakpointColumns : : OFFSET :
return bp - > addr ;
case BreakpointColumns : : SIZE_LABEL :
2023-10-25 22:00:54 +00:00
return m_cpu . GetSymbolMap ( ) . GetLabelName ( bp - > addr ) . c_str ( ) ;
2023-01-07 06:23:15 +00:00
case BreakpointColumns : : OPCODE :
// Note: Fix up the disassemblymanager so we can use it here, instead of calling a function through the disassemblyview (yuck)
2024-04-18 19:53:47 +00:00
return m_cpu . disasm ( bp - > addr , false ) . c_str ( ) ;
2023-01-07 06:23:15 +00:00
case BreakpointColumns : : CONDITION :
2023-11-10 15:08:17 +00:00
return bp - > hasCond ? QString : : fromLocal8Bit ( bp - > cond . expressionString ) : " " ;
2023-01-07 06:23:15 +00:00
case BreakpointColumns : : HITS :
return 0 ;
}
}
else if ( const auto * mc = std : : get_if < MemCheck > ( & bp_mc ) )
{
switch ( index . column ( ) )
{
2023-10-26 22:46:41 +00:00
case BreakpointColumns : : ENABLED :
return ( mc - > result & MEMCHECK_BREAK ) ;
2023-01-07 06:23:15 +00:00
case BreakpointColumns : : TYPE :
return mc - > cond ;
case BreakpointColumns : : OFFSET :
return mc - > start ;
case BreakpointColumns : : SIZE_LABEL :
return mc - > end - mc - > start ;
case BreakpointColumns : : OPCODE :
return " " ;
case BreakpointColumns : : CONDITION :
return " " ;
case BreakpointColumns : : HITS :
return mc - > numHits ;
}
}
}
2023-10-15 00:54:39 +00:00
else if ( role = = BreakpointModel : : ExportRole )
{
auto bp_mc = m_breakpoints . at ( index . row ( ) ) ;
if ( const auto * bp = std : : get_if < BreakPoint > ( & bp_mc ) )
{
switch ( index . column ( ) )
{
2023-10-26 22:46:41 +00:00
case BreakpointColumns : : ENABLED :
return static_cast < int > ( bp - > enabled ) ;
2023-10-15 00:54:39 +00:00
case BreakpointColumns : : TYPE :
return MEMCHECK_INVALID ;
case BreakpointColumns : : OFFSET :
return QtUtils : : FilledQStringFromValue ( bp - > addr , 16 ) ;
case BreakpointColumns : : SIZE_LABEL :
2023-10-25 22:00:54 +00:00
return m_cpu . GetSymbolMap ( ) . GetLabelName ( bp - > addr ) . c_str ( ) ;
2023-10-15 00:54:39 +00:00
case BreakpointColumns : : OPCODE :
// Note: Fix up the disassemblymanager so we can use it here, instead of calling a function through the disassemblyview (yuck)
2024-04-18 19:53:47 +00:00
return m_cpu . disasm ( bp - > addr , false ) . c_str ( ) ;
2023-10-15 00:54:39 +00:00
case BreakpointColumns : : CONDITION :
2023-11-10 15:08:17 +00:00
return bp - > hasCond ? QString : : fromLocal8Bit ( bp - > cond . expressionString ) : " " ;
2023-10-15 00:54:39 +00:00
case BreakpointColumns : : HITS :
return 0 ;
}
}
else if ( const auto * mc = std : : get_if < MemCheck > ( & bp_mc ) )
{
switch ( index . column ( ) )
{
case BreakpointColumns : : TYPE :
return mc - > cond ;
case BreakpointColumns : : OFFSET :
return QtUtils : : FilledQStringFromValue ( mc - > start , 16 ) ;
case BreakpointColumns : : SIZE_LABEL :
return mc - > end - mc - > start ;
case BreakpointColumns : : OPCODE :
return " " ;
case BreakpointColumns : : CONDITION :
return " " ;
case BreakpointColumns : : HITS :
return mc - > numHits ;
case BreakpointColumns : : ENABLED :
return ( mc - > result & MEMCHECK_BREAK ) ;
}
}
}
2023-01-03 05:27:05 +00:00
else if ( role = = Qt : : CheckStateRole )
{
2023-10-26 22:46:41 +00:00
if ( index . column ( ) = = 0 )
2023-01-03 05:27:05 +00:00
{
auto bp_mc = m_breakpoints . at ( index . row ( ) ) ;
if ( const auto * bp = std : : get_if < BreakPoint > ( & bp_mc ) )
{
return bp - > enabled ? Qt : : CheckState : : Checked : Qt : : CheckState : : Unchecked ;
}
else if ( const auto * mc = std : : get_if < MemCheck > ( & bp_mc ) )
{
return ( mc - > result & MEMCHECK_BREAK ) ? Qt : : CheckState : : Checked : Qt : : CheckState : : Unchecked ;
}
}
}
return QVariant ( ) ;
}
QVariant BreakpointModel : : headerData ( int section , Qt : : Orientation orientation , int role ) const
{
if ( role = = Qt : : DisplayRole & & orientation = = Qt : : Horizontal )
{
switch ( section )
{
case BreakpointColumns : : TYPE :
2023-03-18 21:14:55 +00:00
//: Warning: limited space available. Abbreviate if needed.
2023-01-03 05:27:05 +00:00
return tr ( " TYPE " ) ;
case BreakpointColumns : : OFFSET :
2023-03-18 21:14:55 +00:00
//: Warning: limited space available. Abbreviate if needed.
2023-01-03 05:27:05 +00:00
return tr ( " OFFSET " ) ;
case BreakpointColumns : : SIZE_LABEL :
2023-03-18 21:14:55 +00:00
//: Warning: limited space available. Abbreviate if needed.
2023-01-03 05:27:05 +00:00
return tr ( " SIZE / LABEL " ) ;
case BreakpointColumns : : OPCODE :
2023-03-18 21:14:55 +00:00
//: Warning: limited space available. Abbreviate if needed.
2023-01-03 05:27:05 +00:00
return tr ( " INSTRUCTION " ) ;
case BreakpointColumns : : CONDITION :
2023-03-18 21:14:55 +00:00
//: Warning: limited space available. Abbreviate if needed.
2023-01-03 05:27:05 +00:00
return tr ( " CONDITION " ) ;
case BreakpointColumns : : HITS :
2023-03-18 21:14:55 +00:00
//: Warning: limited space available. Abbreviate if needed.
2023-01-03 05:27:05 +00:00
return tr ( " HITS " ) ;
case BreakpointColumns : : ENABLED :
2023-03-18 21:14:55 +00:00
//: Warning: limited space available. Abbreviate if needed.
2023-10-26 22:26:16 +00:00
return tr ( " X " ) ;
2023-01-03 05:27:05 +00:00
default :
return QVariant ( ) ;
}
}
2024-01-19 01:15:40 +00:00
if ( role = = Qt : : UserRole & & orientation = = Qt : : Horizontal )
{
switch ( section )
{
case BreakpointColumns : : TYPE :
return " TYPE " ;
case BreakpointColumns : : OFFSET :
return " OFFSET " ;
case BreakpointColumns : : SIZE_LABEL :
return " SIZE / LABEL " ;
case BreakpointColumns : : OPCODE :
return " INSTRUCTION " ;
case BreakpointColumns : : CONDITION :
return " CONDITION " ;
case BreakpointColumns : : HITS :
return " HITS " ;
case BreakpointColumns : : ENABLED :
return " X " ;
default :
return QVariant ( ) ;
}
}
2023-01-03 05:27:05 +00:00
return QVariant ( ) ;
}
Qt : : ItemFlags BreakpointModel : : flags ( const QModelIndex & index ) const
{
volatile const int row = index . row ( ) ;
bool is_breakpoint = std : : holds_alternative < BreakPoint > ( m_breakpoints . at ( row ) ) ;
switch ( index . column ( ) )
{
case BreakpointColumns : : CONDITION :
if ( is_breakpoint )
return Qt : : ItemFlag : : ItemIsEnabled | Qt : : ItemFlag : : ItemIsSelectable | Qt : : ItemFlag : : ItemIsEditable ;
[[fallthrough]] ;
case BreakpointColumns : : TYPE :
case BreakpointColumns : : OPCODE :
case BreakpointColumns : : HITS :
case BreakpointColumns : : OFFSET :
case BreakpointColumns : : SIZE_LABEL :
return Qt : : ItemFlag : : ItemIsEnabled | Qt : : ItemFlag : : ItemIsSelectable ;
case BreakpointColumns : : ENABLED :
return Qt : : ItemFlag : : ItemIsUserCheckable | Qt : : ItemFlag : : ItemIsEnabled | Qt : : ItemFlag : : ItemIsSelectable ;
}
return index . flags ( ) ;
}
bool BreakpointModel : : setData ( const QModelIndex & index , const QVariant & value , int role )
{
if ( role = = Qt : : CheckStateRole & & index . column ( ) = = BreakpointColumns : : ENABLED )
{
auto bp_mc = m_breakpoints . at ( index . row ( ) ) ;
if ( const auto * bp = std : : get_if < BreakPoint > ( & bp_mc ) )
{
Host : : RunOnCPUThread ( [ cpu = this - > m_cpu . getCpuType ( ) , bp = * bp , enabled = value . toBool ( ) ] {
CBreakPoints : : ChangeBreakPoint ( cpu , bp . addr , enabled ) ;
} ) ;
}
else if ( const auto * mc = std : : get_if < MemCheck > ( & bp_mc ) )
{
Host : : RunOnCPUThread ( [ cpu = this - > m_cpu . getCpuType ( ) , mc = * mc ] {
CBreakPoints : : ChangeMemCheck ( cpu , mc . start , mc . end , mc . cond ,
MemCheckResult ( mc . result ^ MEMCHECK_BREAK ) ) ;
} ) ;
}
2024-04-07 20:48:28 +00:00
emit dataChanged ( index , index ) ;
2023-01-03 05:27:05 +00:00
return true ;
}
else if ( role = = Qt : : EditRole & & index . column ( ) = = BreakpointColumns : : CONDITION )
{
auto bp_mc = m_breakpoints . at ( index . row ( ) ) ;
if ( std : : holds_alternative < MemCheck > ( bp_mc ) )
return false ;
const auto bp = std : : get < BreakPoint > ( bp_mc ) ;
const QString condValue = value . toString ( ) ;
if ( condValue . isEmpty ( ) )
{
if ( bp . hasCond )
{
Host : : RunOnCPUThread ( [ cpu = m_cpu . getCpuType ( ) , bp ] {
CBreakPoints : : ChangeBreakPointRemoveCond ( cpu , bp . addr ) ;
} ) ;
}
}
else
{
PostfixExpression expr ;
if ( ! m_cpu . initExpression ( condValue . toLocal8Bit ( ) . constData ( ) , expr ) )
{
QMessageBox : : warning ( nullptr , " Condition Error " , QString ( getExpressionError ( ) ) ) ;
return false ;
}
BreakPointCond cond ;
cond . debug = & m_cpu ;
cond . expression = expr ;
strcpy ( & cond . expressionString [ 0 ] , condValue . toLocal8Bit ( ) . constData ( ) ) ;
Host : : RunOnCPUThread ( [ cpu = m_cpu . getCpuType ( ) , bp , cond ] {
CBreakPoints : : ChangeBreakPointAddCond ( cpu , bp . addr , cond ) ;
} ) ;
}
2024-04-07 20:48:28 +00:00
emit dataChanged ( index , index ) ;
return true ;
2023-01-03 05:27:05 +00:00
}
return false ;
}
bool BreakpointModel : : removeRows ( int row , int count , const QModelIndex & index )
{
2023-12-30 04:01:30 +00:00
beginRemoveRows ( index , row , row + count - 1 ) ;
2023-01-03 05:27:05 +00:00
for ( int i = row ; i < row + count ; i + + )
{
auto bp_mc = m_breakpoints . at ( i ) ;
if ( const auto * bp = std : : get_if < BreakPoint > ( & bp_mc ) )
{
Host : : RunOnCPUThread ( [ cpu = m_cpu . getCpuType ( ) , addr = bp - > addr ] {
CBreakPoints : : RemoveBreakPoint ( cpu , addr ) ;
} ) ;
}
else if ( const auto * mc = std : : get_if < MemCheck > ( & bp_mc ) )
{
Host : : RunOnCPUThread ( [ cpu = m_cpu . getCpuType ( ) , start = mc - > start , end = mc - > end ] {
CBreakPoints : : RemoveMemCheck ( cpu , start , end ) ;
} ) ;
}
}
2024-04-07 20:48:28 +00:00
const auto begin = m_breakpoints . begin ( ) + row ;
const auto end = begin + count ;
m_breakpoints . erase ( begin , end ) ;
2023-01-03 05:27:05 +00:00
endRemoveRows ( ) ;
return true ;
}
2023-01-12 09:15:55 +00:00
bool BreakpointModel : : insertBreakpointRows ( int row , int count , std : : vector < BreakpointMemcheck > breakpoints , const QModelIndex & index )
2023-01-03 05:27:05 +00:00
{
2023-01-12 09:15:55 +00:00
if ( breakpoints . size ( ) ! = static_cast < size_t > ( count ) )
2023-01-03 05:27:05 +00:00
return false ;
2023-04-28 01:07:03 +00:00
beginInsertRows ( index , row , row + ( count - 1 ) ) ;
2023-01-03 05:27:05 +00:00
2023-04-28 01:07:03 +00:00
// After endInsertRows, Qt will try and validate our new rows
// Because we add the breakpoints off of the UI thread, our new rows may not be visible yet
// To prevent the (seemingly harmless?) warning emitted by enderInsertRows, add the breakpoints manually here as well
m_breakpoints . insert ( m_breakpoints . begin ( ) , breakpoints . begin ( ) , breakpoints . end ( ) ) ;
2023-01-03 05:27:05 +00:00
for ( const auto & bp_mc : breakpoints )
{
if ( const auto * bp = std : : get_if < BreakPoint > ( & bp_mc ) )
{
Host : : RunOnCPUThread ( [ cpu = m_cpu . getCpuType ( ) , bp = * bp ] {
2023-10-09 22:27:24 +00:00
CBreakPoints : : AddBreakPoint ( cpu , bp . addr , false , bp . enabled ) ;
2023-01-03 05:27:05 +00:00
if ( bp . hasCond )
{
CBreakPoints : : ChangeBreakPointAddCond ( cpu , bp . addr , bp . cond ) ;
}
} ) ;
}
else if ( const auto * mc = std : : get_if < MemCheck > ( & bp_mc ) )
{
Host : : RunOnCPUThread ( [ cpu = m_cpu . getCpuType ( ) , mc = * mc ] {
CBreakPoints : : AddMemCheck ( cpu , mc . start , mc . end , mc . cond , mc . result ) ;
} ) ;
}
}
endInsertRows ( ) ;
return true ;
}
void BreakpointModel : : refreshData ( )
{
2024-04-07 20:48:28 +00:00
Host : : RunOnCPUThread ( [ this ] ( ) mutable {
2023-01-03 05:27:05 +00:00
2024-04-07 20:48:28 +00:00
std : : vector < BreakpointMemcheck > all_breakpoints ;
std : : ranges : : move ( CBreakPoints : : GetBreakpoints ( m_cpu . getCpuType ( ) , false ) , std : : back_inserter ( all_breakpoints ) ) ;
std : : ranges : : move ( CBreakPoints : : GetMemChecks ( m_cpu . getCpuType ( ) ) , std : : back_inserter ( all_breakpoints ) ) ;
2023-01-03 05:27:05 +00:00
2024-04-07 20:48:28 +00:00
QtHost : : RunOnUIThread ( [ this , breakpoints = std : : move ( all_breakpoints ) ] ( ) mutable {
beginResetModel ( ) ;
m_breakpoints = std : : move ( breakpoints ) ;
endResetModel ( ) ;
} ) ;
2023-01-03 05:27:05 +00:00
2024-04-07 20:48:28 +00:00
} ) ;
2023-01-03 05:27:05 +00:00
}
2024-01-19 01:15:40 +00:00
void BreakpointModel : : loadBreakpointFromFieldList ( QStringList fields )
{
bool ok ;
if ( fields . size ( ) ! = BreakpointModel : : BreakpointColumns : : COLUMN_COUNT )
{
Console . WriteLn ( " Debugger Breakpoint Model: Invalid number of columns, skipping " ) ;
return ;
}
const int type = fields [ BreakpointModel : : BreakpointColumns : : TYPE ] . toUInt ( & ok ) ;
if ( ! ok )
{
Console . WriteLn ( " Debugger Breakpoint Model: Failed to parse type '%s', skipping " , fields [ BreakpointModel : : BreakpointColumns : : TYPE ] . toUtf8 ( ) . constData ( ) ) ;
return ;
}
// This is how we differentiate between breakpoints and memchecks
if ( type = = MEMCHECK_INVALID )
{
BreakPoint bp ;
// Address
bp . addr = fields [ BreakpointModel : : BreakpointColumns : : OFFSET ] . toUInt ( & ok , 16 ) ;
if ( ! ok )
{
Console . WriteLn ( " Debugger Breakpoint Model: Failed to parse address '%s', skipping " , fields [ BreakpointModel : : BreakpointColumns : : OFFSET ] . toUtf8 ( ) . constData ( ) ) ;
return ;
}
// Condition
if ( ! fields [ BreakpointModel : : BreakpointColumns : : CONDITION ] . isEmpty ( ) )
{
PostfixExpression expr ;
bp . hasCond = true ;
bp . cond . debug = & m_cpu ;
if ( ! m_cpu . initExpression ( fields [ BreakpointModel : : BreakpointColumns : : CONDITION ] . toUtf8 ( ) . constData ( ) , expr ) )
{
Console . WriteLn ( " Debugger Breakpoint Model: Failed to parse cond '%s', skipping " , fields [ BreakpointModel : : BreakpointColumns : : CONDITION ] . toUtf8 ( ) . constData ( ) ) ;
return ;
}
bp . cond . expression = expr ;
strncpy ( & bp . cond . expressionString [ 0 ] , fields [ BreakpointModel : : BreakpointColumns : : CONDITION ] . toUtf8 ( ) . constData ( ) , sizeof ( bp . cond . expressionString ) ) ;
}
// Enabled
bp . enabled = fields [ BreakpointModel : : BreakpointColumns : : ENABLED ] . toUInt ( & ok ) ;
if ( ! ok )
{
Console . WriteLn ( " Debugger Breakpoint Model: Failed to parse enable flag '%s', skipping " , fields [ BreakpointModel : : BreakpointColumns : : ENABLED ] . toUtf8 ( ) . constData ( ) ) ;
return ;
}
insertBreakpointRows ( 0 , 1 , { bp } ) ;
}
else
{
MemCheck mc ;
// Mode
if ( type > = MEMCHECK_INVALID )
{
Console . WriteLn ( " Debugger Breakpoint Model: Failed to parse cond type '%s', skipping " , fields [ BreakpointModel : : BreakpointColumns : : TYPE ] . toUtf8 ( ) . constData ( ) ) ;
return ;
}
mc . cond = static_cast < MemCheckCondition > ( type ) ;
// Address
QString test = fields [ BreakpointModel : : BreakpointColumns : : OFFSET ] ;
mc . start = fields [ BreakpointModel : : BreakpointColumns : : OFFSET ] . toUInt ( & ok , 16 ) ;
if ( ! ok )
{
Console . WriteLn ( " Debugger Breakpoint Model: Failed to parse address '%s', skipping " , fields [ BreakpointModel : : BreakpointColumns : : OFFSET ] . toUtf8 ( ) . constData ( ) ) ;
return ;
}
// Size
mc . end = fields [ BreakpointModel : : BreakpointColumns : : SIZE_LABEL ] . toUInt ( & ok ) + mc . start ;
if ( ! ok )
{
Console . WriteLn ( " Debugger Breakpoint Model: Failed to parse length '%s', skipping " , fields [ BreakpointModel : : BreakpointColumns : : SIZE_LABEL ] . toUtf8 ( ) . constData ( ) ) ;
return ;
}
// Result
const int result = fields [ BreakpointModel : : BreakpointColumns : : ENABLED ] . toUInt ( & ok ) ;
if ( ! ok )
{
Console . WriteLn ( " Debugger Breakpoint Model: Failed to parse result flag '%s', skipping " , fields [ BreakpointModel : : BreakpointColumns : : ENABLED ] . toUtf8 ( ) . constData ( ) ) ;
return ;
}
mc . result = static_cast < MemCheckResult > ( result ) ;
insertBreakpointRows ( 0 , 1 , { mc } ) ;
}
}
void BreakpointModel : : clear ( )
{
beginResetModel ( ) ;
m_breakpoints . clear ( ) ;
endResetModel ( ) ;
}