SettingsDialog: add test buttons for PlantUML and Graphviz

This commit is contained in:
Le Tan 2018-06-16 09:00:36 +08:00
parent a5e64696ea
commit 3bd80387fa
10 changed files with 263 additions and 10 deletions

View File

@ -25,6 +25,7 @@
#include "vnote.h"
#include "vexporter.h"
#include "vlineedit.h"
#include "utils/vprocessutils.h"
extern VConfigManager *g_config;
@ -521,22 +522,24 @@ bool VExportDialog::checkWkhtmltopdfExecutable(const QString &p_file)
{
QStringList args;
args << "--version";
int ret = QProcess::execute(p_file, args);
QByteArray out, err;
int exitCode = -1;
int ret = VProcessUtils::startProcess(p_file, args, exitCode, out, err);
switch (ret) {
case -2:
appendLogLine(tr("Fail to start wkhtmltopdf."));
appendLogLine(tr("Fail to start wkhtmltopdf (%1).").arg(p_file));
break;
case -1:
appendLogLine(tr("wkhtmltopdf crashed."));
appendLogLine(tr("wkhtmltopdf crashed (%1).").arg(p_file));
break;
case 0:
appendLogLine(tr("Use %1.").arg(p_file));
appendLogLine(tr("Use %1 (%2).").arg(p_file).arg(exitCode));
break;
default:
appendLogLine(tr("wkhtmltopdf returned %1.").arg(ret));
Q_ASSERT(false);
break;
}

View File

@ -7,6 +7,8 @@
#include "utils/vutils.h"
#include "vconstants.h"
#include "vlineedit.h"
#include "vplantumlhelper.h"
#include "vgraphvizhelper.h"
extern VConfigManager *g_config;
@ -1011,6 +1013,48 @@ VMarkdownTab::VMarkdownTab(QWidget *p_parent)
m_plantUMLJarEdit = new VLineEdit();
m_plantUMLJarEdit->setToolTip(tr("Location to the PlantUML JAR executable for local PlantUML"));
QPushButton *plantUMLJarTestBtn = new QPushButton(tr("Test"));
plantUMLJarTestBtn->setToolTip(tr("Test PlantUML JAR configuration"));
connect(plantUMLJarTestBtn, &QPushButton::clicked,
this, [this]() {
QString jar = m_plantUMLJarEdit->text();
if (jar.isEmpty() || !QFileInfo::exists(jar)) {
VUtils::showMessage(QMessageBox::Warning,
tr("Warning"),
tr("The JAR file specified does not exist."),
tr("Please input the right absolute file path to the JAR file."),
QMessageBox::Ok,
QMessageBox::Ok,
this);
return;
}
if (!jar.trimmed().toLower().endsWith(".jar")) {
VUtils::showMessage(QMessageBox::Warning,
tr("Warning"),
tr("Please specify the absolute file path to the JAR file."),
tr("It should be something like \"/path/to/plantuml.jar\"."),
QMessageBox::Ok,
QMessageBox::Ok,
this);
return;
}
QString msg;
bool ret = VPlantUMLHelper::testPlantUMLJar(jar, msg);
VUtils::showMessage(QMessageBox::Information,
tr("Information"),
tr("Test %1.").arg((ret ? tr("succeeded") : tr("failed"))),
msg,
QMessageBox::Ok,
QMessageBox::Ok,
this);
});
QHBoxLayout *plantUMLLayout = new QHBoxLayout();
plantUMLLayout->addWidget(m_plantUMLJarEdit);
plantUMLLayout->addWidget(plantUMLJarTestBtn);
// Graphviz.
m_graphvizCB = new QCheckBox(tr("Graphviz"));
m_graphvizCB->setToolTip(tr("Enable Graphviz for drawing graph"));
@ -1019,6 +1063,30 @@ VMarkdownTab::VMarkdownTab(QWidget *p_parent)
m_graphvizDotEdit->setPlaceholderText(tr("Empty to detect automatically"));
m_graphvizDotEdit->setToolTip(tr("Location to the GraphViz dot executable"));
QPushButton *graphvizTestBtn = new QPushButton(tr("Test"));
graphvizTestBtn->setToolTip(tr("Test Graphviz executable configuration"));
connect(graphvizTestBtn, &QPushButton::clicked,
this, [this]() {
QString dot = m_graphvizDotEdit->text();
if (dot.isEmpty()) {
dot = "dot";
}
QString msg;
bool ret = VGraphvizHelper::testGraphviz(dot, msg);
VUtils::showMessage(QMessageBox::Information,
tr("Information"),
tr("Test %1.").arg((ret ? tr("succeeded") : tr("failed"))),
msg,
QMessageBox::Ok,
QMessageBox::Ok,
this);
});
QHBoxLayout *graphvizLayout = new QHBoxLayout();
graphvizLayout->addWidget(m_graphvizDotEdit);
graphvizLayout->addWidget(graphvizTestBtn);
QFormLayout *mainLayout = new QFormLayout();
mainLayout->addRow(tr("Open mode:"), m_openModeCombo);
mainLayout->addRow(tr("Heading sequence:"), headingSequenceLayout);
@ -1026,9 +1094,9 @@ VMarkdownTab::VMarkdownTab(QWidget *p_parent)
mainLayout->addRow(tr("MathJax configuration:"), m_mathjaxConfigEdit);
mainLayout->addRow(tr("PlantUML:"), m_plantUMLModeCombo);
mainLayout->addRow(tr("PlantUML server:"), m_plantUMLServerEdit);
mainLayout->addRow(tr("PlantUML JAR:"), m_plantUMLJarEdit);
mainLayout->addRow(tr("PlantUML JAR:"), plantUMLLayout);
mainLayout->addRow(m_graphvizCB);
mainLayout->addRow(tr("Graphviz executable:"), m_graphvizDotEdit);
mainLayout->addRow(tr("Graphviz executable:"), graphvizLayout);
setLayout(mainLayout);
}

