ToolTip for cropped lines in Graph, Fix #227

This commit is contained in:
Florian Märkl 2017-12-19 17:59:39 +01:00
parent 41430d2826
commit 2522e6a378
6 changed files with 122 additions and 12 deletions

View File

@ -102,7 +102,7 @@ void RichTextPainter::htmlRichText(const List & richText, QString & textHtml, QS
}
}
RichTextPainter::List RichTextPainter::cropped(const RichTextPainter::List &richText, int maxCols, const QString &indicator)
RichTextPainter::List RichTextPainter::cropped(const RichTextPainter::List &richText, int maxCols, const QString &indicator, bool *croppedOut)
{
List r;
r.reserve(richText.size());
@ -154,5 +154,9 @@ RichTextPainter::List RichTextPainter::cropped(const RichTextPainter::List &rich
}
}
if(croppedOut)
{
*croppedOut = cropped;
}
return r;
}

View File

@ -39,7 +39,7 @@ public:
static void paintRichText(QPainter* painter, int x, int y, int w, int h, int xinc, const List & richText, CachedFontMetrics* fontMetrics);
static void htmlRichText(const List & richText, QString & textHtml, QString & textPlain);
static List cropped(const List &richText, int maxCols, const QString &indicator = nullptr);
static List cropped(const List &richText, int maxCols, const QString &indicator = nullptr, bool *croppedOut = nullptr);
};
#endif // RICHTEXTPAINTER_H

View File

