瀏覽代碼

MdEditor: support copying diagram in puml and graphviz

Le Tan 7 年之前
父節點
當前提交
d4daf32f20

+ 7 - 0
src/pegmarkdownhighlighter.h

@@ -44,6 +44,8 @@ public:
 
     const QVector<VElementRegion> &getImageRegions() const;
 
+    const QVector<VCodeBlock> &getCodeBlocks() const;
+
 public slots:
     // Parse and rehighlight immediately.
     void updateHighlight();
@@ -360,4 +362,9 @@ inline bool PegMarkdownHighlighter::isFastParseBlock(int p_blockNum) const
 {
     return p_blockNum >= m_fastParseBlocks.first && p_blockNum <= m_fastParseBlocks.second;
 }
+
+inline const QVector<VCodeBlock> &PegMarkdownHighlighter::getCodeBlocks() const
+{
+    return m_result->m_codeBlocks;
+}
 #endif // PEGMARKDOWNHIGHLIGHTER_H

+ 9 - 0
src/utils/veditutils.cpp

@@ -7,6 +7,7 @@
 #include <QScrollBar>
 
 #include "vutils.h"
+#include "vcodeblockhighlighthelper.h"
 
 void VEditUtils::removeBlock(QTextBlock &p_block, QString *p_text)
 {
@@ -1083,3 +1084,11 @@ bool VEditUtils::isWordSeparator(QChar p_char)
 
     return false;
 }
+
+QString VEditUtils::removeCodeBlockFence(const QString &p_text)
+{
+    QString text = VCodeBlockHighlightHelper::unindentCodeBlock(p_text);
+    Q_ASSERT(text.startsWith("```") && text.endsWith("```"));
+    int idx = text.indexOf('\n') + 1;
+    return text.mid(idx, text.size() - idx - 3);
+}

+ 3 - 0
src/utils/veditutils.h

@@ -211,6 +211,9 @@ public:
 
     static bool isWordSeparator(QChar p_char);
 
+    // Remove the fence of fenced code block.
+    static QString removeCodeBlockFence(const QString &p_text);
+
 private:
     VEditUtils() {}
 };

+ 40 - 13
src/utils/vprocessutils.cpp

@@ -11,24 +11,36 @@ int VProcessUtils::startProcess(const QString &p_program,
                                 QByteArray &p_out,
                                 QByteArray &p_err)
 {
-    int ret = 0;
     QScopedPointer<QProcess> process(new QProcess());
     process->start(p_program, p_args);
+    return startProcess(process.data(),
+                        p_in,
+                        p_exitCode,
+                        p_out,
+                        p_err);
+}
 
