+ menu.exec(event->screenPos());
+}
+
+/* QGraphicsTextItem has an adjustSize() function that is supposed to
+ * resize the widget to it's "ideal" size. However it totally ignores
+ * all directives to not wrap lines and "ideal" is actually just a
+ * bunch of heuristics.
+ *
+ * We are starting with a hopefully absurdly large startingwidth and
+ * reduce it untill a line is broken (detected by a change in
+ * height). As long as the width (1000 here) is sufficiently large,
+ * this should give us a widget without any line-wrapping.
+ *
+ * One needs to call this on a Pointer of tye CustomQGraphicsTextItem
+ * as the adjustSize() function is not polymorphic (vurtual).
+ */
+void CustomQGraphicsTextItem::adjustSize() {
+ int width = 1000;
+ setTextWidth(width);
+ int height = boundingRect().height();
+ while (width > 250 && height == boundingRect().height()) {
+ setTextWidth(width -= 10);
+ }
+ width += 10;
+ if (width < 250) width = 250;
+ setTextWidth(width);
+}
+
+BasicBlockWidget::BasicBlockWidget(const QString& name, BasicBlock * block,
+ Mainwindow * mainwindow)
+ : width(200), height(45), name(name)
+ , _table(NULL)
+ , block(block), mainwindow(mainwindow)
+ , logger(log4cxx::Logger::getLogger("gui.BasicBlockWidget." + name.toStdString())) {
+ next[0] = NULL; next[1] = NULL;
+
+ block->getManager()->registerRenameFunctionEvent([=](RenameFunctionEvent* event) {updateFunctionName(event);});
+
+ _widget.reset(new CustomQGraphicsTextItem("", this));
+ _widget->setPos(5, 20);
+ _widget->setTextInteractionFlags(Qt::TextSelectableByMouse|
+ Qt::LinksAccessibleByMouse);
+
+ if (width < 250) width = 250;
+
+ QObject::connect(_widget.get(), &QGraphicsTextItem::linkActivated,
+ [=](QString str) {
+ if (str.startsWith("function:")) {
+ QString address = str.remove("function:");
+ mainwindow->switchMainPlaneToAddress(address.toInt(NULL, 16));
+ }
+ });
+ instructions = block->getInstructions();
+ populateWidget();
+ block->getManager()->registerChangeCommentEvent([=](ChangeCommentEvent* e) {changeCommentHandler(e);});
+}
+
+void BasicBlockWidget::updateFunctionName(RenameFunctionEvent *event) {
+ QString search = QString("function:") + QString::number(event->address, 16);
+ QTextDocument *document = _widget->document();
+ QTextBlock b = document->begin();
+ while (b.isValid()) {
+ for (QTextBlock::iterator i = b.begin(); !i.atEnd(); ++i) {
+ QTextCharFormat format = i.fragment().charFormat();
+ bool isLink = format.isAnchor();
+ if (isLink)
+ {
+ if (search == format.anchorHref()) {
+ LOG4CXX_DEBUG(logger, i.fragment().text().toStdString() << " ---> "
+ << format.anchorHref().toStdString());
+
+ /* This should select the function name. It stars
+ * by selecting the whole link fragment from back
+ * to front and then moves one word to the back
+ * again deselecting whatever mnemonic is used for
+ * the call instruction.
+ */
+ QTextCursor c(b);
+ c.setPosition(i.fragment().position());
+ c.movePosition(QTextCursor::Right, QTextCursor::MoveAnchor, i.fragment().length());
+ c.movePosition(QTextCursor::Left, QTextCursor::KeepAnchor, i.fragment().length());
+ c.movePosition(QTextCursor::WordRight, QTextCursor::KeepAnchor);
+ c.insertText(event->new_name.c_str());
+
+ QGraphicsTextItem* item = _widget.get();
+ ((CustomQGraphicsTextItem*)item)->adjustSize();
+ }
+ }
+ }
+ b = b.next();