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 <QApplication>
#include <QClipboard> #include <QClipboard>
#include <QColorDialog>
#include <QHBoxLayout> #include <QHBoxLayout>
#include <QHeaderView> #include <QHeaderView>
#include <QLineEdit> #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_IS_ROW_BREAKPOINT_CELL = Qt::UserRole;
constexpr auto USER_ROLE_CELL_ADDRESS = Qt::UserRole + 1; constexpr auto USER_ROLE_CELL_ADDRESS = Qt::UserRole + 1;
constexpr auto USER_ROLE_VALUE_TYPE = Qt::UserRole + 2; 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 // 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. // 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_address = row_address + c * GetTypeSize(m_type);
item->setData(USER_ROLE_CELL_ADDRESS, item_address); 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) if (cell_address == m_address_highlight)
cell_item->setSelected(true); 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 // It gets a bit complicated, because invalid addresses becoming valid should not be
// colored. // colored.
if (!new_text.has_value()) if (!new_text.has_value())
{
cell_item->setBackground(Qt::transparent);
cell_item->setData(USER_ROLE_VALID_ADDRESS, false);
cell_item->setText(INVALID_MEMORY); 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()); 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 // 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); const AddressSpace::Accessors* accessors = AddressSpace::GetAccessors(m_address_space);
if (!accessors->IsValidAddress(guard, address)) if (!accessors->IsValidAddress(guard, address))
return INVALID_MEMORY; return std::nullopt;
switch (type) switch (type)
{ {
@ -643,7 +679,7 @@ QString MemoryViewWidget::ValueToString(const Core::CPUThreadGuard& guard, u32 a
return string; return string;
} }
default: 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); 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) void MemoryViewWidget::SetBPType(BPType type)
{ {
m_bp_type = type; m_bp_type = type;

View File

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