+int VProcessUtils::startProcess(QProcess *p_process,
+                                const QByteArray &p_in,
+                                int &p_exitCode,
+                                QByteArray &p_out,
+                                QByteArray &p_err)
+{
+    int ret = 0;
     if (!p_in.isEmpty()) {
-        if (process->write(p_in) == -1) {
-            process->closeWriteChannel();
-            qWarning() << "fail to write to QProcess:" << process->errorString();
+        if (p_process->write(p_in) == -1) {
+            p_process->closeWriteChannel();
+            qWarning() << "fail to write to QProcess:" << p_process->errorString();
             return -1;
         } else {
-            process->closeWriteChannel();
+            p_process->closeWriteChannel();
         }
     }
 
     bool finished = false;
     bool started = false;
     while (true) {
-        QProcess::ProcessError err = process->error();
+        QProcess::ProcessError err = p_process->error();
         if (err == QProcess::FailedToStart
             || err == QProcess::Crashed) {
             if (err == QProcess::FailedToStart) {
@@ -41,34 +53,34 @@ int VProcessUtils::startProcess(const QString &p_program,
         }
 
         if (started) {
-            if (process->state() == QProcess::NotRunning) {
+            if (p_process->state() == QProcess::NotRunning) {
                 finished = true;
             }
         } else {
-            if (process->state() != QProcess::NotRunning) {
+            if (p_process->state() != QProcess::NotRunning) {
                 started = true;
             }
         }
 
-        if (process->waitForFinished(500)) {
+        if (p_process->waitForFinished(500)) {
             // Finished.
             finished = true;
         }
 
         if (finished) {
-            QProcess::ExitStatus sta = process->exitStatus();
+            QProcess::ExitStatus sta = p_process->exitStatus();
             if (sta == QProcess::CrashExit) {
                 ret = -1;
                 break;
             }
 
-            p_exitCode = process->exitCode();
+            p_exitCode = p_process->exitCode();
             break;
         }
     }
 
-    p_out = process->readAllStandardOutput();
-    p_err = process->readAllStandardError();
+    p_out = p_process->readAllStandardOutput();
+    p_err = p_process->readAllStandardError();
 
     return ret;
 }
@@ -86,3 +98,18 @@ int VProcessUtils::startProcess(const QString &p_program,
                         p_out,
                         p_err);
 }
+
+int VProcessUtils::startProcess(const QString &p_cmd,
+                                const QByteArray &p_in,
+                                int &p_exitCode,
+                                QByteArray &p_out,
+                                QByteArray &p_err)
+{
+    QScopedPointer<QProcess> process(new QProcess());
+    process->start(p_cmd);
+    return startProcess(process.data(),
+                        p_in,
+                        p_exitCode,
+                        p_out,
+                        p_err);
+}

+ 13 - 0
src/utils/vprocessutils.h

@@ -4,6 +4,7 @@
 #include <QStringList>
 #include <QByteArray>
 
+class QProcess;
 
 class VProcessUtils
 {
@@ -25,8 +26,20 @@ public:
                             QByteArray &p_out,
                             QByteArray &p_err);
 
+    static int startProcess(const QString &p_cmd,
+                            const QByteArray &p_in,
+                            int &p_exitCode,
+                            QByteArray &p_out,
+                            QByteArray &p_err);
+
 private:
     VProcessUtils() {}
+
+    static int startProcess(QProcess *p_process,
+                            const QByteArray &p_in,
+                            int &p_exitCode,
+                            QByteArray &p_out,
+                            QByteArray &p_err);
 };
 
 #endif // VPROCESSUTILS_H

+ 11 - 0
src/veditor.cpp

@@ -35,6 +35,17 @@ VEditor::~VEditor()
     if (m_completer->widget() == m_editor) {
         m_completer->setWidget(NULL);
     }
+
+    cleanUp();
+}
+
+void VEditor::cleanUp()
+{
+    for (auto const & file : m_tempFiles) {
+        VUtils::deleteFile(file);
+    }
+
+    m_tempFiles.clear();
 }
 
 void VEditor::init()

+ 11 - 0
src/veditor.h

@@ -254,6 +254,8 @@ protected:
 
     virtual int lineNumberAreaWidth() const = 0;
 
+    void addTempFile(const QString &p_file);
+
     QWidget *m_editor;
 
     VEditorObject *m_object;
@@ -309,6 +311,8 @@ private:
 
     QStringList generateCompletionCandidates() const;
 
+    void cleanUp();
+
     QLabel *m_wrapLabel;
     QTimer *m_labelTimer;
 
@@ -352,6 +356,9 @@ private:
 
     QSharedPointer<VTextEditCompleter> m_completer;
 
+    // Temp files needed to be delete.
+    QStringList m_tempFiles;
+
 // Functions for private slots.
 private:
     void labelTimerTimeout();
@@ -456,4 +463,8 @@ inline QWidget *VEditor::getEditor() const
     return m_editor;
 }
 
+inline void VEditor::addTempFile(const QString &p_file)
+{
+    m_tempFiles.append(p_file);
+}
 #endif // VEDITOR_H

+ 23 - 0
src/vgraphvizhelper.cpp

@@ -119,3 +119,26 @@ bool VGraphvizHelper::testGraphviz(const QString &p_dot, QString &p_msg)
 
     return ret == 0 && exitCode == 0;
 }
+
+QByteArray VGraphvizHelper::process(const QString &p_format, const QString &p_text)
+{
+    VGraphvizHelper inst;
+
+    int exitCode = -1;
+    QByteArray out, err;
+
+    QStringList args(inst.m_args);
+    args << ("-T" + p_format);
+    int ret = VProcessUtils::startProcess(inst.m_program,
+                                          args,
+                                          p_text.toUtf8(),
+                                          exitCode,
+                                          out,
+                                          err);
+
+    if (ret != 0 || exitCode < 0) {
+        qWarning() << "Graphviz fail" << ret << exitCode << QString::fromLocal8Bit(err);
+    }
+
+    return out;
+}

+ 4 - 2
src/vgraphvizhelper.h

@@ -16,10 +16,10 @@ public:
 
     void processAsync(int p_id, TimeStamp p_timeStamp, const QString &p_format, const QString &p_text);
 
-    void prepareCommand(QString &p_cmd, QStringList &p_args) const;
-
     static bool testGraphviz(const QString &p_dot, QString &p_msg);
 
+    static QByteArray process(const QString &p_format, const QString &p_text);
+
 signals:
     void resultReady(int p_id, TimeStamp p_timeStamp, const QString &p_format, const QString &p_result);
 
@@ -27,6 +27,8 @@ private slots:
     void handleProcessFinished(int p_exitCode, QProcess::ExitStatus p_exitStatus);
 
 private:
+    void prepareCommand(QString &p_cmd, QStringList &p_args) const;
+
     QString m_program;
     QStringList m_args;
 };

