From 7b191921348c3689488c5559c1a0f8e6111751e0 Mon Sep 17 00:00:00 2001 From: TryTwo Date: Sun, 19 Jan 2025 23:24:08 -0700 Subject: [PATCH] MemoryViewWidget: Color recently changed memory when auto updating. --- .../DolphinQt/Debugger/MemoryViewWidget.cpp | 92 ++++++++++++++++++- .../DolphinQt/Debugger/MemoryViewWidget.h | 4 +- 2 files changed, 91 insertions(+), 5 deletions(-) diff --git a/Source/Core/DolphinQt/Debugger/MemoryViewWidget.cpp b/Source/Core/DolphinQt/Debugger/MemoryViewWidget.cpp index 9928632273..9f5bd628ff 100644 --- a/Source/Core/DolphinQt/Debugger/MemoryViewWidget.cpp +++ b/Source/Core/DolphinQt/Debugger/MemoryViewWidget.cpp @@ -8,6 +8,7 @@ #include #include +#include #include #include #include @@ -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,12 +527,41 @@ 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 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; diff --git a/Source/Core/DolphinQt/Debugger/MemoryViewWidget.h b/Source/Core/DolphinQt/Debugger/MemoryViewWidget.h index a1e2af09ea..29d006f7db 100644 --- a/Source/Core/DolphinQt/Debugger/MemoryViewWidget.h +++ b/Source/Core/DolphinQt/Debugger/MemoryViewWidget.h @@ -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 ValueToString(const Core::CPUThreadGuard& guard, u32 address, Type type); Core::System& m_system;