diff --git a/src/dialog/vsettingsdialog.cpp b/src/dialog/vsettingsdialog.cpp index 4d2c28d3..fcfbd8f9 100644 --- a/src/dialog/vsettingsdialog.cpp +++ b/src/dialog/vsettingsdialog.cpp @@ -912,10 +912,13 @@ VMarkdownTab::VMarkdownTab(QWidget *p_parent) m_plantUMLJarEdit = new VLineEdit(); m_plantUMLJarEdit->setToolTip(tr("Location to the PlantUML JAR executable for local PlantUML")); - m_plantUMLDotEdit = new VLineEdit(); - m_plantUMLDotEdit->setPlaceholderText(tr("Empty to detect automatically")); - m_plantUMLDotEdit->setToolTip(tr("Location to the GraphViz executable for local PlantUML " - "(empty to let PlantUML detect it automatically)")); + // Graphviz. + m_graphvizCB = new QCheckBox(tr("Graphviz")); + m_graphvizCB->setToolTip(tr("Enable Graphviz for drawing graph")); + + m_graphvizDotEdit = new VLineEdit(); + m_graphvizDotEdit->setPlaceholderText(tr("Empty to detect automatically")); + m_graphvizDotEdit->setToolTip(tr("Location to the GraphViz dot executable")); QFormLayout *mainLayout = new QFormLayout(); mainLayout->addRow(tr("Note open mode:"), m_openModeCombo); @@ -924,7 +927,8 @@ VMarkdownTab::VMarkdownTab(QWidget *p_parent) mainLayout->addRow(tr("PlantUML:"), m_plantUMLModeCombo); mainLayout->addRow(tr("PlantUML server:"), m_plantUMLServerEdit); mainLayout->addRow(tr("PlantUML JAR:"), m_plantUMLJarEdit); - mainLayout->addRow(tr("Graphviz executable:"), m_plantUMLDotEdit); + mainLayout->addRow(m_graphvizCB); + mainLayout->addRow(tr("Graphviz executable:"), m_graphvizDotEdit); setLayout(mainLayout); } @@ -947,6 +951,10 @@ bool VMarkdownTab::loadConfiguration() return false; } + if (!loadGraphviz()) { + return false; + } + return true; } @@ -968,6 +976,10 @@ bool VMarkdownTab::saveConfiguration() return false; } + if (!saveGraphviz()) { + return false; + } + return true; } @@ -1044,7 +1056,6 @@ bool VMarkdownTab::loadPlantUML() m_plantUMLModeCombo->setCurrentIndex(m_plantUMLModeCombo->findData(g_config->getPlantUMLMode())); m_plantUMLServerEdit->setText(g_config->getPlantUMLServer()); m_plantUMLJarEdit->setText(g_config->getPlantUMLJar()); - m_plantUMLDotEdit->setText(g_config->getPlantUMLDot()); return true; } @@ -1053,6 +1064,19 @@ bool VMarkdownTab::savePlantUML() g_config->setPlantUMLMode(m_plantUMLModeCombo->currentData().toInt()); g_config->setPlantUMLServer(m_plantUMLServerEdit->text()); g_config->setPlantUMLJar(m_plantUMLJarEdit->text()); - g_config->setPlantUMLDot(m_plantUMLDotEdit->text()); + return true; +} + +bool VMarkdownTab::loadGraphviz() +{ + m_graphvizCB->setChecked(g_config->getEnableGraphviz()); + m_graphvizDotEdit->setText(g_config->getGraphvizDot()); + return true; +} + +bool VMarkdownTab::saveGraphviz() +{ + g_config->setEnableGraphviz(m_graphvizCB->isChecked()); + g_config->setGraphvizDot(m_graphvizDotEdit->text()); return true; } diff --git a/src/dialog/vsettingsdialog.h b/src/dialog/vsettingsdialog.h index 280e95d4..6468a6dc 100644 --- a/src/dialog/vsettingsdialog.h +++ b/src/dialog/vsettingsdialog.h @@ -160,6 +160,9 @@ private: bool loadPlantUML(); bool savePlantUML(); + bool loadGraphviz(); + bool saveGraphviz(); + // Default note open mode for markdown. QComboBox *m_openModeCombo; @@ -174,7 +177,10 @@ private: QComboBox *m_plantUMLModeCombo; VLineEdit *m_plantUMLServerEdit; VLineEdit *m_plantUMLJarEdit; - VLineEdit *m_plantUMLDotEdit; + + // Graphviz. + QCheckBox *m_graphvizCB; + VLineEdit *m_graphvizDotEdit; }; class VSettingsDialog : public QDialog diff --git a/src/resources/hoedown.js b/src/resources/hoedown.js index 7cb90cbe..cbaa9a0b 100644 --- a/src/resources/hoedown.js +++ b/src/resources/hoedown.js @@ -25,6 +25,7 @@ var updateHtml = function(html) { var codes = document.getElementsByTagName('code'); mermaidIdx = 0; plantUMLIdx = 0; + graphvizIdx = 0; for (var i = 0; i < codes.length; ++i) { var code = codes[i]; if (code.parentElement.tagName.toLowerCase() == 'pre') { @@ -59,9 +60,15 @@ var updateHtml = function(html) { renderPlantUMLOneLocal(code); } + continue; + } else if (VEnableGraphviz + && code.classList.contains('language-dot')) { + // Graphviz code block. + renderGraphvizOneLocal(code); continue; } + if (listContainsRegex(code.classList, /language-.*/)) { hljs.highlightBlock(code); } diff --git a/src/resources/markdown-it.js b/src/resources/markdown-it.js index 98503c47..049779a4 100644 --- a/src/resources/markdown-it.js +++ b/src/resources/markdown-it.js @@ -116,6 +116,7 @@ var updateText = function(text) { renderMermaid('lang-mermaid'); renderFlowchart(['lang-flowchart', 'lang-flow']); renderPlantUML('lang-puml'); + renderGraphviz('lang-dot'); addClassToCodeBlock(); renderCodeBlockLineNumber(); diff --git a/src/resources/markdown_template.js b/src/resources/markdown_template.js index 1384ddb7..023d4df3 100644 --- a/src/resources/markdown_template.js +++ b/src/resources/markdown_template.js @@ -1,3 +1,5 @@ +var channelInitialized = false; + var content; // Current header index in all headers. @@ -45,6 +47,18 @@ if (typeof VPlantUMLServer == 'undefined') { VPlantUMLServer = 'http://www.plantuml.com/plantuml'; } +if (typeof VPlantUMLFormat == 'undefined') { + VPlantUMLFormat = 'svg'; +} + +if (typeof VEnableGraphviz == 'undefined') { + VEnableGraphviz = false; +} + +if (typeof VGraphvizFormat == 'undefined') { + VGraphvizFormat = 'svg'; +} + // Add a caption (using alt text) under the image. var VImageCenterClass = 'img-center'; var VImageCaptionClass = 'img-caption'; @@ -123,14 +137,7 @@ var htmlContent = function() { new QWebChannel(qt.webChannelTransport, function(channel) { content = channel.objects.content; - if (typeof updateHtml == "function") { - updateHtml(content.html); - content.htmlChanged.connect(updateHtml); - } - if (typeof updateText == "function") { - content.textChanged.connect(updateText); - content.updateText(); - } + content.requestScrollToAnchor.connect(scrollToAnchor); if (typeof highlightText == "function") { @@ -148,6 +155,19 @@ new QWebChannel(qt.webChannelTransport, } content.plantUMLResultReady.connect(handlePlantUMLResult); + content.graphvizResultReady.connect(handleGraphvizResult); + + if (typeof updateHtml == "function") { + updateHtml(content.html); + content.htmlChanged.connect(updateHtml); + } + + if (typeof updateText == "function") { + content.textChanged.connect(updateText); + content.updateText(); + } + + channelInitialized = true; }); var VHighlightedAnchorClass = 'highlighted-anchor'; @@ -686,6 +706,33 @@ var renderPlantUMLOneLocal = function(code) { plantUMLIdx++; }; +var graphvizIdx = 0; +var graphvizCodeClass = 'graphviz_code_'; + +// @className, the class name of the Graghviz code block, such as 'lang-dot'. +var renderGraphviz = function(className) { + if (!VEnableGraphviz) { + return; + } + + graphvizIdx = 0; + + var codes = document.getElementsByTagName('code'); + for (var i = 0; i < codes.length; ++i) { + var code = codes[i]; + if (code.classList.contains(className)) { + renderGraphvizOneLocal(code); + } + } +}; + +var renderGraphvizOneLocal = function(code) { + ++asyncJobsCount; + code.classList.add(graphvizCodeClass + graphvizIdx); + content.processGraphviz(graphvizIdx, VGraphvizFormat, code.textContent); + graphvizIdx++; +}; + var isImageBlock = function(img) { var pn = img.parentNode; return (pn.children.length == 1) && (pn.textContent == ''); @@ -1260,7 +1307,8 @@ var specialCodeBlock = function(lang) { return (VEnableMathjax && lang == 'mathjax') || (VEnableMermaid && lang == 'mermaid') || (VEnableFlowchart && (lang == 'flowchart' || lang == 'flow')) - || (VPlantUMLMode != 0 && lang == 'puml'); + || (VPlantUMLMode != 0 && lang == 'puml') + || (VEnableGraphviz && lang == 'dot'); }; var handlePlantUMLResult = function(id, format, result) { @@ -1282,3 +1330,22 @@ var handlePlantUMLResult = function(id, format, result) { finishOneAsyncJob(); }; + +var handleGraphvizResult = function(id, format, result) { + var code = document.getElementsByClassName(graphvizCodeClass + id)[0]; + if (code && result.length > 0) { + var obj = null; + if (format == 'svg') { + obj = document.createElement('p'); + obj.innerHTML = result; + } else { + obj = document.createElement('img'); + obj.src = "data:image/" + format + ";base64, " + result; + } + + var preNode = code.parentNode; + preNode.parentNode.replaceChild(obj, preNode); + } + + finishOneAsyncJob(); +}; diff --git a/src/resources/marked.js b/src/resources/marked.js index dd198b6c..67e0a9b3 100644 --- a/src/resources/marked.js +++ b/src/resources/marked.js @@ -60,6 +60,7 @@ var updateText = function(text) { renderMermaid('lang-mermaid'); renderFlowchart(['lang-flowchart', 'lang-flow']); renderPlantUML('lang-puml'); + renderGraphviz('lang-dot'); addClassToCodeBlock(); renderCodeBlockLineNumber(); diff --git a/src/resources/showdown.js b/src/resources/showdown.js index aaeace80..17ce9069 100644 --- a/src/resources/showdown.js +++ b/src/resources/showdown.js @@ -49,7 +49,12 @@ var mdHasTocSection = function(markdown) { return n != -1; }; -var highlightCodeBlocks = function(doc, enableMermaid, enableFlowchart, enableMathJax, enablePlantUML) { +var highlightCodeBlocks = function(doc, + enableMermaid, + enableFlowchart, + enableMathJax, + enablePlantUML, + enableGraphviz) { var codes = doc.getElementsByTagName('code'); for (var i = 0; i < codes.length; ++i) { var code = codes[i]; @@ -68,6 +73,9 @@ var highlightCodeBlocks = function(doc, enableMermaid, enableFlowchart, enableMa } else if (enablePlantUML && code.classList.contains('language-puml')) { // PlantUML code block. continue; + } else if (enableGraphviz && code.classList.contains('language-dot')) { + // Graphviz code block. + continue; } if (listContainsRegex(code.classList, /language-.*/)) { @@ -89,10 +97,16 @@ var updateText = function(text) { placeholder.innerHTML = html; handleToc(needToc); insertImageCaption(); - highlightCodeBlocks(document, VEnableMermaid, VEnableFlowchart, VEnableMathjax, VPlantUMLMode != 0); + highlightCodeBlocks(document, + VEnableMermaid, + VEnableFlowchart, + VEnableMathjax, + VPlantUMLMode != 0, + VEnableGraphviz); renderMermaid('language-mermaid'); renderFlowchart(['language-flowchart', 'language-flow']); renderPlantUML('language-puml'); + renderGraphviz('language-dot'); addClassToCodeBlock(); renderCodeBlockLineNumber(); diff --git a/src/resources/vnote.ini b/src/resources/vnote.ini index c8c40086..f6834830 100644 --- a/src/resources/vnote.ini +++ b/src/resources/vnote.ini @@ -49,6 +49,9 @@ enable_flowchart=false ; 2 - local PlantUML plantuml_mode=0 +; Enable Graphviz +enable_graphviz=false + ; -1 - calculate the factor web_zoom_factor=-1 @@ -277,8 +280,8 @@ plantuml_server=http://www.plantuml.com/plantuml ; PlantUML JAR location plantuml_jar= -; PlantUML Graphviz Dot location -plantuml_dot= +; Graphviz Dot location +graphviz_dot= [shortcuts] ; Define shortcuts here, with each item in the form "operation=keysequence". diff --git a/src/src.pro b/src/src.pro index 9c22dafe..b6efef2a 100644 --- a/src/src.pro +++ b/src/src.pro @@ -126,7 +126,8 @@ SOURCES += main.cpp\ vhelpue.cpp \ vlistfolderue.cpp \ dialog/vfixnotebookdialog.cpp \ - vplantumlhelper.cpp + vplantumlhelper.cpp \ + vgraphvizhelper.cpp HEADERS += vmainwindow.h \ vdirectorytree.h \ @@ -243,7 +244,8 @@ HEADERS += vmainwindow.h \ vhelpue.h \ vlistfolderue.h \ dialog/vfixnotebookdialog.h \ - vplantumlhelper.h + vplantumlhelper.h \ + vgraphvizhelper.h RESOURCES += \ vnote.qrc \ diff --git a/src/utils/vutils.cpp b/src/utils/vutils.cpp index d8bceb49..eaa568fa 100644 --- a/src/utils/vutils.cpp +++ b/src/utils/vutils.cpp @@ -736,6 +736,13 @@ QString VUtils::generateHtmlTemplate(const QString &p_template, extraFile += QString("\n").arg(format); } + if (g_config->getEnableGraphviz()) { + extraFile += "\n"; + + QString format = p_isPDF ? "png" : "svg"; + extraFile += QString("\n").arg(format); + } + if (g_config->getEnableImageCaption()) { extraFile += "\n"; } diff --git a/src/vconfigmanager.cpp b/src/vconfigmanager.cpp index 5e2298bb..f775a2a5 100644 --- a/src/vconfigmanager.cpp +++ b/src/vconfigmanager.cpp @@ -288,7 +288,9 @@ void VConfigManager::initialize() m_plantUMLMode = getConfigFromSettings("global", "plantuml_mode").toInt(); m_plantUMLServer = getConfigFromSettings("web", "plantuml_server").toString(); m_plantUMLJar = getConfigFromSettings("web", "plantuml_jar").toString(); - m_plantUMLDot = getConfigFromSettings("web", "plantuml_dot").toString(); + + m_enableGraphviz = getConfigFromSettings("global", "enable_graphviz").toBool(); + m_graphvizDot = getConfigFromSettings("web", "graphviz_dot").toString(); } void VConfigManager::initSettings() diff --git a/src/vconfigmanager.h b/src/vconfigmanager.h index ff8ca64c..4c7dad67 100644 --- a/src/vconfigmanager.h +++ b/src/vconfigmanager.h @@ -210,6 +210,9 @@ public: bool getEnableMathjax() const; void setEnableMathjax(bool p_enabled); + bool getEnableGraphviz() const; + void setEnableGraphviz(bool p_enabled); + int getPlantUMLMode() const; void setPlantUMLMode(int p_mode); @@ -469,8 +472,8 @@ public: const QString &getPlantUMLJar() const; void setPlantUMLJar(const QString &p_jarPath); - const QString &getPlantUMLDot() const; - void setPlantUMLDot(const QString &p_dotPath); + const QString &getGraphvizDot() const; + void setGraphvizDot(const QString &p_dotPath); private: // Look up a config from user and default settings. @@ -634,6 +637,11 @@ private: // Enable Mathjax. bool m_enableMathjax; + // Enable Graphviz. + bool m_enableGraphviz; + + QString m_graphvizDot; + // Zoom factor of the QWebEngineView. qreal m_webZoomFactor; @@ -871,8 +879,6 @@ private: QString m_plantUMLJar; - QString m_plantUMLDot; - // The name of the config file in each directory, obsolete. // Use c_dirConfigFile instead. static const QString c_obsoleteDirConfigFile; @@ -1351,6 +1357,21 @@ inline void VConfigManager::setEnableMathjax(bool p_enabled) setConfigToSettings("global", "enable_mathjax", m_enableMathjax); } +inline bool VConfigManager::getEnableGraphviz() const +{ + return m_enableGraphviz; +} + +inline void VConfigManager::setEnableGraphviz(bool p_enabled) +{ + if (m_enableGraphviz == p_enabled) { + return; + } + + m_enableGraphviz = p_enabled; + setConfigToSettings("global", "enable_graphviz", m_enableGraphviz); +} + inline int VConfigManager::getPlantUMLMode() const { return m_plantUMLMode; @@ -2217,18 +2238,18 @@ inline void VConfigManager::setPlantUMLJar(const QString &p_jarPath) setConfigToSettings("web", "plantuml_jar", p_jarPath); } -inline const QString &VConfigManager::getPlantUMLDot() const +inline const QString &VConfigManager::getGraphvizDot() const { - return m_plantUMLDot; + return m_graphvizDot; } -inline void VConfigManager::setPlantUMLDot(const QString &p_dotPath) +inline void VConfigManager::setGraphvizDot(const QString &p_dotPath) { - if (m_plantUMLDot == p_dotPath) { + if (m_graphvizDot == p_dotPath) { return; } - m_plantUMLDot = p_dotPath; - setConfigToSettings("web", "plantuml_dot", p_dotPath); + m_graphvizDot = p_dotPath; + setConfigToSettings("web", "graphviz_dot", p_dotPath); } #endif // VCONFIGMANAGER_H diff --git a/src/vdocument.cpp b/src/vdocument.cpp index 0c6c4fe9..62a1e171 100644 --- a/src/vdocument.cpp +++ b/src/vdocument.cpp @@ -4,12 +4,14 @@ #include "vfile.h" #include "vplantumlhelper.h" +#include "vgraphvizhelper.h" VDocument::VDocument(const VFile *v_file, QObject *p_parent) : QObject(p_parent), m_file(v_file), m_readyToHighlight(false), - m_plantUMLHelper(NULL) + m_plantUMLHelper(NULL), + m_graphvizHelper(NULL) { } @@ -142,10 +144,19 @@ void VDocument::processPlantUML(int p_id, const QString &p_format, const QString if (!m_plantUMLHelper) { m_plantUMLHelper = new VPlantUMLHelper(this); connect(m_plantUMLHelper, &VPlantUMLHelper::resultReady, - this, [this](int p_id, const QString &p_format, const QString &p_result) { - emit plantUMLResultReady(p_id, p_format, p_result); - }); + this, &VDocument::plantUMLResultReady); } m_plantUMLHelper->processAsync(p_id, p_format, p_text); } + +void VDocument::processGraphviz(int p_id, const QString &p_format, const QString &p_text) +{ + if (!m_graphvizHelper) { + m_graphvizHelper = new VGraphvizHelper(this); + connect(m_graphvizHelper, &VGraphvizHelper::resultReady, + this, &VDocument::graphvizResultReady); + } + + m_graphvizHelper->processAsync(p_id, p_format, p_text); +} diff --git a/src/vdocument.h b/src/vdocument.h index 097b11db..ebc72737 100644 --- a/src/vdocument.h +++ b/src/vdocument.h @@ -8,6 +8,7 @@ class VFile; class VPlantUMLHelper; +class VGraphvizHelper; class VDocument : public QObject { @@ -86,6 +87,9 @@ public slots: // Web-side call this to process PlantUML locally. void processPlantUML(int p_id, const QString &p_format, const QString &p_text); + // Web-side call this to process Graphviz locally. + void processGraphviz(int p_id, const QString &p_format, const QString &p_text); + signals: void textChanged(const QString &text); @@ -124,6 +128,8 @@ signals: void plantUMLResultReady(int p_id, const QString &p_format, const QString &p_result); + void graphvizResultReady(int p_id, const QString &p_format, const QString &p_result); + private: QString m_toc; QString m_header; @@ -145,6 +151,8 @@ private: VWordCountInfo m_wordCountInfo; VPlantUMLHelper *m_plantUMLHelper; + + VGraphvizHelper *m_graphvizHelper; }; inline bool VDocument::isReadyToHighlight() const diff --git a/src/veditarea.cpp b/src/veditarea.cpp index 8a81344d..a0d37f1c 100644 --- a/src/veditarea.cpp +++ b/src/veditarea.cpp @@ -1012,6 +1012,7 @@ bool VEditArea::activateNextTabByCaptain(void *p_target, void *p_data) VEditWindow *win = obj->getCurrentWindow(); if (win) { win->focusNextTab(true); + return false; } return true; diff --git a/src/vgraphvizhelper.cpp b/src/vgraphvizhelper.cpp new file mode 100644 index 00000000..a26bc4b7 --- /dev/null +++ b/src/vgraphvizhelper.cpp @@ -0,0 +1,83 @@ +#include "vgraphvizhelper.h" + +#include +#include + +#include "vconfigmanager.h" + +extern VConfigManager *g_config; + +#define TaskIdProperty "GraphvizTaskId" +#define TaskFormatProperty "GraphvizTaskFormat" + +VGraphvizHelper::VGraphvizHelper(QObject *p_parent) + : QObject(p_parent) +{ + prepareCommand(m_program, m_args); +} + +void VGraphvizHelper::processAsync(int p_id, const QString &p_format, const QString &p_text) +{ + QProcess *process = new QProcess(this); + process->setProperty(TaskIdProperty, p_id); + process->setProperty(TaskFormatProperty, p_format); + connect(process, SIGNAL(finished(int, QProcess::ExitStatus)), + this, SLOT(handleProcessFinished(int, QProcess::ExitStatus))); + + QStringList args(m_args); + args << ("-T" + p_format); + + qDebug() << m_program << args; + + process->start(m_program, args); + process->write(p_text.toUtf8()); + process->closeWriteChannel(); +} + +void VGraphvizHelper::prepareCommand(QString &p_program, QStringList &p_args) const +{ + const QString &dot = g_config->getGraphvizDot(); + if (dot.isEmpty()) { + p_program = "dot"; + } else { + p_program = dot; + } + + p_args.clear(); +} + +void VGraphvizHelper::handleProcessFinished(int p_exitCode, QProcess::ExitStatus p_exitStatus) +{ + QProcess *process = static_cast(sender()); + int id = process->property(TaskIdProperty).toInt(); + QString format = process->property(TaskFormatProperty).toString(); + qDebug() << "process finished" << id << format << p_exitCode << p_exitStatus; + bool failed = true; + if (p_exitStatus == QProcess::NormalExit) { + if (p_exitCode < 0) { + qWarning() << "Graphviz fail" << p_exitCode; + } else { + failed = false; + QByteArray outBa = process->readAllStandardOutput(); + if (format == "svg") { + emit resultReady(id, format, QString::fromLocal8Bit(outBa)); + } else { + emit resultReady(id, format, QString::fromLocal8Bit(outBa.toBase64())); + } + } + } else { + qWarning() << "fail to start Graphviz process" << p_exitCode << p_exitStatus; + } + + if (failed) { + QByteArray errBa = process->readAllStandardError(); + if (!errBa.isEmpty()) { + QString errStr(QString::fromLocal8Bit(errBa)); + qWarning() << "Graphviz stderr:" << errStr; + } + + emit resultReady(id, format, ""); + } + + process->deleteLater(); +} diff --git a/src/vgraphvizhelper.h b/src/vgraphvizhelper.h new file mode 100644 index 00000000..ac49c12c --- /dev/null +++ b/src/vgraphvizhelper.h @@ -0,0 +1,30 @@ +#ifndef VGRAPHVIZHELPER_H +#define VGRAPHVIZHELPER_H + +#include + +#include +#include + +class VGraphvizHelper : public QObject +{ + Q_OBJECT +public: + explicit VGraphvizHelper(QObject *p_parent = nullptr); + + void processAsync(int p_id, const QString &p_format, const QString &p_text); + + void prepareCommand(QString &p_cmd, QStringList &p_args) const; + +signals: + void resultReady(int p_id, const QString &p_format, const QString &p_result); + +private slots: + void handleProcessFinished(int p_exitCode, QProcess::ExitStatus p_exitStatus); + +private: + QString m_program; + QStringList m_args; +}; + +#endif // VGRAPHVIZHELPER_H diff --git a/src/vplantumlhelper.cpp b/src/vplantumlhelper.cpp index f942cabd..9b2e1104 100644 --- a/src/vplantumlhelper.cpp +++ b/src/vplantumlhelper.cpp @@ -44,7 +44,7 @@ void VPlantUMLHelper::prepareCommand(QString &p_program, QStringList &p_args) co int nbthread = QThread::idealThreadCount(); p_args << "-nbthread" << QString::number(nbthread > 0 ? nbthread : 1); - const QString &dot = g_config->getPlantUMLDot(); + const QString &dot = g_config->getGraphvizDot(); if (!dot.isEmpty()) { p_args << "-graphvizdot"; p_args << dot;