+ 8 - 16
src/vlivepreviewhelper.cpp

@@ -8,10 +8,10 @@
 #include "vconfigmanager.h"
 #include "vgraphvizhelper.h"
 #include "vplantumlhelper.h"
-#include "vcodeblockhighlighthelper.h"
 #include "vmainwindow.h"
 #include "veditarea.h"
 #include "vmathjaxpreviewhelper.h"
+#include "utils/veditutils.h"
 
 extern VConfigManager *g_config;
 
@@ -249,14 +249,6 @@ void VLivePreviewHelper::handleCursorPositionChanged()
     }
 }
 
-static QString removeFence(const QString &p_text)
-{
-    QString text = VCodeBlockHighlightHelper::unindentCodeBlock(p_text);
-    Q_ASSERT(text.startsWith("```") && text.endsWith("```"));
-    int idx = text.indexOf('\n') + 1;
-    return text.mid(idx, text.size() - idx - 3);
-}
-
 void VLivePreviewHelper::updateLivePreview()
 {
     if (m_cbIndex < 0) {
@@ -277,7 +269,7 @@ void VLivePreviewHelper::updateLivePreview()
             m_graphvizHelper->processAsync(m_cbIndex | LANG_PREFIX_GRAPHVIZ | TYPE_LIVE_PREVIEW,
                                            m_timeStamp,
                                            "svg",
-                                           removeFence(vcb.m_text));
+                                           VEditUtils::removeCodeBlockFence(vcb.m_text));
         } else {
             m_document->setPreviewContent(vcb.m_lang, cb.imageData());
         }
@@ -292,7 +284,7 @@ void VLivePreviewHelper::updateLivePreview()
             m_plantUMLHelper->processAsync(m_cbIndex | LANG_PREFIX_PLANTUML | TYPE_LIVE_PREVIEW,
                                            m_timeStamp,
                                            "svg",
-                                           removeFence(vcb.m_text));
+                                           VEditUtils::removeCodeBlockFence(vcb.m_text));
         } else {
             m_document->setPreviewContent(vcb.m_lang, cb.imageData());
         }
@@ -300,7 +292,7 @@ void VLivePreviewHelper::updateLivePreview()
         // No need to live preview MathJax.
         m_document->previewCodeBlock(m_cbIndex,
                                      vcb.m_lang,
-                                     removeFence(vcb.m_text),
+                                     VEditUtils::removeCodeBlockFence(vcb.m_text),
                                      true);
     }
 }
@@ -418,7 +410,7 @@ void VLivePreviewHelper::processForInplacePreview(int p_idx)
         m_graphvizHelper->processAsync(p_idx | LANG_PREFIX_GRAPHVIZ | TYPE_INPLACE_PREVIEW,
                                        m_timeStamp,
                                        "svg",
-                                       removeFence(vcb.m_text));
+                                       VEditUtils::removeCodeBlockFence(vcb.m_text));
     } else if (vcb.m_lang == "puml" && m_plantUMLMode == PlantUMLMode::LocalPlantUML) {
         if (!m_plantUMLHelper) {
             m_plantUMLHelper = new VPlantUMLHelper(this);
@@ -429,19 +421,19 @@ void VLivePreviewHelper::processForInplacePreview(int p_idx)
         m_plantUMLHelper->processAsync(p_idx | LANG_PREFIX_PLANTUML | TYPE_INPLACE_PREVIEW,
                                        m_timeStamp,
                                        "svg",
-                                       removeFence(vcb.m_text));
+                                       VEditUtils::removeCodeBlockFence(vcb.m_text));
     } else if (vcb.m_lang == "flow"
                || vcb.m_lang == "flowchart") {
         m_mathJaxHelper->previewDiagram(m_mathJaxID,
                                         p_idx,
                                         m_timeStamp,
                                         vcb.m_lang,
-                                        removeFence(vcb.m_text));
+                                        VEditUtils::removeCodeBlockFence(vcb.m_text));
     } else if (vcb.m_lang == "mathjax") {
         m_mathJaxHelper->previewMathJax(m_mathJaxID,
                                         p_idx,
                                         m_timeStamp,
-                                        removeFence(vcb.m_text));
+                                        VEditUtils::removeCodeBlockFence(vcb.m_text));
     }
 }
 

