MemoryViewWidget: Color recently changed memory when auto updating.

This commit is contained in:
TryTwo 2025-01-19 23:24:08 -07:00
parent 6d8f40c245
commit 7b19192134
2 changed files with 91 additions and 5 deletions

View File

@ -8,6 +8,7 @@
#include <QApplication>
#include <QClipboard>
#include <QColorDialog>
#include <QHBoxLayout>
#include <QHeaderView>
#include <QLineEdit>
@ -43,6 +44,7 @@ constexpr int MISC_COLUMNS = 2;
constexpr auto USER_ROLE_IS_ROW_BREAKPOINT_CELL = Qt::UserRole;
constexpr auto USER_ROLE_CELL_ADDRESS = Qt::UserRole + 1;
constexpr auto USER_ROLE_VALUE_TYPE = Qt::UserRole + 2;
constexpr auto USER_ROLE_VALID_ADDRESS = Qt::UserRole + 3;
// Numbers for the scrollbar. These affect how much big the draggable part of the scrollbar is, how
// smooth it scrolls, and how much memory it traverses while dragging.
@ -483,6 +485,10 @@ void MemoryViewWidget::Update()
item_address = row_address + c * GetTypeSize(m_type);
item->setData(USER_ROLE_CELL_ADDRESS, item_address);
// Reset highlighting.
item->setBackground(Qt::transparent);
item->setData(USER_ROLE_VALID_ADDRESS, false);
}
}
@ -521,13 +527,42 @@ void MemoryViewWidget::UpdateColumns()
if (cell_address == m_address_highlight)
cell_item->setSelected(true);
// Color recently changed items.
QColor bcolor = cell_item->background().color();
const bool valid = cell_item->data(USER_ROLE_VALID_ADDRESS).toBool();
// It gets a bit complicated, because invalid addresses becoming valid should not be
// colored.
if (!new_text.has_value())
{
cell_item->setBackground(Qt::transparent);
cell_item->setData(USER_ROLE_VALID_ADDRESS, false);
cell_item->setText(INVALID_MEMORY);
else
}
else if (!valid)
{
// Wasn't valid on last update, is valid now.
cell_item->setData(USER_ROLE_VALID_ADDRESS, true);
cell_item->setText(new_text.value());
}
else if (bcolor.rgb() != m_highlight_color.rgb() && bcolor != Qt::transparent)
{
// Filter out colors that shouldn't change, such as breakpoints.
cell_item->setText(new_text.value());
}
else if (cell_item->text() != new_text.value())
{
// Cell changed, apply highlighting.
cell_item->setBackground(m_highlight_color);
cell_item->setText(new_text.value());
}
else if (bcolor.alpha() > 0)
{
// Fade out highlighting each frame.
bcolor.setAlpha(bcolor.alpha() - 1);
cell_item->setBackground(bcolor);
}
}
}
}
@ -577,11 +612,12 @@ void MemoryViewWidget::GetValues()
}
// May only be called if we have taken on the role of the CPU thread
QString MemoryViewWidget::ValueToString(const Core::CPUThreadGuard& guard, u32 address, Type type)
std::optional<QString> MemoryViewWidget::ValueToString(const Core::CPUThreadGuard& guard,
u32 address, Type type)
{
const AddressSpace::Accessors* accessors = AddressSpace::GetAccessors(m_address_space);
if (!accessors->IsValidAddress(guard, address))
return INVALID_MEMORY;
return std::nullopt;
switch (type)
{
@ -643,7 +679,7 @@ QString MemoryViewWidget::ValueToString(const Core::CPUThreadGuard& guard, u32 a
return string;
}
default:
return INVALID_MEMORY;
return std::nullopt;
}
}
@ -873,6 +909,54 @@ void MemoryViewWidget::SetDisplay(Type type, int bytes_per_row, int alignment, b
UpdateDispatcher(UpdateType::Full);
}
void MemoryViewWidget::ToggleHighlights(bool enabled)
{
// m_highlight_color should hold the current highlight color even when disabled, so it can
// be used if re-enabled. If modifying the enabled alpha, change in .h file as well.
if (enabled)
{
m_highlight_color.setAlpha(100);
}
else
{
// Treated as being interchangable with Qt::transparent.
m_highlight_color.setAlpha(0);
// Immediately remove highlights when paused.
for (int i = 0; i < m_table->rowCount(); i++)
{
for (int c = 0; c < m_data_columns; c++)
m_table->item(i, c + MISC_COLUMNS)->setBackground(m_highlight_color);
}
}
}
void MemoryViewWidget::SetHighlightColor()
{
// Could allow custom alphas to be set, which would change fade-out rate.
QColor color = QColorDialog::getColor(m_highlight_color);
if (!color.isValid())
return;
const bool enabled = m_highlight_color.alpha() != 0;
m_highlight_color = color;
m_highlight_color.setAlpha(enabled ? 100 : 0);
if (!enabled)
return;
// Immediately update colors. Only useful for playing with colors while paused.
for (int i = 0; i < m_table->rowCount(); i++)
{
for (int c = 0; c < m_data_columns; c++)
{
auto* item = m_table->item(i, c + MISC_COLUMNS);
// Get current cell alpha state.
color.setAlpha(item->background().color().alpha());
m_table->item(i, c + MISC_COLUMNS)->setBackground(color);
}
}
}
void MemoryViewWidget::SetBPType(BPType type)
{
m_bp_type = type;

View File

@ -93,6 +93,8 @@ public:
void SetAddressSpace(AddressSpace::Type address_space);
AddressSpace::Type GetAddressSpace() const;
void SetDisplay(Type type, int bytes_per_row, int alignment, bool dual_view);
void ToggleHighlights(bool enabled);
void SetHighlightColor();
void SetBPType(BPType type);
void SetAddress(u32 address);
void SetFocus() const;
@ -112,7 +114,7 @@ private:
void UpdateColumns();
void ScrollbarActionTriggered(int action);
void ScrollbarSliderReleased();
QString ValueToString(const Core::CPUThreadGuard& guard, u32 address, Type type);
std::optional<QString> ValueToString(const Core::CPUThreadGuard& guard, u32 address, Type type);
Core::System& m_system;