1 #include "BasicBlockWidget.hxx"
2 #include "gui/Mainwindow.hxx"
3 #include "gui/dialogs/SimpleStringDialog.hxx"
4 #include "core/BasicBlock.hxx"
5 #include "core/Function.hxx"
6 #include "core/InformationManager.hxx"
7 #include "core/events/RenameFunctionEvent.hxx"
10 class CustomQGraphicsTextItem
: public QObject
, public QGraphicsTextItem
{
12 CustomQGraphicsTextItem(const QString
& text
, BasicBlockWidget
* parent
)
13 : QGraphicsTextItem(text
, parent
), parent(parent
) {}
14 void contextMenuEvent(QGraphicsSceneContextMenuEvent
*);
16 void addComment(QTextTableCell cell
, const QString
& title
);
18 BasicBlockWidget
* parent
;
21 void CustomQGraphicsTextItem::addComment(QTextTableCell cell
, const QString
& title
) {
22 SimpleStringDialog
dialog(title
);
23 int result
= dialog
.exec();
24 if (QDialog::Accepted
== result
) {
25 LOG4CXX_DEBUG(parent
->logger
, "adding comment " << dialog
.result().toStdString()
26 << " at row " << cell
.row());
27 cell
.firstCursorPosition().insertHtml(QString(";; ") + dialog
.result());
29 LOG4CXX_DEBUG(parent
->logger
, "addComment aborted");
33 void CustomQGraphicsTextItem::contextMenuEvent(QGraphicsSceneContextMenuEvent
* event
) {
34 QTextCursor c
= textCursor();
35 c
.setPosition(document()->documentLayout()->hitTest(event
->pos(), Qt::FuzzyHit
));
36 c
.select(QTextCursor::WordUnderCursor
);
40 uint64_t address
= c
.selectedText().toLongLong(&ok
, 16);
42 QAction
* act
= menu
.addAction(c
.selectedText() + " is a Function");
43 QObject::connect(act
, &QAction::triggered
,
44 [=]() {parent
->mainwindow
->requestNewFunctionByAddress(address
);});
47 QTextTable
* table
= c
.currentTable();
49 int row
= table
->cellAt(c
).row();
50 QTextTableCell cell
= table
->cellAt(row
, 2);
51 QAction
* globalComment
= menu
.addAction("Add global Comment");
52 QAction
* localComment
= menu
.addAction("Add local Comment");
54 QObject::connect(globalComment
, &QAction::triggered
,
55 [=]() { addComment(cell
, "Global comment"); });
56 QObject::connect(localComment
, &QAction::triggered
,
57 [=]() { addComment(cell
, "Local comment"); });
60 menu
.exec(event
->screenPos());
63 BasicBlockWidget::BasicBlockWidget(const QString
& name
, BasicBlock
* block
,
64 Mainwindow
* mainwindow
)
65 : width(270), height(45), name(name
)
67 , block(block
), mainwindow(mainwindow
)
68 , logger(log4cxx::Logger::getLogger("gui.BasicBlockWidget." + name
.toStdString())) {
69 next
[0] = NULL
; next
[1] = NULL
;
71 block
->getManager()->registerRenameFunctionEvent([=](RenameFunctionEvent
* event
) {updateFunctionName(event
);});
73 _widget
.reset(new CustomQGraphicsTextItem("", this));
74 _widget
->setPos(5, 20);
75 _widget
->setTextInteractionFlags(Qt::TextSelectableByMouse
|
76 Qt::LinksAccessibleByMouse
);
78 if (width
< 250) width
= 250;
80 QObject::connect(_widget
.get(), &QGraphicsTextItem::linkActivated
,
82 if (str
.startsWith("function:")) {
83 QString address
= str
.remove("function:");
84 mainwindow
->switchMainPlaneToAddress(address
.toInt(NULL
, 16));
87 instructions
= block
->getInstructions();
91 void BasicBlockWidget::updateFunctionName(RenameFunctionEvent
*event
) {
92 QString search
= QString("function:") + QString::number(event
->address
, 16);
93 QTextDocument
*document
= _widget
->document();
94 QTextBlock b
= document
->begin();
96 for (QTextBlock::iterator i
= b
.begin(); !i
.atEnd(); ++i
) {
97 QTextCharFormat format
= i
.fragment().charFormat();
98 bool isLink
= format
.isAnchor();
101 if (search
== format
.anchorHref()) {
102 LOG4CXX_DEBUG(logger
, i
.fragment().text().toStdString() << " ---> " << format
.anchorHref().toStdString());
104 c
.setPosition(i
.fragment().position());
105 c
.movePosition(QTextCursor::Right
, QTextCursor::MoveAnchor
, i
.fragment().length());
106 c
.movePosition(QTextCursor::Left
, QTextCursor::KeepAnchor
, i
.fragment().length());
107 c
.movePosition(QTextCursor::WordRight
, QTextCursor::KeepAnchor
);
108 c
.insertText(event
->new_name
.c_str());
116 void BasicBlockWidget::populateWidget() {
118 QTextTableFormat format
;
119 format
.setBorderStyle(QTextFrameFormat::BorderStyle_None
);
122 for (Instruction
& inst
: instructions
) {
124 row
= _table
->rows();
125 _table
->appendRows(1);
128 _table
= _widget
->textCursor().insertTable(1, 3, format
);
131 for (uint8_t byte
: inst
.getBytes()) {
132 const char * hexdigits
= "0123456789ABCDEF";
133 bytestring
+= hexdigits
[(byte
>> 4) & 0xF];
134 bytestring
+= hexdigits
[byte
& 0xF];
137 _table
->cellAt(row
, 0).firstCursorPosition().insertText(bytestring
);
139 QString line
= inst
.getText().c_str();
140 line
= line
.replace('\t', ' ').toHtmlEscaped();
141 if (inst
.getReference() != "") {
142 QString href
= inst
.getReference().c_str();
143 QStringList list
= href
.split(":");
144 if (list
[0] == "function") {
145 uint64_t address
= href
.split(":")[1].toLongLong(NULL
, 16);
146 Function
* fun
= block
->getManager()->getFunction(address
);
149 line
= line
.split(" ")[0] + " " + QString(fun
->getName().c_str()).toHtmlEscaped();
150 LOG4CXX_DEBUG(logger
, "Naming function at " << address
<< " " << fun
->getName());
153 line
= "<a href=\"" + href
+ "\">" + line
+ "</a>";
156 _table
->cellAt(row
, 1).firstCursorPosition().insertHtml(line
);
160 void BasicBlockWidget::paint(QPainter
*painter
, const QStyleOptionGraphicsItem
*,
162 _widget
->adjustSize();
163 width
= 10 + _widget
->boundingRect().width();
164 height
= 25 + _widget
->boundingRect().height();
165 if (width
< 250) width
= 250;
167 painter
->fillRect(0, 0, width
, height
, QColor(0xcc, 0xcc, 0xff, 0xff));
168 painter
->setPen(QColor(0x00, 0x00, 0xff, 0xff));
169 painter
->drawRect(0, 0, width
, height
);
170 painter
->drawText(5, 15, name
);
173 QRectF
BasicBlockWidget::boundingRect() const {
175 QRectF
result(- penWidth
/ 2, - penWidth
/ 2,
176 width
+ penWidth
, height
+ penWidth
);
180 std::array
<QPointF
, 3> BasicBlockWidget::getExits() const {
181 return { { mapToScene(QPointF( width
/3, height
)),
182 mapToScene(QPointF( width
/2, height
)),
183 mapToScene(QPointF(2*width
/3, height
)) } };