+ 125 - 0
src/vmdeditor.cpp

@@ -25,6 +25,8 @@
 #include "utils/vwebutils.h"
 #include "dialog/vinsertlinkdialog.h"
 #include "utils/vclipboardutils.h"
+#include "vplantumlhelper.h"
+#include "vgraphvizhelper.h"
 
 extern VWebUtils *g_webUtils;
 
@@ -1604,7 +1606,16 @@ void VMdEditor::initLinkAndPreviewMenu(QAction *p_before, QMenu *p_menu, const Q
         return;
     }
 
+    bool needSeparator = false;
     if (initInPlacePreviewMenu(p_before, p_menu, block, pos)) {
+        needSeparator = true;
+    }
+
+    if (initExportAndCopyMenu(p_before, p_menu, block, pos)) {
+        needSeparator = true;
+    }
+
+    if (needSeparator) {
         p_menu->insertSeparator(p_before ? p_before : NULL);
     }
 }
@@ -1665,3 +1676,117 @@ bool VMdEditor::initInPlacePreviewMenu(QAction *p_before,
     p_menu->insertAction(p_before, copyImageAct);
     return true;
 }
+
+bool VMdEditor::initExportAndCopyMenu(QAction *p_before,
+                                      QMenu *p_menu,
+                                      const QTextBlock &p_block,
+                                      int p_pos)
+{
+    Q_UNUSED(p_pos);
+    int state = p_block.userState();
+    if (state != HighlightBlockState::CodeBlockStart
+        && state != HighlightBlockState::CodeBlock
+        && state != HighlightBlockState::CodeBlockEnd) {
+        return false;
+    }
+
+    int blockNum = p_block.blockNumber();
+    const QVector<VCodeBlock> &cbs = m_pegHighlighter->getCodeBlocks();
+    int idx = 0;
+    for (idx = 0; idx < cbs.size(); ++idx) {
+        if (cbs[idx].m_startBlock <= blockNum
+            && cbs[idx].m_endBlock >= blockNum) {
+            break;
+        }
+    }
+
+    if (idx >= cbs.size()) {
+        return false;
+    }
+
+    const VCodeBlock &cb = cbs[idx];
+    if (cb.m_lang != "puml" && cb.m_lang != "dot") {
+        return false;
+    }
+
+    QMenu *subMenu = new QMenu(tr("Copy Diagram"), p_menu);
+    subMenu->setToolTipsVisible(true);
+
+    QAction *pngAct = new QAction(tr("PNG"), subMenu);
+    pngAct->setToolTip(tr("Export diagram as PNG to a temporary file and copy"));
+    connect(pngAct, &QAction::triggered,
+            this, [this, lang = cb.m_lang, text = cb.m_text]() {
+                exportDiagramAndCopy(lang, text, "png");
+            });
+    subMenu->addAction(pngAct);
+
+    QAction *svgAct = new QAction(tr("SVG"), subMenu);
+    svgAct->setToolTip(tr("Export diagram as SVG to a temporary file and copy"));
+    connect(svgAct, &QAction::triggered,
+            this, [this, lang = cb.m_lang, text = cb.m_text]() {
+                exportDiagramAndCopy(lang, text, "svg");
+            });
+    subMenu->addAction(svgAct);
+
+    p_menu->insertMenu(p_before, subMenu);
+    return true;
+}
+
+void VMdEditor::exportDiagramAndCopy(const QString &p_lang,
+                                     const QString &p_text,
+                                     const QString &p_format)
+{
+    m_exportTempFile.reset(new QTemporaryFile(QDir::tempPath()
+                                              + QDir::separator()
+                                              + "XXXXXX." + p_format));
+    if (!m_exportTempFile->open()) {
+        VUtils::showMessage(QMessageBox::Warning,
+                            tr("Warning"),
+                            tr("Fail to open a temporary file for export."),
+                            "",
+                            QMessageBox::Ok,
+                            QMessageBox::Ok,
+                            this);
+        m_exportTempFile.clear();
+        return;
+    }
+
+    emit m_object->statusMessage(tr("Exporting diagram"));
+
+    QString filePath(m_exportTempFile->fileName());
+    QByteArray out;
+    if (p_lang == "puml") {
+        out = VPlantUMLHelper::process(p_format,
+                                       VEditUtils::removeCodeBlockFence(p_text));
+    } else if (p_lang == "dot") {
+        out = VGraphvizHelper::process(p_format,
+                                       VEditUtils::removeCodeBlockFence(p_text));
+    }
+
+    if (out.isEmpty() || m_exportTempFile->write(out) == -1) {
+        VUtils::showMessage(QMessageBox::Warning,
+                            tr("Warning"),
+                            tr("Fail to export diagram."),
+                            "",
+                            QMessageBox::Ok,
+                            QMessageBox::Ok,
+                            this);
+    } else {
+        QClipboard *clipboard = QApplication::clipboard();
+        clipboard->clear();
+        QImage img;
+        img.loadFromData(out, p_format.toLocal8Bit().data());
+        if (!img.isNull()) {
+            VClipboardUtils::setImageAndLinkToClipboard(clipboard,
+                                                        img,
+                                                        filePath,
+                                                        QClipboard::Clipboard);
+            emit m_object->statusMessage(tr("Diagram exported and copied"));
+        } else {
+            emit m_object->statusMessage(tr("Fail to read exported image: %1").arg(filePath));
+        }
+    }
+
+    m_exportTempFile->close();
+
+}

