diff --git a/src/utils/RichTextPainter.cpp b/src/utils/RichTextPainter.cpp index 120b1211..b5f152c1 100644 --- a/src/utils/RichTextPainter.cpp +++ b/src/utils/RichTextPainter.cpp @@ -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; } diff --git a/src/utils/RichTextPainter.h b/src/utils/RichTextPainter.h index af9797ad..59c3df98 100644 --- a/src/utils/RichTextPainter.h +++ b/src/utils/RichTextPainter.h @@ -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 diff --git a/src/widgets/DisassemblerGraphView.cpp b/src/widgets/DisassemblerGraphView.cpp index 6c6913b4..48149f3a 100644 --- a/src/widgets/DisassemblerGraphView.cpp +++ b/src/widgets/DisassemblerGraphView.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #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) diff --git a/src/widgets/DisassemblerGraphView.h b/src/widgets/DisassemblerGraphView.h index 86e7a63b..959c2768 100644 --- a/src/widgets/DisassemblerGraphView.h +++ b/src/widgets/DisassemblerGraphView.h @@ -92,6 +92,7 @@ class DisassemblerGraphView : public GraphView ut64 addr = 0; ut64 size = 0; Text text; + Text fullText; std::vector 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); diff --git a/src/widgets/GraphView.cpp b/src/widgets/GraphView.cpp index 94c34b78..9c5c7882 100644 --- a/src/widgets/GraphView.cpp +++ b/src/widgets/GraphView.cpp @@ -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(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()); diff --git a/src/widgets/GraphView.h b/src/widgets/GraphView.h index 445df099..73408a0b 100644 --- a/src/widgets/GraphView.h +++ b/src/widgets/GraphView.h @@ -7,6 +7,7 @@ #include #include #include +#include #include #include @@ -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);