diff --git a/Source/Core/DolphinQt/Debugger/MemoryViewWidget.cpp b/Source/Core/DolphinQt/Debugger/MemoryViewWidget.cpp index 5c2335fd2c..fa92c4e886 100644 --- a/Source/Core/DolphinQt/Debugger/MemoryViewWidget.cpp +++ b/Source/Core/DolphinQt/Debugger/MemoryViewWidget.cpp @@ -28,6 +28,10 @@ // 120; i.e., 120 units * 1/8 = 15 degrees." (http://doc.qt.io/qt-5/qwheelevent.html#angleDelta) constexpr double SCROLL_FRACTION_DEGREES = 15.; +constexpr auto USER_ROLE_IS_ROW_BREAKPOINT_CELL = Qt::UserRole; +constexpr auto USER_ROLE_CELL_ADDRESS = Qt::UserRole + 1; +constexpr auto USER_ROLE_HAS_VALUE = Qt::UserRole + 2; + MemoryViewWidget::MemoryViewWidget(QWidget* parent) : QTableWidget(parent) { horizontalHeader()->hide(); @@ -158,15 +162,19 @@ void MemoryViewWidget::Update() auto* bp_item = new QTableWidgetItem; bp_item->setFlags(Qt::ItemIsEnabled); - bp_item->setData(Qt::UserRole, row_address); + bp_item->setData(USER_ROLE_IS_ROW_BREAKPOINT_CELL, true); + bp_item->setData(USER_ROLE_CELL_ADDRESS, row_address); + bp_item->setData(USER_ROLE_HAS_VALUE, false); setItem(i, 0, bp_item); auto* row_item = new QTableWidgetItem(QStringLiteral("%1").arg(row_address, 8, 16, QLatin1Char('0'))); - row_item->setData(Qt::UserRole, row_address); row_item->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable); + row_item->setData(USER_ROLE_IS_ROW_BREAKPOINT_CELL, false); + row_item->setData(USER_ROLE_CELL_ADDRESS, row_address); + row_item->setData(USER_ROLE_HAS_VALUE, false); setItem(i, 1, row_item); @@ -179,7 +187,9 @@ void MemoryViewWidget::Update() { auto* item = new QTableWidgetItem(QStringLiteral("-")); item->setFlags(Qt::ItemIsEnabled); - item->setData(Qt::UserRole, row_address); + item->setData(USER_ROLE_IS_ROW_BREAKPOINT_CELL, false); + item->setData(USER_ROLE_CELL_ADDRESS, row_address); + item->setData(USER_ROLE_HAS_VALUE, false); setItem(i, c, item); } @@ -245,7 +255,7 @@ void MemoryViewWidget::UpdateColumns(Type type, int first_column) for (int i = 0; i < rowCount(); i++) { - u32 row_address = item(i, 1)->data(Qt::UserRole).toUInt(); + u32 row_address = item(i, 1)->data(USER_ROLE_CELL_ADDRESS).toUInt(); if (!accessors->IsValidAddress(row_address)) continue; @@ -263,13 +273,17 @@ void MemoryViewWidget::UpdateColumns(Type type, int first_column) if (accessors->IsValidAddress(cell_address)) { cell_item->setText(value_to_string(cell_address)); - cell_item->setData(Qt::UserRole, cell_address); + cell_item->setData(USER_ROLE_IS_ROW_BREAKPOINT_CELL, false); + cell_item->setData(USER_ROLE_CELL_ADDRESS, cell_address); + cell_item->setData(USER_ROLE_HAS_VALUE, true); } else { cell_item->setFlags({}); cell_item->setText(QStringLiteral("-")); - cell_item->setData(Qt::UserRole, cell_address); + cell_item->setData(USER_ROLE_IS_ROW_BREAKPOINT_CELL, false); + cell_item->setData(USER_ROLE_CELL_ADDRESS, cell_address); + cell_item->setData(USER_ROLE_HAS_VALUE, false); } } }; @@ -371,7 +385,7 @@ void MemoryViewWidget::UpdateBreakpointTags() { // Pull address from cell itself, helpful for dual column view. auto cell = item(i, c); - u32 address = cell->data(Qt::UserRole).toUInt(); + u32 address = cell->data(USER_ROLE_CELL_ADDRESS).toUInt(); if (address == 0) { @@ -539,7 +553,7 @@ void MemoryViewWidget::mousePressEvent(QMouseEvent* event) if (item_selected == nullptr) return; - const u32 address = item(row(item_selected), 1)->data(Qt::UserRole).toUInt(); + const u32 address = item(row(item_selected), 1)->data(USER_ROLE_CELL_ADDRESS).toUInt(); switch (event->button()) { @@ -576,12 +590,13 @@ void MemoryViewWidget::OnContextMenu(const QPoint& pos) { auto* item_selected = itemAt(pos); - // we don't have a meaningful context menu to show for when the user right-clicks free space in - // the table - if (!item_selected) + // We don't have a meaningful context menu to show for when the user right-clicks either free + // space in the table or the row breakpoint cell. + if (!item_selected || item_selected->data(USER_ROLE_IS_ROW_BREAKPOINT_CELL).toBool()) return; - const u32 addr = item_selected->data(Qt::UserRole).toUInt(); + const bool item_has_value = item_selected->data(USER_ROLE_HAS_VALUE).toBool(); + const u32 addr = item_selected->data(USER_ROLE_CELL_ADDRESS).toUInt(); auto* menu = new QMenu(this); @@ -590,9 +605,17 @@ void MemoryViewWidget::OnContextMenu(const QPoint& pos) auto* copy_hex = menu->addAction(tr("Copy Hex"), this, [this, addr] { OnCopyHex(addr); }); const AddressSpace::Accessors* accessors = AddressSpace::GetAccessors(m_address_space); - copy_hex->setEnabled(Core::GetState() != Core::State::Uninitialized && + copy_hex->setEnabled(item_has_value && Core::GetState() != Core::State::Uninitialized && accessors->IsValidAddress(addr)); + auto* copy_value = menu->addAction(tr("Copy Value"), this, [this, &pos] { + // Re-fetch the item in case the underlying table has refreshed since the menu was opened. + auto* item = itemAt(pos); + if (item && item->data(USER_ROLE_HAS_VALUE).toBool()) + QApplication::clipboard()->setText(item->text()); + }); + copy_value->setEnabled(item_has_value); + menu->addSeparator(); menu->addAction(tr("Show in code"), this, [this, addr] { emit ShowCode(addr); });