diff --git a/src/widgets/DisassemblerGraphView.cpp b/src/widgets/DisassemblerGraphView.cpp index dafc907b..4966be96 100644 --- a/src/widgets/DisassemblerGraphView.cpp +++ b/src/widgets/DisassemblerGraphView.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -19,6 +20,7 @@ #include "utils/Configuration.h" #include "utils/CachedFontMetrics.h" #include "utils/TempConfig.h" +#include "utils/SyntaxHighlighter.h" DisassemblerGraphView::DisassemblerGraphView(QWidget *parent) : GraphView(parent), @@ -111,6 +113,12 @@ DisassemblerGraphView::DisassemblerGraphView(QWidget *parent) connect(&actionSyncOffset, SIGNAL(triggered(bool)), this, SLOT(toggleSync())); initFont(); colorsUpdatedSlot(); + + header = new QTextEdit(viewport()); + header->setFixedHeight(30); + header->setReadOnly(true); + header->setLineWrapMode(QTextEdit::NoWrap); + highlighter = new SyntaxHighlighter(header->document()); } void DisassemblerGraphView::connectSeekChanged(bool disconn) @@ -336,6 +344,44 @@ void DisassemblerGraphView::prepareGraphNode(GraphBlock &block) block.height = (height * charHeight) + extra; } +void DisassemblerGraphView::prepareHeader() +{ + QString afcf = Core()->cmd("afcf").trimmed(); + if (afcf.length() > 0) { + header->setPlainText(afcf); + header->show(); + return; + } + QJsonArray func = Core()->cmdj("afij").array(); + QJsonValue value = func.first(); + QJsonObject obj = value.toObject(); + QString name = obj["name"].toString().trimmed(); + if (name.isEmpty()) { + header->hide(); + return; + } + QString ret = obj["calltype"].toString().trimmed(); + ret += (" ") + name + ("("); + QJsonArray args = obj["bpvars"].toArray(); + QString argNames = QString(); + for (QJsonValue value : args) { + QJsonObject obj = value.toObject(); + QString kind = obj["kind"].toString(); + if (kind == "arg") { + QString typeName = obj["type"].toString().trimmed(); + QString argName = obj["name"].toString().trimmed(); + if (argNames.isEmpty()) { + argNames += typeName + (" ") + argName; + } else { + argNames += (", ") + typeName + (" ") + argName; + } + } + } + ret += argNames + (")"); + header->setPlainText(ret); + header->show(); +} + void DisassemblerGraphView::initFont() { setFont(Config()->getFont()); @@ -629,14 +675,16 @@ void DisassemblerGraphView::onSeekChanged(RVA addr) // This is a local address! We animated to it. transition_dont_seek = true; showBlock(&blocks[db->entry], true); + prepareHeader(); return; } else { refreshView(); - DisassemblyBlock *db = blockForAddress(addr); + db = blockForAddress(addr); if (db) { // This is a local address! We animated to it. transition_dont_seek = true; - showBlock(&blocks[db->entry], false); + showBlock(&blocks[db->entry], true); + prepareHeader(); return; } } diff --git a/src/widgets/DisassemblerGraphView.h b/src/widgets/DisassemblerGraphView.h index 4fd47429..da69285e 100644 --- a/src/widgets/DisassemblerGraphView.h +++ b/src/widgets/DisassemblerGraphView.h @@ -13,6 +13,9 @@ #include "utils/RichTextPainter.h" #include "CutterSeekableWidget.h" +class QTextEdit; +class SyntaxHighlighter; + class DisassemblerGraphView : public GraphView { Q_OBJECT @@ -123,6 +126,7 @@ public: void loadCurrentGraph(); QString windowTitle; bool isGraphEmpty(); + QTextEdit *header = nullptr; public slots: void refreshView(); @@ -168,6 +172,7 @@ private: void initFont(); void prepareGraphNode(GraphBlock &block); + void prepareHeader(); Token *getToken(Instr *instr, int x); RVA getAddrForMouseEvent(GraphBlock &block, QPoint *point); Instr *getInstrForMouseEvent(GraphBlock &block, QPoint *point); @@ -206,6 +211,7 @@ private: QAction actionSyncOffset; QLabel *emptyText = nullptr; + SyntaxHighlighter *highlighter = nullptr; }; #endif // DISASSEMBLERGRAPHVIEW_H diff --git a/src/widgets/GraphWidget.cpp b/src/widgets/GraphWidget.cpp index abac3ab7..6c038daa 100644 --- a/src/widgets/GraphWidget.cpp +++ b/src/widgets/GraphWidget.cpp @@ -14,16 +14,16 @@ GraphWidget::GraphWidget(MainWindow *main, QAction *action) : // getting the name of the class is implementation defined, and cannot be // used reliably across different compilers. //QShortcut *toggle_shortcut = new QShortcut(widgetShortcuts[typeid(this).name()], main); - QShortcut *toggle_shortcut = new QShortcut(widgetShortcuts["GraphWidget"], main); - connect(toggle_shortcut, &QShortcut::activated, this, [=] (){ + connect(toggle_shortcut, &QShortcut::activated, this, [ = ]() { toggleDockWidget(true); main->updateDockActionChecked(action); - } ); + }); - connect(this, &QDockWidget::visibilityChanged, this, [](bool visibility) { + connect(this, &QDockWidget::visibilityChanged, this, [ = ](bool visibility) { if (visibility) { Core()->setMemoryWidgetPriority(CutterCore::MemoryWidgetType::Graph); + this->graphView->header->setFixedWidth(width()); } }); @@ -33,6 +33,7 @@ GraphWidget::GraphWidget(MainWindow *main, QAction *action) : if (type == CutterCore::MemoryWidgetType::Graph && !emptyGraph) { this->raise(); this->graphView->setFocus(); + this->graphView->header->setFixedWidth(width()); } }); }