mirror of
https://github.com/rizinorg/cutter.git
synced 2024-12-24 05:45:27 +00:00
Fix graph export commands to use c api
This commit is contained in:
parent
20801f7fe6
commit
7a96fad546
@ -4515,3 +4515,68 @@ QStringList CutterCore::getConfigVariableSpaces(const QString &key)
|
|||||||
rz_list_free(list);
|
rz_list_free(list);
|
||||||
return stringList;
|
return stringList;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char *CutterCore::getTextualGraphAt(RzCoreGraphType type, RzCoreGraphFormat format, RVA address)
|
||||||
|
{
|
||||||
|
CORE_LOCK();
|
||||||
|
char *string = nullptr;
|
||||||
|
RzGraph *graph = rz_core_graph(core, type, address);
|
||||||
|
if (!graph) {
|
||||||
|
if (address == RVA_INVALID) {
|
||||||
|
qWarning() << "Cannot get global graph";
|
||||||
|
} else {
|
||||||
|
qWarning() << "Cannot get graph at " << RzAddressString(address);
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
core->graph->is_callgraph = type == RZ_CORE_GRAPH_TYPE_FUNCALL;
|
||||||
|
|
||||||
|
switch (format) {
|
||||||
|
case RZ_CORE_GRAPH_FORMAT_CMD: {
|
||||||
|
string = rz_graph_drawable_to_cmd(graph);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case RZ_CORE_GRAPH_FORMAT_DOT: {
|
||||||
|
string = rz_core_graph_to_dot_str(core, graph);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case RZ_CORE_GRAPH_FORMAT_JSON:
|
||||||
|
/* fall-thru */
|
||||||
|
case RZ_CORE_GRAPH_FORMAT_JSON_DISASM: {
|
||||||
|
string = rz_graph_drawable_to_json_str(graph, true);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case RZ_CORE_GRAPH_FORMAT_GML: {
|
||||||
|
string = rz_graph_drawable_to_gml(graph);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
rz_graph_free(graph);
|
||||||
|
|
||||||
|
if (!string) {
|
||||||
|
qWarning() << "Failed to generate graph";
|
||||||
|
}
|
||||||
|
|
||||||
|
return string;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CutterCore::writeGraphvizGraphToFile(QString path, QString format, RzCoreGraphType type,
|
||||||
|
RVA address)
|
||||||
|
{
|
||||||
|
TempConfig tempConfig;
|
||||||
|
tempConfig.set("scr.color", false);
|
||||||
|
tempConfig.set("graph.gv.format", format);
|
||||||
|
|
||||||
|
CORE_LOCK();
|
||||||
|
auto filepath = path.toUtf8();
|
||||||
|
|
||||||
|
if (!rz_core_graph_write(core, address, type, filepath)) {
|
||||||
|
if (address == RVA_INVALID) {
|
||||||
|
qWarning() << "Cannot get global graph";
|
||||||
|
} else {
|
||||||
|
qWarning() << "Cannot get graph at " << RzAddressString(address);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -720,6 +720,25 @@ public:
|
|||||||
*/
|
*/
|
||||||
bool isWriteModeEnabled();
|
bool isWriteModeEnabled();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns the textual version of global or specific graph.
|
||||||
|
* @param type Graph type, example RZ_CORE_GRAPH_TYPE_FUNCALL or RZ_CORE_GRAPH_TYPE_IMPORT
|
||||||
|
* @param format Graph format, example RZ_CORE_GRAPH_FORMAT_DOT or RZ_CORE_GRAPH_FORMAT_GML
|
||||||
|
* @param address The object address (if global set it to RVA_INVALID)
|
||||||
|
* @return The textual graph string.
|
||||||
|
*/
|
||||||
|
char *getTextualGraphAt(RzCoreGraphType type, RzCoreGraphFormat format, RVA address);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Writes a graphviz graph to a file.
|
||||||
|
* @param path The file output path
|
||||||
|
* @param format The output format (see graph.gv.format)
|
||||||
|
* @param type The graph type, example RZ_CORE_GRAPH_TYPE_FUNCALL or
|
||||||
|
* RZ_CORE_GRAPH_TYPE_IMPORT
|
||||||
|
* @param address The object address (if global set it to RVA_INVALID)
|
||||||
|
*/
|
||||||
|
void writeGraphvizGraphToFile(QString path, QString format, RzCoreGraphType type, RVA address);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void refreshAll();
|
void refreshAll();
|
||||||
|
|
||||||
|
@ -7,7 +7,9 @@
|
|||||||
#include <QJsonObject>
|
#include <QJsonObject>
|
||||||
|
|
||||||
CallGraphWidget::CallGraphWidget(MainWindow *main, bool global)
|
CallGraphWidget::CallGraphWidget(MainWindow *main, bool global)
|
||||||
: MemoryDockWidget(MemoryWidgetType::CallGraph, main), graphView(new CallGraphView(this, main, global)), global(global)
|
: MemoryDockWidget(MemoryWidgetType::CallGraph, main),
|
||||||
|
graphView(new CallGraphView(this, main, global)),
|
||||||
|
global(global)
|
||||||
{
|
{
|
||||||
setObjectName(main ? main->getUniqueObjectName(getWidgetType()) : getWidgetType());
|
setObjectName(main ? main->getUniqueObjectName(getWidgetType()) : getWidgetType());
|
||||||
this->setWindowTitle(getWindowTitle());
|
this->setWindowTitle(getWindowTitle());
|
||||||
@ -53,7 +55,7 @@ void CallGraphView::showExportDialog()
|
|||||||
} else {
|
} else {
|
||||||
defaultName = QString("callgraph_%1").arg(RzAddressString(address));
|
defaultName = QString("callgraph_%1").arg(RzAddressString(address));
|
||||||
}
|
}
|
||||||
showExportGraphDialog(defaultName, global ? "agC" : "agc", address);
|
showExportGraphDialog(defaultName, RZ_CORE_GRAPH_TYPE_FUNCALL, global ? RVA_INVALID : address);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CallGraphView::showAddress(RVA address)
|
void CallGraphView::showAddress(RVA address)
|
||||||
@ -80,7 +82,6 @@ static inline bool isBetween(ut64 a, ut64 x, ut64 b)
|
|||||||
return (a == UT64_MAX || a <= x) && (b == UT64_MAX || x <= b);
|
return (a == UT64_MAX || a <= x) && (b == UT64_MAX || x <= b);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void CallGraphView::loadCurrentGraph()
|
void CallGraphView::loadCurrentGraph()
|
||||||
{
|
{
|
||||||
blockContent.clear();
|
blockContent.clear();
|
||||||
|
@ -152,7 +152,7 @@ void CutterGraphView::zoomReset()
|
|||||||
|
|
||||||
void CutterGraphView::showExportDialog()
|
void CutterGraphView::showExportDialog()
|
||||||
{
|
{
|
||||||
showExportGraphDialog("graph", "", RVA_INVALID);
|
showExportGraphDialog("global_funcall", RZ_CORE_GRAPH_TYPE_FUNCALL, RVA_INVALID);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CutterGraphView::updateColors()
|
void CutterGraphView::updateColors()
|
||||||
@ -318,12 +318,12 @@ void CutterGraphView::mouseMoveEvent(QMouseEvent *event)
|
|||||||
emit graphMoved();
|
emit graphMoved();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CutterGraphView::exportGraph(QString filePath, GraphExportType type, QString graphCommand,
|
void CutterGraphView::exportGraph(QString filePath, GraphExportType exportType,
|
||||||
RVA address)
|
RzCoreGraphType graphType, RVA address)
|
||||||
{
|
{
|
||||||
bool graphTransparent = Config()->getBitmapTransparentState();
|
bool graphTransparent = Config()->getBitmapTransparentState();
|
||||||
double graphScaleFactor = Config()->getBitmapExportScaleFactor();
|
double graphScaleFactor = Config()->getBitmapExportScaleFactor();
|
||||||
switch (type) {
|
switch (exportType) {
|
||||||
case GraphExportType::Png:
|
case GraphExportType::Png:
|
||||||
this->saveAsBitmap(filePath, "png", graphScaleFactor, graphTransparent);
|
this->saveAsBitmap(filePath, "png", graphScaleFactor, graphTransparent);
|
||||||
break;
|
break;
|
||||||
@ -335,56 +335,55 @@ void CutterGraphView::exportGraph(QString filePath, GraphExportType type, QStrin
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case GraphExportType::GVDot:
|
case GraphExportType::GVDot:
|
||||||
exportRzTextGraph(filePath, graphCommand + "d", address);
|
exportRzTextGraph(filePath, graphType, RZ_CORE_GRAPH_FORMAT_DOT, address);
|
||||||
break;
|
break;
|
||||||
case GraphExportType::RzJson:
|
case GraphExportType::RzJson:
|
||||||
exportRzTextGraph(filePath, graphCommand + "j", address);
|
exportRzTextGraph(filePath, graphType, RZ_CORE_GRAPH_FORMAT_JSON, address);
|
||||||
break;
|
break;
|
||||||
case GraphExportType::RzGml:
|
case GraphExportType::RzGml:
|
||||||
exportRzTextGraph(filePath, graphCommand + "g", address);
|
exportRzTextGraph(filePath, graphType, RZ_CORE_GRAPH_FORMAT_GML, address);
|
||||||
break;
|
|
||||||
case GraphExportType::RzSDBKeyValue:
|
|
||||||
exportRzTextGraph(filePath, graphCommand + "k", address);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case GraphExportType::GVJson:
|
case GraphExportType::GVJson:
|
||||||
exportRizinGraphvizGraph(filePath, "json", graphCommand, address);
|
Core()->writeGraphvizGraphToFile(filePath, "json", graphType, address);
|
||||||
break;
|
break;
|
||||||
case GraphExportType::GVGif:
|
case GraphExportType::GVGif:
|
||||||
exportRizinGraphvizGraph(filePath, "gif", graphCommand, address);
|
Core()->writeGraphvizGraphToFile(filePath, "gif", graphType, address);
|
||||||
break;
|
break;
|
||||||
case GraphExportType::GVPng:
|
case GraphExportType::GVPng:
|
||||||
exportRizinGraphvizGraph(filePath, "png", graphCommand, address);
|
Core()->writeGraphvizGraphToFile(filePath, "png", graphType, address);
|
||||||
break;
|
break;
|
||||||
case GraphExportType::GVJpeg:
|
case GraphExportType::GVJpeg:
|
||||||
exportRizinGraphvizGraph(filePath, "jpg", graphCommand, address);
|
Core()->writeGraphvizGraphToFile(filePath, "jpg", graphType, address);
|
||||||
break;
|
break;
|
||||||
case GraphExportType::GVPostScript:
|
case GraphExportType::GVPostScript:
|
||||||
exportRizinGraphvizGraph(filePath, "ps", graphCommand, address);
|
Core()->writeGraphvizGraphToFile(filePath, "ps", graphType, address);
|
||||||
break;
|
break;
|
||||||
case GraphExportType::GVSvg:
|
case GraphExportType::GVSvg:
|
||||||
exportRizinGraphvizGraph(filePath, "svg", graphCommand, address);
|
Core()->writeGraphvizGraphToFile(filePath, "svg", graphType, address);
|
||||||
|
break;
|
||||||
|
case GraphExportType::GVPdf:
|
||||||
|
Core()->writeGraphvizGraphToFile(filePath, "pdf", graphType, address);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CutterGraphView::exportRizinGraphvizGraph(QString filePath, QString type, QString graphCommand,
|
void CutterGraphView::exportRzTextGraph(QString filePath, RzCoreGraphType type,
|
||||||
RVA address)
|
RzCoreGraphFormat format, RVA address)
|
||||||
{
|
{
|
||||||
TempConfig tempConfig;
|
char *string = Core()->getTextualGraphAt(type, format, address);
|
||||||
tempConfig.set("graph.gv.format", type);
|
if (!string) {
|
||||||
qWarning() << Core()->cmdRawAt(QString("%0w \"%1\"").arg(graphCommand).arg(filePath), address);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CutterGraphView::exportRzTextGraph(QString filePath, QString graphCommand, RVA address)
|
|
||||||
{
|
|
||||||
QFile file(filePath);
|
|
||||||
if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
|
|
||||||
qWarning() << "Can't open file";
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QFile file(filePath);
|
||||||
|
if (file.open(QIODevice::WriteOnly | QIODevice::Text)) {
|
||||||
QTextStream fileOut(&file);
|
QTextStream fileOut(&file);
|
||||||
fileOut << Core()->cmdRawAt(QString("%0").arg(graphCommand), address);
|
fileOut << string;
|
||||||
|
} else {
|
||||||
|
qWarning() << "Can't open or create file: " << filePath;
|
||||||
|
}
|
||||||
|
free(string);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CutterGraphView::graphIsBitamp(CutterGraphView::GraphExportType type)
|
bool CutterGraphView::graphIsBitamp(CutterGraphView::GraphExportType type)
|
||||||
@ -403,24 +402,22 @@ bool CutterGraphView::graphIsBitamp(CutterGraphView::GraphExportType type)
|
|||||||
|
|
||||||
Q_DECLARE_METATYPE(CutterGraphView::GraphExportType);
|
Q_DECLARE_METATYPE(CutterGraphView::GraphExportType);
|
||||||
|
|
||||||
void CutterGraphView::showExportGraphDialog(QString defaultName, QString graphCommand, RVA address)
|
void CutterGraphView::showExportGraphDialog(QString defaultName, RzCoreGraphType type, RVA address)
|
||||||
{
|
{
|
||||||
|
qWarning() << defaultName << " - " << type << " addr " << RzAddressString(address);
|
||||||
QVector<MultitypeFileSaveDialog::TypeDescription> types = {
|
QVector<MultitypeFileSaveDialog::TypeDescription> types = {
|
||||||
{ tr("PNG (*.png)"), "png", QVariant::fromValue(GraphExportType::Png) },
|
{ tr("PNG (*.png)"), "png", QVariant::fromValue(GraphExportType::Png) },
|
||||||
{ tr("JPEG (*.jpg)"), "jpg", QVariant::fromValue(GraphExportType::Jpeg) },
|
{ tr("JPEG (*.jpg)"), "jpg", QVariant::fromValue(GraphExportType::Jpeg) },
|
||||||
{ tr("SVG (*.svg)"), "svg", QVariant::fromValue(GraphExportType::Svg) }
|
{ tr("SVG (*.svg)"), "svg", QVariant::fromValue(GraphExportType::Svg) }
|
||||||
};
|
};
|
||||||
|
|
||||||
bool rzGraphExports = !graphCommand.isEmpty();
|
|
||||||
if (rzGraphExports) {
|
|
||||||
types.append({
|
types.append({
|
||||||
{ tr("Graphviz dot (*.dot)"), "dot", QVariant::fromValue(GraphExportType::GVDot) },
|
{ tr("Graphviz dot (*.dot)"), "dot", QVariant::fromValue(GraphExportType::GVDot) },
|
||||||
{ tr("Graph Modelling Language (*.gml)"), "gml",
|
{ tr("Graph Modelling Language (*.gml)"), "gml",
|
||||||
QVariant::fromValue(GraphExportType::RzGml) },
|
QVariant::fromValue(GraphExportType::RzGml) },
|
||||||
{ tr("RZ JSON (*.json)"), "json", QVariant::fromValue(GraphExportType::RzJson) },
|
{ tr("RZ JSON (*.json)"), "json", QVariant::fromValue(GraphExportType::RzJson) },
|
||||||
{ tr("SDB key-value (*.txt)"), "txt",
|
|
||||||
QVariant::fromValue(GraphExportType::RzSDBKeyValue) },
|
|
||||||
});
|
});
|
||||||
|
|
||||||
bool hasGraphviz = !QStandardPaths::findExecutable("dot").isEmpty()
|
bool hasGraphviz = !QStandardPaths::findExecutable("dot").isEmpty()
|
||||||
|| !QStandardPaths::findExecutable("xdot").isEmpty();
|
|| !QStandardPaths::findExecutable("xdot").isEmpty();
|
||||||
if (hasGraphviz) {
|
if (hasGraphviz) {
|
||||||
@ -435,8 +432,9 @@ void CutterGraphView::showExportGraphDialog(QString defaultName, QString graphCo
|
|||||||
{ tr("Graphviz PostScript (*.ps)"), "ps",
|
{ tr("Graphviz PostScript (*.ps)"), "ps",
|
||||||
QVariant::fromValue(GraphExportType::GVPostScript) },
|
QVariant::fromValue(GraphExportType::GVPostScript) },
|
||||||
{ tr("Graphviz svg (*.svg)"), "svg",
|
{ tr("Graphviz svg (*.svg)"), "svg",
|
||||||
QVariant::fromValue(GraphExportType::GVSvg) } });
|
QVariant::fromValue(GraphExportType::GVSvg) },
|
||||||
}
|
{ tr("Graphviz pdf (*.pdf)"), "pdf",
|
||||||
|
QVariant::fromValue(GraphExportType::GVPdf) } });
|
||||||
}
|
}
|
||||||
|
|
||||||
MultitypeFileSaveDialog dialog(this, tr("Export Graph"));
|
MultitypeFileSaveDialog dialog(this, tr("Export Graph"));
|
||||||
@ -470,5 +468,5 @@ void CutterGraphView::showExportGraphDialog(QString defaultName, QString graphCo
|
|||||||
}
|
}
|
||||||
|
|
||||||
QString filePath = dialog.selectedFiles().first();
|
QString filePath = dialog.selectedFiles().first();
|
||||||
exportGraph(filePath, exportType, graphCommand, address);
|
exportGraph(filePath, exportType, type, address);
|
||||||
}
|
}
|
||||||
|
@ -32,48 +32,38 @@ public:
|
|||||||
GVJpeg,
|
GVJpeg,
|
||||||
GVPostScript,
|
GVPostScript,
|
||||||
GVSvg,
|
GVSvg,
|
||||||
|
GVPdf,
|
||||||
RzGml,
|
RzGml,
|
||||||
RzSDBKeyValue,
|
|
||||||
RzJson
|
RzJson
|
||||||
};
|
};
|
||||||
/**
|
/**
|
||||||
* @brief Export graph to a file in the specified format
|
* @brief Export graph to a file in the specified format
|
||||||
* @param filePath
|
* @param filePath - output file path
|
||||||
* @param type export type, GV* and Rz* types require \p graphCommand
|
* @param exportType - export type, GV* and Rz* types require \p graphCommand
|
||||||
* @param graphCommand rizin graph printing command without type, not required for direct image
|
* @param graphType - graph type, example RZ_CORE_GRAPH_TYPE_FUNCALL or
|
||||||
* export
|
* RZ_CORE_GRAPH_TYPE_IMPORT
|
||||||
* @param address object address for commands like agf
|
* @param address - object address (if global set it to RVA_INVALID)
|
||||||
*/
|
*/
|
||||||
void exportGraph(QString filePath, GraphExportType type, QString graphCommand = "",
|
void exportGraph(QString filePath, GraphExportType exportType, RzCoreGraphType graphType,
|
||||||
RVA address = RVA_INVALID);
|
RVA address = RVA_INVALID);
|
||||||
/**
|
|
||||||
* @brief Export image using rizin ag*w command and graphviz.
|
|
||||||
* Requires graphviz dot executable in the path.
|
|
||||||
*
|
|
||||||
* @param filePath output file path
|
|
||||||
* @param type image format as expected by "e graph.gv.format"
|
|
||||||
* @param graphCommand rizin command without type, for example agf
|
|
||||||
* @param address object address if required by command
|
|
||||||
*/
|
|
||||||
void exportRizinGraphvizGraph(QString filePath, QString type, QString graphCommand,
|
|
||||||
RVA address);
|
|
||||||
/**
|
/**
|
||||||
* @brief Export graph in one of the text formats supported by rizin json, gml, SDB key-value
|
* @brief Export graph in one of the text formats supported by rizin json, gml, SDB key-value
|
||||||
* @param filePath output file path
|
* @param filePath - output file path
|
||||||
* @param graphCommand graph command including the format, example "agfd" or "agfg"
|
* @param type - graph type, example RZ_CORE_GRAPH_TYPE_FUNCALL or RZ_CORE_GRAPH_TYPE_IMPORT
|
||||||
* @param address object address if required by command
|
* @param format - graph format, example RZ_CORE_GRAPH_FORMAT_DOT or RZ_CORE_GRAPH_FORMAT_GML
|
||||||
|
* @param address - object address (if global set it to RVA_INVALID)
|
||||||
*/
|
*/
|
||||||
void exportRzTextGraph(QString filePath, QString graphCommand, RVA address);
|
void exportRzTextGraph(QString filePath, RzCoreGraphType type, RzCoreGraphFormat format,
|
||||||
|
RVA address);
|
||||||
static bool graphIsBitamp(GraphExportType type);
|
static bool graphIsBitamp(GraphExportType type);
|
||||||
/**
|
/**
|
||||||
* @brief Show graph export dialog.
|
* @brief Show graph export dialog.
|
||||||
* @param defaultName - default file name in the export dialog
|
* @param defaultName - default file name in the export dialog
|
||||||
* @param graphCommand - rizin graph commmand with graph type and without export type, for
|
* @param type - graph type, example RZ_CORE_GRAPH_TYPE_FUNCALL or RZ_CORE_GRAPH_TYPE_IMPORT
|
||||||
* example afC. Leave empty for non-rizin graphs. In such case only direct image export will be
|
* @param address - object address (if global set it to RVA_INVALID)
|
||||||
* available.
|
|
||||||
* @param address - object address if relevant for \p graphCommand
|
|
||||||
*/
|
*/
|
||||||
void showExportGraphDialog(QString defaultName, QString graphCommand = "",
|
void showExportGraphDialog(QString defaultName, RzCoreGraphType type,
|
||||||
RVA address = RVA_INVALID);
|
RVA address = RVA_INVALID);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
|
@ -194,6 +194,7 @@ void DisassemblerGraphView::loadCurrentGraph()
|
|||||||
|
|
||||||
windowTitle = tr("Graph");
|
windowTitle = tr("Graph");
|
||||||
if (fcn && RZ_STR_ISNOTEMPTY(fcn->name)) {
|
if (fcn && RZ_STR_ISNOTEMPTY(fcn->name)) {
|
||||||
|
currentFcnAddr = fcn->addr;
|
||||||
auto fcnName = fromOwned(rz_str_escape_utf8_for_json(fcn->name, -1));
|
auto fcnName = fromOwned(rz_str_escape_utf8_for_json(fcn->name, -1));
|
||||||
windowTitle += QString("(%0)").arg(fcnName.get());
|
windowTitle += QString("(%0)").arg(fcnName.get());
|
||||||
} else {
|
} else {
|
||||||
@ -891,6 +892,11 @@ void DisassemblerGraphView::contextMenuEvent(QContextMenuEvent *event)
|
|||||||
|
|
||||||
void DisassemblerGraphView::showExportDialog()
|
void DisassemblerGraphView::showExportDialog()
|
||||||
{
|
{
|
||||||
|
if (currentFcnAddr == RVA_INVALID) {
|
||||||
|
qWarning() << "Cannot find current function.";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
QString defaultName = "graph";
|
QString defaultName = "graph";
|
||||||
if (auto f = Core()->functionIn(currentFcnAddr)) {
|
if (auto f = Core()->functionIn(currentFcnAddr)) {
|
||||||
QString functionName = f->name;
|
QString functionName = f->name;
|
||||||
@ -901,7 +907,7 @@ void DisassemblerGraphView::showExportDialog()
|
|||||||
defaultName = functionName;
|
defaultName = functionName;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
showExportGraphDialog(defaultName, "agf", currentFcnAddr);
|
showExportGraphDialog(defaultName, RZ_CORE_GRAPH_TYPE_BLOCK_FUN, currentFcnAddr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DisassemblerGraphView::blockDoubleClicked(GraphView::GraphBlock &block, QMouseEvent *event,
|
void DisassemblerGraphView::blockDoubleClicked(GraphView::GraphBlock &block, QMouseEvent *event,
|
||||||
|
Loading…
Reference in New Issue
Block a user