Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add tooltip for displaying flag and comment in hexdump (#1471) #2116

Merged
merged 6 commits into from
Apr 4, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions src/core/Cutter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -775,6 +775,16 @@ void CutterCore::delComment(RVA addr)
emit commentsChanged();
}

/**
* @brief Gets the comment present at a specific address
* @param addr The address to be checked
* @return String containing comment
*/
QString CutterCore::getCommentAt(RVA addr)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

docstrings :) Try to not forget to document everything. This was a decision we made not so long ago, and this is why you see a lot of undocumented places in the code. Please pay attention to this :)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, I'll keep that in mind. Yeah, looking at other places in the code, I wasn't sure about what all is supposed to be documented.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

everything :) Every function, and every coding decision that might not be clear for the reader

{
return Core()->cmdRawAt("CC.", addr);
}

void CutterCore::setImmediateBase(const QString &r2BaseName, RVA offset)
{
if (offset == RVA_INVALID) {
Expand Down Expand Up @@ -3465,6 +3475,17 @@ void CutterCore::addFlag(RVA offset, QString name, RVA size)
emit flagsChanged();
}

/**
* @brief Gets all the flags present at a specific address
* @param addr The address to be checked
* @return String containing all the flags which are comma-separated
*/
QString CutterCore::listFlagsAsStringAt(RVA addr)
{
CORE_LOCK();
return r_flag_get_liststr (core->flags, addr);
}

QString CutterCore::nearestFlag(RVA offset, RVA *flagOffsetOut)
{
auto r = cmdj(QString("fdj @") + QString::number(offset)).object();
Expand Down
2 changes: 2 additions & 0 deletions src/core/Cutter.h
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,7 @@ class CutterCore: public QObject
void delFlag(RVA addr);
void delFlag(const QString &name);
void addFlag(RVA offset, QString name, RVA size);
QString listFlagsAsStringAt(RVA addr);
/**
* @brief Get nearest flag at or before offset.
* @param offset search position
Expand Down Expand Up @@ -217,6 +218,7 @@ class CutterCore: public QObject
/* Comments */
void setComment(RVA addr, const QString &cmt);
void delComment(RVA addr);
QString getCommentAt(RVA addr);
void setImmediateBase(const QString &r2BaseName, RVA offset = RVA_INVALID);
void setCurrentBits(int bits, RVA offset = RVA_INVALID);

Expand Down
39 changes: 39 additions & 0 deletions src/widgets/HexWidget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include <QJsonObject>
#include <QJsonArray>
#include <QRegularExpression>
#include <QToolTip>

static constexpr uint64_t MAX_COPY_SIZE = 128 * 1024 * 1024;
static constexpr int MAX_LINE_WIDTH_PRESET = 32;
Expand Down Expand Up @@ -467,6 +468,15 @@ void HexWidget::mouseMoveEvent(QMouseEvent *event)
QPoint pos = event->pos();
pos.rx() += horizontalScrollBar()->value();

auto mouseAddr = mousePosToAddr(pos).address;

QString metaData = getFlagsAndComment(mouseAddr);
if (!metaData.isEmpty() && itemArea.contains(pos)) {
QToolTip::showText(event->globalPos(), metaData.replace(",", ", "), this);
} else {
QToolTip::hideText();
}

if (!updatingSelection) {
if (itemArea.contains(pos) || asciiArea.contains(pos))
setCursor(Qt::IBeamCursor);
Expand Down Expand Up @@ -1010,6 +1020,14 @@ void HexWidget::drawItemArea(QPainter &painter)
for (int j = 0; j < itemColumns; ++j) {
for (int k = 0; k < itemGroupSize && itemAddr <= data->maxIndex(); ++k, itemAddr += itemByteLen) {
itemString = renderItem(itemAddr - startAddress, &itemColor);

if (!getFlagsAndComment(itemAddr).isEmpty()) {
QColor markerColor(borderColor);
markerColor.setAlphaF(0.5);
const auto shape = rangePolygons(itemAddr, itemAddr, false)[0];
painter.setPen(markerColor);
painter.drawPolyline(shape);
}
if (selection.contains(itemAddr) && !cursorOnAscii) {
itemColor = palette().highlightedText().color();
}
Expand Down Expand Up @@ -1454,6 +1472,27 @@ QChar HexWidget::renderAscii(int offset, QColor *color)
return QChar(byte);
}

/**
* @brief Gets the available flags and comment at a specific address.
* @param address Address of Item to be checked.
* @return String containing the flags and comment available at the address.
*/
QString HexWidget::getFlagsAndComment(uint64_t address)
{
QString flagNames = Core()->listFlagsAsStringAt(address);
QString metaData = flagNames.isEmpty() ? "" : "Flags: " + flagNames.trimmed();

QString comment = Core()->getCommentAt(address);
if (!comment.isEmpty()) {
if (!metaData.isEmpty()) {
metaData.append("\n");
}
metaData.append("Comment: " + comment.trimmed());
}

return metaData;
}

void HexWidget::fetchData()
{
data.swap(oldData);
Expand Down
1 change: 1 addition & 0 deletions src/widgets/HexWidget.h
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,7 @@ private slots:
QVariant readItem(int offset, QColor *color = nullptr);
QString renderItem(int offset, QColor *color = nullptr);
QChar renderAscii(int offset, QColor *color = nullptr);
QString getFlagsAndComment(uint64_t address);
/**
* @brief Get the location on which operations such as Writing should apply.
* @return Start of selection if multiple bytes are selected. Otherwise, the curren seek of the widget.
Expand Down