Qt/MemoryViewWidget: Add option to copy the actually displayed cell value to clipboard.
This commit is contained in:
parent
54ec0bd0d0
commit
6920a24f1d
|
@ -28,6 +28,10 @@
|
||||||
// 120; i.e., 120 units * 1/8 = 15 degrees." (http://doc.qt.io/qt-5/qwheelevent.html#angleDelta)
|
// 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 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)
|
MemoryViewWidget::MemoryViewWidget(QWidget* parent) : QTableWidget(parent)
|
||||||
{
|
{
|
||||||
horizontalHeader()->hide();
|
horizontalHeader()->hide();
|
||||||
|
@ -158,15 +162,19 @@ void MemoryViewWidget::Update()
|
||||||
|
|
||||||
auto* bp_item = new QTableWidgetItem;
|
auto* bp_item = new QTableWidgetItem;
|
||||||
bp_item->setFlags(Qt::ItemIsEnabled);
|
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);
|
setItem(i, 0, bp_item);
|
||||||
|
|
||||||
auto* row_item =
|
auto* row_item =
|
||||||
new QTableWidgetItem(QStringLiteral("%1").arg(row_address, 8, 16, QLatin1Char('0')));
|
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->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);
|
setItem(i, 1, row_item);
|
||||||
|
|
||||||
|
@ -179,7 +187,9 @@ void MemoryViewWidget::Update()
|
||||||
{
|
{
|
||||||
auto* item = new QTableWidgetItem(QStringLiteral("-"));
|
auto* item = new QTableWidgetItem(QStringLiteral("-"));
|
||||||
item->setFlags(Qt::ItemIsEnabled);
|
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);
|
setItem(i, c, item);
|
||||||
}
|
}
|
||||||
|
@ -245,7 +255,7 @@ void MemoryViewWidget::UpdateColumns(Type type, int first_column)
|
||||||
|
|
||||||
for (int i = 0; i < rowCount(); i++)
|
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))
|
if (!accessors->IsValidAddress(row_address))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
@ -263,13 +273,17 @@ void MemoryViewWidget::UpdateColumns(Type type, int first_column)
|
||||||
if (accessors->IsValidAddress(cell_address))
|
if (accessors->IsValidAddress(cell_address))
|
||||||
{
|
{
|
||||||
cell_item->setText(value_to_string(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
|
else
|
||||||
{
|
{
|
||||||
cell_item->setFlags({});
|
cell_item->setFlags({});
|
||||||
cell_item->setText(QStringLiteral("-"));
|
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.
|
// Pull address from cell itself, helpful for dual column view.
|
||||||
auto cell = item(i, c);
|
auto cell = item(i, c);
|
||||||
u32 address = cell->data(Qt::UserRole).toUInt();
|
u32 address = cell->data(USER_ROLE_CELL_ADDRESS).toUInt();
|
||||||
|
|
||||||
if (address == 0)
|
if (address == 0)
|
||||||
{
|
{
|
||||||
|
@ -539,7 +553,7 @@ void MemoryViewWidget::mousePressEvent(QMouseEvent* event)
|
||||||
if (item_selected == nullptr)
|
if (item_selected == nullptr)
|
||||||
return;
|
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())
|
switch (event->button())
|
||||||
{
|
{
|
||||||
|
@ -576,12 +590,13 @@ void MemoryViewWidget::OnContextMenu(const QPoint& pos)
|
||||||
{
|
{
|
||||||
auto* item_selected = itemAt(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
|
// We don't have a meaningful context menu to show for when the user right-clicks either free
|
||||||
// the table
|
// space in the table or the row breakpoint cell.
|
||||||
if (!item_selected)
|
if (!item_selected || item_selected->data(USER_ROLE_IS_ROW_BREAKPOINT_CELL).toBool())
|
||||||
return;
|
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);
|
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); });
|
auto* copy_hex = menu->addAction(tr("Copy Hex"), this, [this, addr] { OnCopyHex(addr); });
|
||||||
|
|
||||||
const AddressSpace::Accessors* accessors = AddressSpace::GetAccessors(m_address_space);
|
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));
|
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->addSeparator();
|
||||||
|
|
||||||
menu->addAction(tr("Show in code"), this, [this, addr] { emit ShowCode(addr); });
|
menu->addAction(tr("Show in code"), this, [this, addr] { emit ShowCode(addr); });
|
||||||
|
|
Loading…
Reference in New Issue