+ 14 - 0
src/vmdeditor.h

@@ -6,6 +6,8 @@
 #include <QClipboard>
 #include <QImage>
 #include <QUrl>
+#include <QTemporaryFile>
+#include <QSharedPointer>
 
 #include "vtextedit.h"
 #include "veditor.h"
@@ -284,12 +286,21 @@ private:
                                 const QTextBlock &p_block,
                                 int p_pos);
 
+    bool initExportAndCopyMenu(QAction *p_before,
+                               QMenu *p_menu,
+                               const QTextBlock &p_block,
+                               int p_pos);
+
     void insertImageLink(const QString &p_text, const QString &p_url);
 
     void setFontPointSizeByStyleSheet(int p_ptSize);
 
     void setFontAndPaletteByStyleSheet(const QFont &p_font, const QPalette &p_palette);
 
+    void exportDiagramAndCopy(const QString &p_lang,
+                              const QString &p_text,
+                              const QString &p_format);
+
     PegMarkdownHighlighter *m_pegHighlighter;
 
     VCodeBlockHighlightHelper *m_cbHighlighter;
@@ -314,6 +325,9 @@ private:
     VEditTab *m_editTab;
 
     int m_copyTimeStamp;
+
+    // Temp file used for ExportAndCopy.
+    QSharedPointer<QTemporaryFile> m_exportTempFile;
 };
 
 inline PegMarkdownHighlighter *VMdEditor::getMarkdownHighlighter() const

+ 59 - 24
src/vplantumlhelper.cpp