@ -6,6 +6,7 @@
#include <QMouseEvent>
#include <QPropertyAnimation>
#include <QShortcut>
#include <QToolTip>
#include "cutter.h"
#include "utils/Colors.h"
@ -166,7 +167,16 @@ void DisassemblerGraphView::loadCurrentGraph()
comment.flags = RichTextPainter::FlagColor;
richText.insert(richText.end(), comment);
}
i.text = Text(RichTextPainter::cropped(richText, Config()->getGraphBlockMaxChars(), "..."));
bool cropped;
i.text = Text(RichTextPainter::cropped(richText, Config()->getGraphBlockMaxChars(), "...", &cropped));
if(cropped)
{
i.fullText = richText;
}
else
{
i.fullText = Text();
}
db.instrs.push_back(i);
}
disassembly_blocks[db.entry] = db;
@ -377,7 +387,7 @@ GraphView::EdgeConfiguration DisassemblerGraphView::edgeConfiguration(GraphView:
return ec;
}
RVA DisassemblerGraphView::getInstrForMouseEvent(GraphBlock &block, QPoint* point)
RVA DisassemblerGraphView::getAddrForMouseEvent(GraphBlock &block, QPoint *point)
{
DisassemblyBlock &db = disassembly_blocks[block.entry];
@ -393,17 +403,39 @@ RVA DisassemblerGraphView::getInstrForMouseEvent(GraphBlock &block, QPoint* poin
return db.entry;
}
Instr *instr = getInstrForMouseEvent(block, point);
if(instr)
{
return instr->addr;
}
return RVA_INVALID;
}
DisassemblerGraphView::Instr *DisassemblerGraphView::getInstrForMouseEvent(GraphView::GraphBlock &block, QPoint *point)
{
DisassemblyBlock &db = disassembly_blocks[block.entry];
// Remove header and margin
int off_y = (2 * charWidth) + (db.header_text.lines.size() * charHeight);
// Get mouse coordinate over the actual text
int text_point_y = point->y() - off_y;
int mouse_row = text_point_y / charHeight;
int cur_row = db.header_text.lines.size();
for(Instr & instr : db.instrs)
{
if(mouse_row < cur_row + (int)instr.text.lines.size())
{
return instr.addr;
return &instr;
}
cur_row += instr.text.lines.size();
}
return RVA_INVALID;
}
return nullptr;
}
// Public Slots
@ -582,7 +614,7 @@ void DisassemblerGraphView::seekPrev()
void DisassemblerGraphView::blockClicked(GraphView::GraphBlock &block, QMouseEvent *event, QPoint pos)
{
RVA instr = getInstrForMouseEvent(block, &pos);
RVA instr = getAddrForMouseEvent(block, &pos);
if(instr == RVA_INVALID)
{
return;
@ -600,7 +632,7 @@ void DisassemblerGraphView::blockClicked(GraphView::GraphBlock &block, QMouseEve
void DisassemblerGraphView::blockDoubleClicked(GraphView::GraphBlock &block, QMouseEvent *event, QPoint pos)
{
Q_UNUSED(event);
RVA instr = getInstrForMouseEvent(block, &pos);
RVA instr = getAddrForMouseEvent(block, &pos);
if(instr == RVA_INVALID)
{
return;
@ -615,6 +647,30 @@ void DisassemblerGraphView::blockDoubleClicked(GraphView::GraphBlock &block, QMo
}
}
void DisassemblerGraphView::blockHelpEvent(GraphView::GraphBlock &block, QHelpEvent *event, QPoint pos)
{
Instr *instr = getInstrForMouseEvent(block, &pos);
if(!instr || instr->fullText.lines.empty())
{
QToolTip::hideText();
event->ignore();
return;
}
QToolTip::showText(event->globalPos(), instr->fullText.ToQString());
}
bool DisassemblerGraphView::helpEvent(QHelpEvent *event)
{
if(!GraphView::helpEvent(event))
{
QToolTip::hideText();
event->ignore();
}
return true;
}
void DisassemblerGraphView::blockTransitionedTo(GraphView::GraphBlock *to)
{
if(transition_dont_seek)

View File

@ -92,6 +92,7 @@ class DisassemblerGraphView : public GraphView
ut64 addr = 0;
ut64 size = 0;
Text text;
Text fullText;
std::vector<unsigned char> opcode; //instruction bytes
};
@ -142,6 +143,8 @@ public:
virtual void drawBlock(QPainter & p, GraphView::GraphBlock &block) override;
virtual void blockClicked(GraphView::GraphBlock &block, QMouseEvent *event, QPoint pos) override;
virtual void blockDoubleClicked(GraphView::GraphBlock &block, QMouseEvent *event, QPoint pos) override;
virtual bool helpEvent(QHelpEvent *event) override;
virtual void blockHelpEvent(GraphView::GraphBlock &block, QHelpEvent *event, QPoint pos) override;
virtual GraphView::EdgeConfiguration edgeConfiguration(GraphView::GraphBlock &from, GraphView::GraphBlock *to) override;
virtual void blockTransitionedTo(GraphView::GraphBlock *to) override;
@ -183,7 +186,8 @@ private:
void initFont();
void prepareGraphNode(GraphBlock &block);
RVA getInstrForMouseEvent(GraphBlock &block, QPoint* point);
RVA getAddrForMouseEvent(GraphBlock &block, QPoint *point);
Instr *getInstrForMouseEvent(GraphBlock &block, QPoint *point);
DisassemblyBlock *blockForAddress(RVA addr);
void seek(RVA addr, bool update_viewport=true);
void seekInstruction(bool previous_instr);

View File

@ -61,6 +61,34 @@ void GraphView::blockDoubleClicked(GraphView::GraphBlock &block, QMouseEvent *ev
qWarning() << "Block double clicked not overridden!";
}
void GraphView::blockHelpEvent(GraphView::GraphBlock &block, QHelpEvent *event, QPoint pos)
{
Q_UNUSED(block);
Q_UNUSED(event);
Q_UNUSED(pos);
}
bool GraphView::helpEvent(QHelpEvent *event)
{
int x = ((event->pos().x() - unscrolled_render_offset_x) / current_scale) + horizontalScrollBar()->value();
int y = ((event->pos().y() - unscrolled_render_offset_y) / current_scale) + verticalScrollBar()->value();
for(auto & blockIt : blocks)
{
GraphBlock &block = blockIt.second;
if((block.x <= x) && (block.y <= y) &&
(x <= block.x + block.width) & (y <= block.y + block.height))
{
QPoint pos = QPoint(x - block.x, y - block.y);
blockHelpEvent(block, event, pos);
return true;
}
}
return false;
}
void GraphView::blockTransitionedTo(GraphView::GraphBlock *to)
{
Q_UNUSED(to);
@ -98,6 +126,19 @@ void GraphView::adjustSize(int new_width, int new_height)
verticalScrollBar()->setValue((int)((double)verticalScrollBar()->maximum() * vfactor));
}
bool GraphView::event(QEvent *event)
{
if(event->type() == QEvent::ToolTip)
{
if(helpEvent(static_cast<QHelpEvent *>(event)))
{
return true;
}
}
return QAbstractScrollArea::event(event);
}
// This calculates the full graph starting at block entry.
void GraphView::computeGraph(ut64 entry)
{
@ -698,6 +739,7 @@ GraphView::GraphEdge GraphView::routeEdge(EdgesVector & horiz_edges, EdgesVector
return edge;
}
int GraphView::findHorizEdgeIndex(EdgesVector & edges, int row, int min_col, int max_col)
{
//Find a valid index
@ -746,7 +788,6 @@ int GraphView::findVertEdgeIndex(EdgesVector & edges, int col, int min_row, int
return i;
}
void GraphView::showBlock(GraphBlock &block, bool animated)
{
showBlock(&block, animated);
@ -806,6 +847,7 @@ void GraphView::addBlock(GraphView::GraphBlock block)
blocks[block.entry] = block;
}
void GraphView::setEntry(ut64 e)
{
entry = e;
@ -824,7 +866,6 @@ bool GraphView::checkPointClicked(QPointF &point, int x, int y, bool above_y)
return false;
}
void GraphView::resizeEvent(QResizeEvent* event)
{
adjustSize(event->size().width(), event->size().height());

View File

@ -7,6 +7,7 @@
#include <QAbstractScrollArea>
#include <QScrollBar>
#include <QElapsedTimer>
#include <QHelpEvent>
#include <unordered_map>
#include <unordered_set>
@ -121,10 +122,14 @@ protected:
virtual void drawBlock(QPainter & p, GraphView::GraphBlock &block);
virtual void blockClicked(GraphView::GraphBlock &block, QMouseEvent *event, QPoint pos);
virtual void blockDoubleClicked(GraphView::GraphBlock &block, QMouseEvent *event, QPoint pos);
virtual void blockHelpEvent(GraphView::GraphBlock &block, QHelpEvent *event, QPoint pos);
virtual bool helpEvent(QHelpEvent *event);
virtual void blockTransitionedTo(GraphView::GraphBlock *to);
virtual EdgeConfiguration edgeConfiguration(GraphView::GraphBlock &from, GraphView::GraphBlock *to);
void adjustSize(int new_width, int new_height);
bool event(QEvent *event);
private:
bool checkPointClicked(QPointF &point, int x, int y, bool above_y=false);