View File

@ -81,7 +81,7 @@ var postProcessMathJax = function(identifier, id, timeStamp, container, isBlock)
return;
}
var hei = (isBlock ? container.clientHeight * 1.5 : container.clientHeight * 1.8) + 5;
var hei = (isBlock ? container.clientHeight * 1.5 : container.clientHeight * 1.6) + 5;
domtoimage.toPng(container, { height: hei }).then(function (dataUrl) {
var png = dataUrl.substring(dataUrl.indexOf(',') + 1);
content.mathjaxResultReady(identifier, id, timeStamp, 'png', png);

View File

@ -135,7 +135,8 @@ SOURCES += main.cpp\
vhistorylist.cpp \
vexplorer.cpp \
vlistue.cpp \
vuetitlecontentpanel.cpp
vuetitlecontentpanel.cpp \
utils/vprocessutils.cpp
HEADERS += vmainwindow.h \
vdirectorytree.h \
@ -264,7 +265,8 @@ HEADERS += vmainwindow.h \
vexplorer.h \
vexplorerentry.h \
vlistue.h \
vuetitlecontentpanel.h
vuetitlecontentpanel.h \
utils/vprocessutils.h
RESOURCES += \
vnote.qrc \

View File

@ -0,0 +1,88 @@
#include "vprocessutils.h"
#include <QProcess>
#include <QScopedPointer>
#include <QDebug>
int VProcessUtils::startProcess(const QString &p_program,
const QStringList &p_args,
const QByteArray &p_in,
int &p_exitCode,
QByteArray &p_out,
QByteArray &p_err)
{
int ret = 0;
QScopedPointer<QProcess> process(new QProcess());
process->start(p_program, p_args);
if (!p_in.isEmpty()) {
if (process->write(p_in) == -1) {
process->closeWriteChannel();
qWarning() << "fail to write to QProcess:" << process->errorString();
return -1;
} else {
process->closeWriteChannel();
}
}
bool finished = false;
bool started = false;
while (true) {
QProcess::ProcessError err = process->error();
if (err == QProcess::FailedToStart
|| err == QProcess::Crashed) {
if (err == QProcess::FailedToStart) {
ret = -2;
} else {
ret = -1;
}
break;
}
if (started) {
if (process->state() == QProcess::NotRunning) {
finished = true;
}
} else {
if (process->state() != QProcess::NotRunning) {
started = true;
}
}
if (process->waitForFinished(500)) {
// Finished.
finished = true;
}
if (finished) {
QProcess::ExitStatus sta = process->exitStatus();
if (sta == QProcess::CrashExit) {
ret = -1;
break;
}
p_exitCode = process->exitCode();
break;
}
}
p_out = process->readAllStandardOutput();
p_err = process->readAllStandardError();
return ret;
}
int VProcessUtils::startProcess(const QString &p_program,
const QStringList &p_args,
int &p_exitCode,
QByteArray &p_out,
QByteArray &p_err)
{
return startProcess(p_program,
p_args,
QByteArray(),
p_exitCode,
p_out,
p_err);
}

32
src/utils/vprocessutils.h Normal file
View File

@ -0,0 +1,32 @@
#ifndef VPROCESSUTILS_H
#define VPROCESSUTILS_H
#include <QStringList>
#include <QByteArray>
class VProcessUtils
{
public:
// p_exitCode: exit code of the program, valid only when returning 0.
// 0: execute successfully;
// -1: crashed;
// -2: fail to start.
static int startProcess(const QString &p_program,
const QStringList &p_args,
int &p_exitCode,
QByteArray &p_out,
QByteArray &p_err);
static int startProcess(const QString &p_program,
const QStringList &p_args,
const QByteArray &p_in,
int &p_exitCode,
QByteArray &p_out,
QByteArray &p_err);
private:
VProcessUtils() {}
};
#endif // VPROCESSUTILS_H

View File

@ -4,6 +4,7 @@
#include <QThread>
#include "vconfigmanager.h"
#include "utils/vprocessutils.h"
extern VConfigManager *g_config;
@ -96,3 +97,25 @@ void VGraphvizHelper::handleProcessFinished(int p_exitCode, QProcess::ExitStatus
process->deleteLater();
}
bool VGraphvizHelper::testGraphviz(const QString &p_dot, QString &p_msg)
{
QString program(p_dot);
QStringList args;
args << "-Tsvg";
QString testGraph("digraph G {VNote->Markdown}");
int exitCode = -1;
QByteArray out, err;
int ret = VProcessUtils::startProcess(program, args, testGraph.toUtf8(), exitCode, out, err);
p_msg = QString("Command: %1 %2\nExitCode: %3\nOutput: %4\nError: %5")
.arg(program)
.arg(args.join(' '))
.arg(exitCode)
.arg(QString::fromLocal8Bit(out))
.arg(QString::fromLocal8Bit(err));
return ret == 0 && exitCode == 0;
}

View File

@ -18,6 +18,8 @@ public:
void prepareCommand(QString &p_cmd, QStringList &p_args) const;
static bool testGraphviz(const QString &p_dot, QString &p_msg);
signals:
void resultReady(int p_id, TimeStamp p_timeStamp, const QString &p_format, const QString &p_result);

View File

@ -4,6 +4,7 @@
#include <QThread>
#include "vconfigmanager.h"
#include "utils/vprocessutils.h"
extern VConfigManager *g_config;
@ -120,3 +121,35 @@ void VPlantUMLHelper::handleProcessFinished(int p_exitCode, QProcess::ExitStatus
process->deleteLater();
}
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";
args << "-tsvg";
QString testGraph("VNote->Markdown : hello");
int exitCode = -1;
QByteArray out, err;
int ret = VProcessUtils::startProcess(program, args, testGraph.toUtf8(), exitCode, out, err);
p_msg = QString("Command: %1 %2\nExitCode: %3\nOutput: %4\nError: %5")
.arg(program)
.arg(args.join(' '))
.arg(exitCode)
.arg(QString::fromLocal8Bit(out))
.arg(QString::fromLocal8Bit(err));
return ret == 0 && exitCode == 0;
}

View File

@ -21,6 +21,8 @@ public:
void prepareCommand(QString &p_customCmd, QString &p_cmd, QStringList &p_args) const;
static bool testPlantUMLJar(const QString &p_jar, QString &p_msg);
signals:
void resultReady(int p_id, TimeStamp p_timeStamp, const QString &p_format, const QString &p_result);