@@ -15,7 +15,19 @@ extern VConfigManager *g_config;
 VPlantUMLHelper::VPlantUMLHelper(QObject *p_parent)
     : QObject(p_parent)
 {
-    prepareCommand(m_customCmd, m_program, m_args);
+    m_customCmd = g_config->getPlantUMLCmd();
+    if (m_customCmd.isEmpty()) {
+        prepareCommand(m_program, m_args);
+    }
+}
+
+VPlantUMLHelper::VPlantUMLHelper(const QString &p_jar, QObject *p_parent)
+    : QObject(p_parent)
+{
+    m_customCmd = g_config->getPlantUMLCmd();
+    if (m_customCmd.isEmpty()) {
+        prepareCommand(m_program, m_args, p_jar);
+    }
 }
 
 void VPlantUMLHelper::processAsync(int p_id,
@@ -49,18 +61,13 @@ void VPlantUMLHelper::processAsync(int p_id,
     process->closeWriteChannel();
 }
 
-void VPlantUMLHelper::prepareCommand(QString &p_customCmd,
-                                     QString &p_program,
-                                     QStringList &p_args) const
+void VPlantUMLHelper::prepareCommand(QString &p_program,
+                                     QStringList &p_args,
+                                     const QString &p_jar) const
 {
-    p_customCmd = g_config->getPlantUMLCmd();
-    if (!p_customCmd.isEmpty()) {
-        return;
-    }
-
     p_program = "java";
 
-    p_args << "-jar" << g_config->getPlantUMLJar();
+    p_args << "-jar" << (p_jar.isEmpty() ? g_config->getPlantUMLJar() : p_jar);
     p_args << "-charset" << "UTF-8";
 
     int nbthread = QThread::idealThreadCount();
@@ -124,28 +131,23 @@ void VPlantUMLHelper::handleProcessFinished(int p_exitCode, QProcess::ExitStatus
 
 bool VPlantUMLHelper::testPlantUMLJar(const QString &p_jar, QString &p_msg)
 {
-    QString program("java");
-    QStringList args;
-    args << "-jar" << p_jar;
-    args << "-charset" << "UTF-8";
-
-    const QString &dot = g_config->getGraphvizDot();
-    if (!dot.isEmpty()) {
-        args << "-graphvizdot";
-        args << dot;
-    }
-
-    args << "-pipe";
+    VPlantUMLHelper inst(p_jar);
+    QStringList args(inst.m_args);
     args << "-tsvg";
 
     QString testGraph("VNote->Markdown : hello");
 
     int exitCode = -1;
     QByteArray out, err;
-    int ret = VProcessUtils::startProcess(program, args, testGraph.toUtf8(), exitCode, out, err);
+    int ret = VProcessUtils::startProcess(inst.m_program,
+                                          args,
+                                          testGraph.toUtf8(),
+                                          exitCode,
+                                          out,
+                                          err);
 
     p_msg = QString("Command: %1 %2\nExitCode: %3\nOutput: %4\nError: %5")
-                   .arg(program)
+                   .arg(inst.m_program)
                    .arg(args.join(' '))
                    .arg(exitCode)
                    .arg(QString::fromLocal8Bit(out))
@@ -153,3 +155,36 @@ bool VPlantUMLHelper::testPlantUMLJar(const QString &p_jar, QString &p_msg)
 
     return ret == 0 && exitCode == 0;
 }
+
+QByteArray VPlantUMLHelper::process(const QString &p_format, const QString &p_text)
+{
+    VPlantUMLHelper inst;
+
+    int exitCode = -1;
+    QByteArray out, err;
+    int ret = -1;
+    if (inst.m_customCmd.isEmpty()) {
+        QStringList args(inst.m_args);
+        args << ("-t" + p_format);
+        ret = VProcessUtils::startProcess(inst.m_program,
+                                          args,
+                                          p_text.toUtf8(),
+                                          exitCode,
+                                          out,
+                                          err);
+    } else {
+        QString cmd(inst.m_customCmd);
+        cmd.replace("%0", p_format);
+        ret = VProcessUtils::startProcess(cmd,
+                                          p_text.toUtf8(),
+                                          exitCode,
+                                          out,
+                                          err);
+    }
+
+    if (ret != 0 || exitCode < 0) {
+        qWarning() << "PlantUML fail" << ret << exitCode << QString::fromLocal8Bit(err);
+    }
+
+    return out;
+}

+ 10 - 3
src/vplantumlhelper.h

@@ -19,17 +19,24 @@ public:
                       const QString &p_format,
                       const QString &p_text);
 
-    void prepareCommand(QString &p_customCmd, QString &p_cmd, QStringList &p_args) const;
-
     static bool testPlantUMLJar(const QString &p_jar, QString &p_msg);
 
+    static QByteArray process(const QString &p_format, const QString &p_text);
+
 signals:
-    void resultReady(int p_id, TimeStamp p_timeStamp, const QString &p_format, const QString &p_result);
+    void resultReady(int p_id,
+                     TimeStamp p_timeStamp,
+                     const QString &p_format,
+                     const QString &p_result);
 
 private slots:
     void handleProcessFinished(int p_exitCode, QProcess::ExitStatus p_exitStatus);
 
 private:
+    VPlantUMLHelper(const QString &p_jar, QObject *p_parent = nullptr);
+
+    void prepareCommand(QString &p_cmd, QStringList &p_args, const QString &p_jar= QString()) const;
+
     QString m_program;
 
     QStringList m_args;