Skip to content

Commit

Permalink
Add options to copy pointer addresses (or base address) of a watch en…
Browse files Browse the repository at this point in the history
…try (#167)

* feat: Added right click menu to copy pointer address in Edit Address widget

Added a right click menu to m_pointerWidget which activates only if an address label is right clicked. It provides a single option (Copy address) which copies the address from that pointer level to clipboard.

Added an option (copy address) to the right click menu of a MemWatchWidget. Selecting Copy address on a pointer watch can copy the address at any pointer level to the clipboard. Selecting Copy address on a non-pointer watch will copy the base address of the watch to the clipboard.

Instead of finding the QLabel for the address when the pointer widget is clicked, the context menu is now registered to each pointer address label in the pointer widget. A property is also set (addr) which contains the numeric address at that pointer level. If addr is zero, the Copy Address is not enabled. Otherwise it is converted to a hex string which is copied to the clipboard if Copy Address is selected.
  • Loading branch information
jahorta authored Jul 17, 2024
1 parent 8e49bae commit a7cb085
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 1 deletion.
36 changes: 35 additions & 1 deletion Source/GUI/MemWatcher/Dialogs/DlgAddWatchEntry.cpp
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
#include "DlgAddWatchEntry.h"

#include <QApplication>
#include <QClipboard>
#include <QDialogButtonBox>
#include <QFontDatabase>
#include <QFormLayout>
#include <QHBoxLayout>
#include <QMenu>
#include <QMessageBox>
#include <QVBoxLayout>
#include <sstream>
Expand Down Expand Up @@ -167,6 +170,10 @@ void DlgAddWatchEntry::fillFields(MemWatchEntry* entry)
QLabel* lblAddressOfPath = new QLabel();
lblAddressOfPath->setText(
QString::fromStdString(" -> " + m_entry->getAddressStringForPointerLevel(i + 1)));
lblAddressOfPath->setProperty("addr", m_entry->getAddressForPointerLevel(i + 1));
lblAddressOfPath->setContextMenuPolicy(Qt::CustomContextMenu);
connect(lblAddressOfPath, &QWidget::customContextMenuRequested, this,
&DlgAddWatchEntry::onPointerOffsetContextMenuRequested);
m_addressPath.append(lblAddressOfPath);
m_offsetsLayout->addWidget(lblLevel, i, 0);
m_offsetsLayout->addWidget(txbOffset, i, 1);
Expand All @@ -190,6 +197,12 @@ void DlgAddWatchEntry::addPointerOffset()
QLineEdit* txbOffset = new QLineEdit();
m_offsets.append(txbOffset);
QLabel* lblAddressOfPath = new QLabel(" -> ");
lblAddressOfPath->setText(
QString::fromStdString(" -> " + m_entry->getAddressStringForPointerLevel(level + 1)));
lblAddressOfPath->setProperty("addr", m_entry->getAddressForPointerLevel(level + 1));
lblAddressOfPath->setContextMenuPolicy(Qt::CustomContextMenu);
connect(lblAddressOfPath, &QWidget::customContextMenuRequested, this,
&DlgAddWatchEntry::onPointerOffsetContextMenuRequested);
m_addressPath.append(lblAddressOfPath);
m_offsetsLayout->addWidget(lblLevel, level, 0);
m_offsetsLayout->addWidget(txbOffset, level, 1);
Expand Down Expand Up @@ -385,9 +398,10 @@ void DlgAddWatchEntry::updatePreview()
for (int i = 0; i < level; ++i)
{
QLabel* lblAddressOfPath =
static_cast<QLabel*>(m_offsetsLayout->itemAtPosition(i, 2)->widget());
qobject_cast<QLabel*>(m_offsetsLayout->itemAtPosition(i, 2)->widget());
lblAddressOfPath->setText(
QString::fromStdString(" -> " + m_entry->getAddressStringForPointerLevel(i + 1)));
lblAddressOfPath->setProperty("addr", m_entry->getAddressForPointerLevel(i + 1));
}
}
}
Expand Down Expand Up @@ -424,3 +438,23 @@ MemWatchEntry* DlgAddWatchEntry::stealEntry()
m_entry = nullptr;
return entry;
}

void DlgAddWatchEntry::onPointerOffsetContextMenuRequested(const QPoint& pos)
{
QLabel* const lbl = qobject_cast<QLabel*>(sender());

QMenu* const contextMenu = new QMenu(this);
QAction* const copyAddr = new QAction(tr("&Copy Address"), this);

const QString text{QString::number(lbl->property("addr").toUInt(), 16).toUpper()};
connect(copyAddr, &QAction::triggered, this,
[text] { QApplication::clipboard()->setText(text); });
contextMenu->addAction(copyAddr);

if (!lbl->property("addr").toUInt())
{
copyAddr->setEnabled(false);
}

contextMenu->popup(lbl->mapToGlobal(pos));
}
1 change: 1 addition & 0 deletions Source/GUI/MemWatcher/Dialogs/DlgAddWatchEntry.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ class DlgAddWatchEntry : public QDialog
void addPointerOffset();
void removePointerOffset();
void removeAllPointerOffset();
void onPointerOffsetContextMenuRequested(const QPoint& pos);

MemWatchEntry* m_entry{};
AddressInputWidget* m_txbAddress{};
Expand Down
34 changes: 34 additions & 0 deletions Source/GUI/MemWatcher/MemWatchWidget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,40 @@ void MemWatchWidget::onMemWatchContextMenuRequested(const QPoint& pos)
connect(copy, &QAction::triggered, this, [this] { copySelectedWatchesToClipBoard(); });
contextMenu->addAction(copy);

if (index.isValid())
{
MemWatchEntry* const entry = m_watchModel->getEntryFromIndex(index);
if (entry->isBoundToPointer())
{
QMenu* const copyAddrSubmenu = contextMenu->addMenu(tr("Copy add&ress..."));
QAction* const copyPointer = new QAction(tr("Copy &base address..."), this);
const QString addrString{QString::number(entry->getConsoleAddress(), 16).toUpper()};
connect(copyPointer, &QAction::triggered, this,
[addrString] { QApplication::clipboard()->setText(addrString); });
copyAddrSubmenu->addAction(copyPointer);
for (int i = 0; i < static_cast<int>(entry->getPointerLevel()); ++i)
{
if (!entry->getAddressForPointerLevel(i + 1))
break;
QAction* const copyAddrOfPointer =
new QAction(tr("Copy pointed address at &level %1...").arg(i + 1), this);
const QString addrString{
QString::number(entry->getAddressForPointerLevel(i + 1), 16).toUpper()};
connect(copyAddrOfPointer, &QAction::triggered, this,
[addrString] { QApplication::clipboard()->setText(addrString); });
copyAddrSubmenu->addAction(copyAddrOfPointer);
}
}
else
{
QAction* const copyPointer = new QAction(tr("Copy add&ress"), this);
const QString addrString{QString::number(entry->getConsoleAddress(), 16).toUpper()};
connect(copyPointer, &QAction::triggered, this,
[addrString] { QApplication::clipboard()->setText(addrString); });
contextMenu->addAction(copyPointer);
}
}

QAction* paste = new QAction(tr("&Paste"), this);
connect(paste, &QAction::triggered, this, [this, index] { pasteWatchFromClipBoard(index); });
contextMenu->addAction(paste);
Expand Down

0 comments on commit a7cb085

Please sign in to comment.