2020-12-05 13:08:24 +01:00
# include "debugger_list.h"
2020-02-22 20:42:49 +01:00
# include "gui_settings.h"
2021-01-22 09:11:54 +01:00
# include "qt_utils.h"
2020-02-22 20:42:49 +01:00
# include "breakpoint_handler.h"
2018-03-02 22:40:29 +01:00
# include "Emu/Cell/SPUThread.h"
2020-02-22 20:42:49 +01:00
# include "Emu/Cell/PPUThread.h"
# include "Emu/CPU/CPUDisAsm.h"
# include "Emu/CPU/CPUThread.h"
2021-01-22 09:11:54 +01:00
# include "Emu/RSX/RSXDisAsm.h"
2022-03-25 16:17:25 +01:00
# include "Emu/RSX/RSXThread.h"
2018-03-02 22:40:29 +01:00
# include "Emu/System.h"
# include <QMouseEvent>
# include <QWheelEvent>
2021-01-22 09:11:54 +01:00
# include <QVBoxLayout>
# include <QLabel>
2018-03-02 22:40:29 +01:00
# include <memory>
constexpr auto qstr = QString : : fromStdString ;
2021-04-07 23:05:18 +02:00
debugger_list : : debugger_list ( QWidget * parent , std : : shared_ptr < gui_settings > gui_settings , breakpoint_handler * handler )
2020-02-21 13:20:10 +01:00
: QListWidget ( parent )
2021-04-07 23:05:18 +02:00
, m_gui_settings ( std : : move ( gui_settings ) )
2021-10-15 01:26:51 +02:00
, m_ppu_breakpoint_handler ( handler )
2018-03-02 22:40:29 +01:00
{
setWindowTitle ( tr ( " ASM " ) ) ;
2022-05-13 18:11:05 +02:00
2018-03-02 22:40:29 +01:00
for ( uint i = 0 ; i < m_item_count ; + + i )
{
insertItem ( i , new QListWidgetItem ( " " ) ) ;
}
2022-05-13 18:11:05 +02:00
2018-03-02 22:40:29 +01:00
setSizeAdjustPolicy ( QListWidget : : AdjustToContents ) ;
2022-05-13 18:11:05 +02:00
setVerticalScrollBarPolicy ( Qt : : ScrollBarAlwaysOff ) ;
2022-07-29 17:58:38 +02:00
connect ( this , & QListWidget : : currentRowChanged , this , [ this ] ( int row )
{
if ( row < 0 )
{
m_selected_instruction = - 1 ;
m_showing_selected_instruction = false ;
return ;
}
u32 pc = m_start_addr ;
2024-09-06 13:59:44 +02:00
const auto cpu = m_disasm & & ! Emu . IsStopped ( ) ? m_disasm - > get_cpu ( ) : nullptr ;
2024-08-21 18:41:55 +02:00
for ( ; cpu & & cpu - > get_class ( ) = = thread_class : : rsx & & row ; row - - )
2022-07-29 17:58:38 +02:00
{
// If scrolling forwards (downwards), we can skip entire commands
pc + = std : : max < u32 > ( m_disasm - > disasm ( pc ) , 4 ) ;
}
m_selected_instruction = pc + row * 4 ;
} ) ;
2018-03-02 22:40:29 +01:00
}
2024-08-21 18:41:55 +02:00
void debugger_list : : UpdateCPUData ( std : : shared_ptr < CPUDisAsm > disasm )
2018-03-02 22:40:29 +01:00
{
2024-08-21 18:41:55 +02:00
if ( ( ! m_disasm ) ! = ( ! disasm ) | | ( m_disasm & & disasm - > get_cpu ( ) ! = m_disasm - > get_cpu ( ) ) )
2022-05-01 14:48:37 +02:00
{
m_selected_instruction = - 1 ;
2022-07-29 17:58:38 +02:00
m_showing_selected_instruction = false ;
2022-05-01 14:48:37 +02:00
}
2024-08-21 18:41:55 +02:00
m_disasm = std : : move ( disasm ) ;
2018-03-02 22:40:29 +01:00
}
2022-07-29 17:58:38 +02:00
u32 debugger_list : : GetStartAddress ( u32 address )
2018-03-02 22:40:29 +01:00
{
2024-09-06 13:59:44 +02:00
const auto cpu = m_disasm & & ! Emu . IsStopped ( ) ? m_disasm - > get_cpu ( ) : nullptr ;
2024-08-21 18:41:55 +02:00
2022-07-29 17:58:38 +02:00
const u32 steps = m_item_count / 3 ;
2023-08-31 10:35:23 +02:00
const u32 inst_count_jump_on_step = std : : min < u32 > ( steps , 4 ) ;
2022-07-29 17:58:38 +02:00
2024-08-17 12:24:29 +02:00
const bool is_spu = IsSpu ( ) ;
2023-08-31 10:35:23 +02:00
const u32 address_mask = ( is_spu ? 0x3fffc : ~ 3 ) ;
u32 result = address & address_mask ;
2022-07-29 17:58:38 +02:00
2024-08-21 18:41:55 +02:00
if ( cpu & & cpu - > get_class ( ) = = thread_class : : rsx )
2022-07-29 17:58:38 +02:00
{
2024-08-21 18:41:55 +02:00
if ( auto [ count , res ] = static_cast < rsx : : thread * > ( cpu ) - > try_get_pc_of_x_cmds_backwards ( steps , address ) ; count = = steps )
2022-07-29 17:58:38 +02:00
{
result = res ;
}
}
else
{
2023-08-31 10:35:23 +02:00
result = ( address - ( steps * 4 ) ) & address_mask ;
}
u32 upper_bound = ( m_start_addr + ( steps * 4 ) ) & address_mask ;
2024-08-21 18:41:55 +02:00
if ( cpu & & cpu - > get_class ( ) = = thread_class : : rsx )
2023-08-31 10:35:23 +02:00
{
2024-08-21 18:41:55 +02:00
if ( auto [ count , res ] = static_cast < rsx : : thread * > ( cpu ) - > try_get_pc_of_x_cmds_backwards ( 0 - steps , m_start_addr ) ; count = = steps )
2023-08-31 10:35:23 +02:00
{
upper_bound = res ;
}
}
bool goto_addr = false ;
if ( upper_bound > m_start_addr )
{
goto_addr = address < m_start_addr | | address > = upper_bound ;
}
else
{
// Overflowing bounds case
goto_addr = address < m_start_addr & & address > = upper_bound ;
2022-07-29 17:58:38 +02:00
}
2023-08-31 10:35:23 +02:00
if ( goto_addr )
2022-07-29 17:58:38 +02:00
{
m_pc = address ;
2023-08-31 10:35:23 +02:00
if ( address > upper_bound & & address - upper_bound < inst_count_jump_on_step * 4 )
{
m_start_addr = result + inst_count_jump_on_step * 4 ;
}
else
{
m_start_addr = result ;
}
2022-07-29 17:58:38 +02:00
}
return m_start_addr ;
2018-03-02 22:40:29 +01:00
}
2024-08-17 12:24:29 +02:00
bool debugger_list : : IsSpu ( ) const
{
2024-09-06 13:59:44 +02:00
const auto cpu = m_disasm & & ! Emu . IsStopped ( ) ? m_disasm - > get_cpu ( ) : nullptr ;
2024-08-21 18:41:55 +02:00
return ( cpu & & cpu - > get_class ( ) = = thread_class : : spu ) | | ( m_disasm & & ! cpu ) ;
2024-08-17 12:24:29 +02:00
}
2022-07-29 17:58:38 +02:00
void debugger_list : : ShowAddress ( u32 addr , bool select_addr , bool direct )
2018-03-02 22:40:29 +01:00
{
2024-09-06 13:59:44 +02:00
const auto cpu = m_disasm & & ! Emu . IsStopped ( ) ? m_disasm - > get_cpu ( ) : nullptr ;
2024-08-21 18:41:55 +02:00
2022-09-13 15:08:55 +02:00
const decltype ( spu_thread : : local_breakpoints ) * spu_bps_list { } ;
2021-10-15 01:26:51 +02:00
2024-08-21 18:41:55 +02:00
if ( cpu & & cpu - > get_class ( ) = = thread_class : : spu )
2021-10-15 01:26:51 +02:00
{
2024-08-21 18:41:55 +02:00
spu_bps_list = & static_cast < spu_thread * > ( cpu ) - > local_breakpoints ;
2021-10-15 01:26:51 +02:00
}
auto IsBreakpoint = [ & ] ( u32 pc )
2018-03-02 22:40:29 +01:00
{
2024-08-21 18:41:55 +02:00
switch ( cpu ? cpu - > get_class ( ) : thread_class : : general )
2021-10-15 01:26:51 +02:00
{
2024-05-16 01:28:58 +02:00
case thread_class : : ppu :
2024-04-12 15:06:56 +02:00
{
return m_ppu_breakpoint_handler - > HasBreakpoint ( pc ) ;
}
2024-05-16 01:28:58 +02:00
case thread_class : : spu :
2024-04-12 15:06:56 +02:00
{
const u32 pos_at = pc / 4 ;
const u32 pos_bit = 1u < < ( pos_at % 8 ) ;
2024-04-12 20:47:29 +02:00
return ! ! ( ( * spu_bps_list ) [ pos_at / 8 ] & pos_bit ) ;
2024-04-12 15:06:56 +02:00
}
2021-10-15 01:26:51 +02:00
default : return false ;
}
2018-03-02 22:40:29 +01:00
} ;
2022-07-29 17:58:38 +02:00
if ( select_addr | | direct )
2021-01-22 09:11:54 +01:00
{
2022-09-13 15:08:55 +02:00
// The user wants to survey a specific memory location, do not interfere from this point forth
2022-05-01 14:04:56 +02:00
m_follow_thread = false ;
2021-01-22 09:11:54 +01:00
}
2022-09-20 09:19:35 +02:00
m_dirty_flag = false ;
2022-07-29 17:58:38 +02:00
u32 pc = m_start_addr ;
if ( ! direct & & ( m_follow_thread | | select_addr ) )
2018-03-02 22:40:29 +01:00
{
2022-07-29 17:58:38 +02:00
pc = GetStartAddress ( addr ) ;
2018-03-02 22:40:29 +01:00
}
2021-03-23 20:39:39 +01:00
const auto & default_foreground = palette ( ) . color ( foregroundRole ( ) ) ;
const auto & default_background = palette ( ) . color ( backgroundRole ( ) ) ;
2020-06-13 22:17:51 +02:00
2022-07-29 17:58:38 +02:00
m_showing_selected_instruction = false ;
2022-05-01 14:48:37 +02:00
if ( select_addr )
{
m_selected_instruction = addr ;
}
for ( uint i = 0 ; i < m_item_count ; + + i )
{
if ( auto list_item = item ( i ) ; list_item - > isSelected ( ) )
{
list_item - > setSelected ( false ) ;
}
}
2024-08-21 18:41:55 +02:00
if ( ! m_disasm | | ( cpu & & cpu - > state . all_of ( cpu_flag : : exit + cpu_flag : : wait ) ) )
2018-03-02 22:40:29 +01:00
{
2020-06-13 22:37:56 +02:00
for ( uint i = 0 ; i < m_item_count ; + + i )
2018-03-02 22:40:29 +01:00
{
2021-03-23 20:39:39 +01:00
QListWidgetItem * list_item = item ( i ) ;
list_item - > setText ( qstr ( fmt : : format ( " [%08x] ?? ?? ?? ??: " , 0 ) ) ) ;
list_item - > setForeground ( default_foreground ) ;
list_item - > setBackground ( default_background ) ;
2018-03-02 22:40:29 +01:00
}
}
else
{
2024-08-17 12:24:29 +02:00
const bool is_spu = IsSpu ( ) ;
2020-03-19 06:11:59 +01:00
const u32 address_limits = ( is_spu ? 0x3fffc : ~ 3 ) ;
2024-08-21 18:41:55 +02:00
const u32 current_pc = ( cpu ? cpu - > get_pc ( ) : 0 ) ;
2022-07-29 17:58:38 +02:00
m_start_addr & = address_limits ;
2022-09-13 15:08:55 +02:00
pc = m_start_addr ;
2020-04-01 00:02:24 +02:00
2021-03-23 20:39:39 +01:00
for ( uint i = 0 , count = 4 ; i < m_item_count ; + + i , pc = ( pc + count ) & address_limits )
2018-03-02 22:40:29 +01:00
{
2021-03-23 20:39:39 +01:00
QListWidgetItem * list_item = item ( i ) ;
2022-08-26 21:23:57 +02:00
if ( pc = = current_pc )
2020-06-13 22:17:51 +02:00
{
2021-03-23 20:39:39 +01:00
list_item - > setForeground ( m_text_color_pc ) ;
list_item - > setBackground ( m_color_pc ) ;
2020-06-13 22:17:51 +02:00
}
2022-05-01 14:48:37 +02:00
else if ( pc = = m_selected_instruction )
2022-05-01 14:04:56 +02:00
{
2022-05-01 14:48:37 +02:00
// setSelected may invoke a resize event which causes stack overflow, terminate recursion
if ( ! list_item - > isSelected ( ) )
{
list_item - > setSelected ( true ) ;
}
2022-07-29 17:58:38 +02:00
m_showing_selected_instruction = true ;
2022-05-01 14:04:56 +02:00
}
2020-06-13 22:17:51 +02:00
else if ( IsBreakpoint ( pc ) )
{
2021-03-23 20:39:39 +01:00
list_item - > setForeground ( m_text_color_bp ) ;
list_item - > setBackground ( m_color_bp ) ;
2020-06-13 22:17:51 +02:00
}
else
{
2021-03-23 20:39:39 +01:00
list_item - > setForeground ( default_foreground ) ;
list_item - > setBackground ( default_background ) ;
2020-06-13 22:17:51 +02:00
}
2024-08-21 18:41:55 +02:00
if ( cpu & & cpu - > get_class ( ) = = thread_class : : ppu & & ! vm : : check_addr ( pc , 0 ) )
2018-03-02 22:40:29 +01:00
{
2021-03-23 20:39:39 +01:00
list_item - > setText ( ( IsBreakpoint ( pc ) ? " >> " : " " ) + qstr ( fmt : : format ( " [%08x] ?? ?? ?? ??: " , pc ) ) ) ;
2018-03-02 22:40:29 +01:00
count = 4 ;
continue ;
}
2024-08-21 18:41:55 +02:00
if ( cpu & & cpu - > get_class ( ) = = thread_class : : ppu & & ! vm : : check_addr ( pc , vm : : page_executable ) )
2020-05-22 03:48:10 +02:00
{
2020-07-17 10:18:04 +02:00
const u32 data = * vm : : get_super_ptr < atomic_be_t < u32 > > ( pc ) ;
2021-03-23 20:39:39 +01:00
list_item - > setText ( ( IsBreakpoint ( pc ) ? " >> " : " " ) + qstr ( fmt : : format ( " [%08x] %02x %02x %02x %02x: " , pc ,
2020-05-22 03:48:10 +02:00
static_cast < u8 > ( data > > 24 ) ,
static_cast < u8 > ( data > > 16 ) ,
static_cast < u8 > ( data > > 8 ) ,
static_cast < u8 > ( data > > 0 ) ) ) ) ;
count = 4 ;
continue ;
}
2020-12-16 07:53:59 +01:00
count = m_disasm - > disasm ( pc ) ;
2018-03-02 22:40:29 +01:00
2021-01-22 09:11:54 +01:00
if ( ! count )
{
2021-03-23 20:39:39 +01:00
list_item - > setText ( ( IsBreakpoint ( pc ) ? " >> " : " " ) + qstr ( fmt : : format ( " [%08x] ??? ?? ?? " , pc ) ) ) ;
2021-01-22 09:11:54 +01:00
count = 4 ;
continue ;
}
2021-03-23 20:39:39 +01:00
list_item - > setText ( ( IsBreakpoint ( pc ) ? " >> " : " " ) + qstr ( m_disasm - > last_opcode ) ) ;
2018-03-02 22:40:29 +01:00
}
}
setLineWidth ( - 1 ) ;
}
2022-05-01 14:04:56 +02:00
void debugger_list : : RefreshView ( )
{
const bool old = std : : exchange ( m_follow_thread , false ) ;
ShowAddress ( 0 , false ) ;
m_follow_thread = old ;
}
void debugger_list : : EnableThreadFollowing ( bool enable )
{
m_follow_thread = enable ;
}
2021-01-22 09:11:54 +01:00
void debugger_list : : scroll ( s32 steps )
{
2024-09-06 13:59:44 +02:00
const auto cpu = m_disasm & & ! Emu . IsStopped ( ) ? m_disasm - > get_cpu ( ) : nullptr ;
2024-08-21 18:41:55 +02:00
for ( ; cpu & & cpu - > get_class ( ) = = thread_class : : rsx & & steps > 0 ; steps - - )
2021-01-22 09:11:54 +01:00
{
// If scrolling forwards (downwards), we can skip entire commands
2022-07-29 17:58:38 +02:00
m_start_addr + = std : : max < u32 > ( m_disasm - > disasm ( m_start_addr ) , 4 ) ;
2021-01-22 09:11:54 +01:00
}
2024-08-21 18:41:55 +02:00
if ( cpu & & cpu - > get_class ( ) = = thread_class : : rsx & & steps < 0 )
2022-03-25 16:17:25 +01:00
{
2022-09-13 15:08:55 +02:00
// If scrolling backwards (upwards), try to obtain the start of commands tail
2024-08-21 18:41:55 +02:00
if ( auto [ count , res ] = static_cast < rsx : : thread * > ( cpu ) - > try_get_pc_of_x_cmds_backwards ( - steps , m_start_addr ) ; count = = 0u - steps )
2022-03-25 16:17:25 +01:00
{
steps = 0 ;
2022-07-29 17:58:38 +02:00
m_start_addr = res ;
2022-03-25 16:17:25 +01:00
}
}
2022-05-01 14:04:56 +02:00
EnableThreadFollowing ( false ) ;
2022-07-29 17:58:38 +02:00
m_start_addr + = steps * 4 ;
ShowAddress ( 0 , false , true ) ;
2021-01-22 09:11:54 +01:00
}
2018-03-02 22:40:29 +01:00
void debugger_list : : keyPressEvent ( QKeyEvent * event )
{
2024-09-06 13:59:44 +02:00
const auto cpu = m_disasm & & ! Emu . IsStopped ( ) ? m_disasm - > get_cpu ( ) : nullptr ;
2024-08-21 18:41:55 +02:00
2023-05-30 10:30:44 +02:00
// Always accept event (so it would not bubble upwards, debugger_frame already sees it)
struct accept_event_t
{
QKeyEvent * event ;
~ accept_event_t ( ) noexcept
{
event - > accept ( ) ;
}
} accept_event { event } ;
2020-11-23 18:57:34 +01:00
if ( ! isActiveWindow ( ) )
2018-03-02 22:40:29 +01:00
{
2023-05-28 09:57:15 +02:00
QListWidget : : keyPressEvent ( event ) ;
2018-03-02 22:40:29 +01:00
return ;
}
2023-04-30 04:21:14 +02:00
if ( event - > modifiers ( ) )
{
2023-05-28 09:57:15 +02:00
QListWidget : : keyPressEvent ( event ) ;
2023-04-30 04:21:14 +02:00
return ;
}
2018-03-02 22:40:29 +01:00
switch ( event - > key ( ) )
{
2021-01-22 09:11:54 +01:00
case Qt : : Key_PageUp : scroll ( 0 - m_item_count ) ; return ;
case Qt : : Key_PageDown : scroll ( m_item_count ) ; return ;
2023-08-31 14:29:11 +02:00
case Qt : : Key_Up : scroll ( - 1 ) ; return ;
case Qt : : Key_Down : scroll ( 1 ) ; return ;
2021-01-22 09:11:54 +01:00
case Qt : : Key_I :
{
2021-06-12 15:04:33 +02:00
if ( event - > isAutoRepeat ( ) )
{
2023-05-28 09:57:15 +02:00
QListWidget : : keyPressEvent ( event ) ;
2021-06-12 15:04:33 +02:00
return ;
}
2023-05-28 09:57:15 +02:00
2024-08-21 18:41:55 +02:00
if ( cpu & & cpu - > get_class ( ) = = thread_class : : rsx )
2021-01-22 09:11:54 +01:00
{
2022-07-29 17:58:38 +02:00
create_rsx_command_detail ( m_showing_selected_instruction ? m_selected_instruction : m_pc ) ;
2021-01-22 09:11:54 +01:00
return ;
}
2023-05-28 09:57:15 +02:00
break ;
2021-01-22 09:11:54 +01:00
}
2018-03-02 22:40:29 +01:00
default : break ;
}
2023-05-28 09:57:15 +02:00
QListWidget : : keyPressEvent ( event ) ;
2018-03-02 22:40:29 +01:00
}
2021-01-22 09:11:54 +01:00
void debugger_list : : showEvent ( QShowEvent * event )
{
if ( m_cmd_detail ) m_cmd_detail - > show ( ) ;
QListWidget : : showEvent ( event ) ;
}
void debugger_list : : hideEvent ( QHideEvent * event )
{
if ( m_cmd_detail ) m_cmd_detail - > hide ( ) ;
QListWidget : : hideEvent ( event ) ;
}
2022-07-29 17:58:38 +02:00
void debugger_list : : create_rsx_command_detail ( u32 pc )
2021-01-22 09:11:54 +01:00
{
2024-08-21 18:41:55 +02:00
RSXDisAsm rsx_dis = static_cast < RSXDisAsm & > ( * m_disasm ) ;
2021-10-12 22:12:30 +02:00
rsx_dis . change_mode ( cpu_disasm_mode : : list ) ;
2021-01-22 09:11:54 +01:00
// Either invalid or not a method
if ( rsx_dis . disasm ( pc ) < = 4 ) return ;
if ( m_cmd_detail )
{
// Edit the existing dialog
m_detail_label - > setText ( QString : : fromStdString ( rsx_dis . last_opcode ) ) ;
m_cmd_detail - > setFixedSize ( m_cmd_detail - > sizeHint ( ) ) ;
return ;
}
m_cmd_detail = new QDialog ( this ) ;
m_cmd_detail - > setWindowTitle ( tr ( " RSX Command Detail " ) ) ;
m_detail_label = new QLabel ( QString : : fromStdString ( rsx_dis . last_opcode ) , this ) ;
m_detail_label - > setFont ( font ( ) ) ;
gui : : utils : : set_font_size ( * m_detail_label , 10 ) ;
m_detail_label - > setTextInteractionFlags ( Qt : : TextSelectableByMouse | Qt : : TextSelectableByKeyboard ) ;
QVBoxLayout * layout = new QVBoxLayout ( this ) ;
layout - > addWidget ( m_detail_label ) ;
m_cmd_detail - > setLayout ( layout ) ;
m_cmd_detail - > setFixedSize ( m_cmd_detail - > sizeHint ( ) ) ;
m_cmd_detail - > show ( ) ;
connect ( m_cmd_detail , & QDialog : : finished , [ this ] ( int )
{
// Cleanup
std : : exchange ( m_cmd_detail , nullptr ) - > deleteLater ( ) ;
} ) ;
}
2018-03-02 22:40:29 +01:00
void debugger_list : : mouseDoubleClickEvent ( QMouseEvent * event )
{
2020-12-16 15:44:41 +01:00
if ( event - > button ( ) = = Qt : : LeftButton )
2018-03-02 22:40:29 +01:00
{
2022-07-29 17:58:38 +02:00
int i = currentRow ( ) ;
2018-03-02 22:40:29 +01:00
if ( i < 0 ) return ;
2022-07-29 17:58:38 +02:00
u32 pc = m_start_addr ;
2024-09-06 13:59:44 +02:00
const auto cpu = m_disasm & & ! Emu . IsStopped ( ) ? m_disasm - > get_cpu ( ) : nullptr ;
2024-08-21 18:41:55 +02:00
for ( ; cpu & & cpu - > get_class ( ) = = thread_class : : rsx & & i ; i - - )
2022-07-29 17:58:38 +02:00
{
// If scrolling forwards (downwards), we can skip entire commands
pc + = std : : max < u32 > ( m_disasm - > disasm ( pc ) , 4 ) ;
}
pc + = i * 4 ;
m_selected_instruction = pc ;
2018-03-02 22:40:29 +01:00
// Let debugger_frame know about breakpoint.
// Other option is to add to breakpoint manager directly and have a signal there instead.
// Either the flow goes from debugger_list->breakpoint_manager->debugger_frame, or it goes debugger_list->debugger_frame, and I felt this was easier to read for now.
Q_EMIT BreakpointRequested ( pc ) ;
}
}
void debugger_list : : wheelEvent ( QWheelEvent * event )
{
2021-03-23 20:39:39 +01:00
const QPoint numSteps = event - > angleDelta ( ) / 8 / 15 ; // http://doc.qt.io/qt-5/qwheelevent.html#pixelDelta
2018-03-02 22:40:29 +01:00
const int value = numSteps . y ( ) ;
2020-04-01 00:02:24 +02:00
const auto direction = ( event - > modifiers ( ) = = Qt : : ControlModifier ) ;
2018-03-02 22:40:29 +01:00
2021-01-22 09:11:54 +01:00
scroll ( direction ? value : - value ) ;
2018-03-02 22:40:29 +01:00
}
void debugger_list : : resizeEvent ( QResizeEvent * event )
{
2022-05-13 18:11:05 +02:00
QListWidget : : resizeEvent ( event ) ;
2018-03-02 22:40:29 +01:00
if ( count ( ) < 1 | | visualItemRect ( item ( 0 ) ) . height ( ) < 1 )
{
return ;
}
2022-05-13 17:20:57 +02:00
const u32 old_size = m_item_count ;
2018-03-02 22:40:29 +01:00
2022-09-13 15:08:55 +02:00
// It is fine if the QWidgetList is a tad bit larger than the frame
2022-05-13 18:11:05 +02:00
m_item_count = utils : : aligned_div < u32 > ( rect ( ) . height ( ) - frameWidth ( ) * 2 , visualItemRect ( item ( 0 ) ) . height ( ) ) ;
2018-03-02 22:40:29 +01:00
2022-05-13 17:20:57 +02:00
if ( old_size < = m_item_count )
{
for ( u32 i = old_size ; i < m_item_count ; + + i )
{
insertItem ( i , new QListWidgetItem ( " " ) ) ;
2022-09-20 09:19:35 +02:00
m_dirty_flag = true ;
2022-05-13 17:20:57 +02:00
}
}
else
{
for ( u32 i = old_size - 1 ; i > = m_item_count ; - - i )
{
delete takeItem ( i ) ;
}
}
2018-03-02 22:40:29 +01:00
}