mirror of
https://gitee.com/vnotex/vnote.git
synced 2025-07-05 22:09:52 +08:00
SettingsDialog: add test buttons for PlantUML and Graphviz
This commit is contained in:
parent
a5e64696ea
commit
3bd80387fa
@ -25,6 +25,7 @@
|
|||||||
#include "vnote.h"
|
#include "vnote.h"
|
||||||
#include "vexporter.h"
|
#include "vexporter.h"
|
||||||
#include "vlineedit.h"
|
#include "vlineedit.h"
|
||||||
|
#include "utils/vprocessutils.h"
|
||||||
|
|
||||||
extern VConfigManager *g_config;
|
extern VConfigManager *g_config;
|
||||||
|
|
||||||
@ -521,22 +522,24 @@ bool VExportDialog::checkWkhtmltopdfExecutable(const QString &p_file)
|
|||||||
{
|
{
|
||||||
QStringList args;
|
QStringList args;
|
||||||
args << "--version";
|
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) {
|
switch (ret) {
|
||||||
case -2:
|
case -2:
|
||||||
appendLogLine(tr("Fail to start wkhtmltopdf."));
|
appendLogLine(tr("Fail to start wkhtmltopdf (%1).").arg(p_file));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case -1:
|
case -1:
|
||||||
appendLogLine(tr("wkhtmltopdf crashed."));
|
appendLogLine(tr("wkhtmltopdf crashed (%1).").arg(p_file));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0:
|
case 0:
|
||||||
appendLogLine(tr("Use %1.").arg(p_file));
|
appendLogLine(tr("Use %1 (%2).").arg(p_file).arg(exitCode));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
appendLogLine(tr("wkhtmltopdf returned %1.").arg(ret));
|
Q_ASSERT(false);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,6 +7,8 @@
|
|||||||
#include "utils/vutils.h"
|
#include "utils/vutils.h"
|
||||||
#include "vconstants.h"
|
#include "vconstants.h"
|
||||||
#include "vlineedit.h"
|
#include "vlineedit.h"
|
||||||
|
#include "vplantumlhelper.h"
|
||||||
|
#include "vgraphvizhelper.h"
|
||||||
|
|
||||||
extern VConfigManager *g_config;
|
extern VConfigManager *g_config;
|
||||||
|
|
||||||
@ -1011,6 +1013,48 @@ VMarkdownTab::VMarkdownTab(QWidget *p_parent)
|
|||||||
m_plantUMLJarEdit = new VLineEdit();
|
m_plantUMLJarEdit = new VLineEdit();
|
||||||
m_plantUMLJarEdit->setToolTip(tr("Location to the PlantUML JAR executable for local PlantUML"));
|
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.
|
// Graphviz.
|
||||||
m_graphvizCB = new QCheckBox(tr("Graphviz"));
|
m_graphvizCB = new QCheckBox(tr("Graphviz"));
|
||||||
m_graphvizCB->setToolTip(tr("Enable Graphviz for drawing graph"));
|
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->setPlaceholderText(tr("Empty to detect automatically"));
|
||||||
m_graphvizDotEdit->setToolTip(tr("Location to the GraphViz dot executable"));
|
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();
|
QFormLayout *mainLayout = new QFormLayout();
|
||||||
mainLayout->addRow(tr("Open mode:"), m_openModeCombo);
|
mainLayout->addRow(tr("Open mode:"), m_openModeCombo);
|
||||||
mainLayout->addRow(tr("Heading sequence:"), headingSequenceLayout);
|
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("MathJax configuration:"), m_mathjaxConfigEdit);
|
||||||
mainLayout->addRow(tr("PlantUML:"), m_plantUMLModeCombo);
|
mainLayout->addRow(tr("PlantUML:"), m_plantUMLModeCombo);
|
||||||
mainLayout->addRow(tr("PlantUML server:"), m_plantUMLServerEdit);
|
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(m_graphvizCB);
|
||||||
mainLayout->addRow(tr("Graphviz executable:"), m_graphvizDotEdit);
|
mainLayout->addRow(tr("Graphviz executable:"), graphvizLayout);
|
||||||
|
|
||||||
setLayout(mainLayout);
|
setLayout(mainLayout);
|
||||||
}
|
}
|
||||||
|
@ -81,7 +81,7 @@ var postProcessMathJax = function(identifier, id, timeStamp, container, isBlock)
|
|||||||
return;
|
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) {
|
domtoimage.toPng(container, { height: hei }).then(function (dataUrl) {
|
||||||
var png = dataUrl.substring(dataUrl.indexOf(',') + 1);
|
var png = dataUrl.substring(dataUrl.indexOf(',') + 1);
|
||||||
content.mathjaxResultReady(identifier, id, timeStamp, 'png', png);
|
content.mathjaxResultReady(identifier, id, timeStamp, 'png', png);
|
||||||
|
@ -135,7 +135,8 @@ SOURCES += main.cpp\
|
|||||||
vhistorylist.cpp \
|
vhistorylist.cpp \
|
||||||
vexplorer.cpp \
|
vexplorer.cpp \
|
||||||
vlistue.cpp \
|
vlistue.cpp \
|
||||||
vuetitlecontentpanel.cpp
|
vuetitlecontentpanel.cpp \
|
||||||
|
utils/vprocessutils.cpp
|
||||||
|
|
||||||
HEADERS += vmainwindow.h \
|
HEADERS += vmainwindow.h \
|
||||||
vdirectorytree.h \
|
vdirectorytree.h \
|
||||||
@ -264,7 +265,8 @@ HEADERS += vmainwindow.h \
|
|||||||
vexplorer.h \
|
vexplorer.h \
|
||||||
vexplorerentry.h \
|
vexplorerentry.h \
|
||||||
vlistue.h \
|
vlistue.h \
|
||||||
vuetitlecontentpanel.h
|
vuetitlecontentpanel.h \
|
||||||
|
utils/vprocessutils.h
|
||||||
|
|
||||||
RESOURCES += \
|
RESOURCES += \
|
||||||
vnote.qrc \
|
vnote.qrc \
|
||||||
|
88
src/utils/vprocessutils.cpp
Normal file
88
src/utils/vprocessutils.cpp
Normal 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
32
src/utils/vprocessutils.h
Normal 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
|
@ -4,6 +4,7 @@
|
|||||||
#include <QThread>
|
#include <QThread>
|
||||||
|
|
||||||
#include "vconfigmanager.h"
|
#include "vconfigmanager.h"
|
||||||
|
#include "utils/vprocessutils.h"
|
||||||
|
|
||||||
extern VConfigManager *g_config;
|
extern VConfigManager *g_config;
|
||||||
|
|
||||||
@ -96,3 +97,25 @@ void VGraphvizHelper::handleProcessFinished(int p_exitCode, QProcess::ExitStatus
|
|||||||
|
|
||||||
process->deleteLater();
|
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;
|
||||||
|
}
|
||||||
|
@ -18,6 +18,8 @@ public:
|
|||||||
|
|
||||||
void prepareCommand(QString &p_cmd, QStringList &p_args) const;
|
void prepareCommand(QString &p_cmd, QStringList &p_args) const;
|
||||||
|
|
||||||
|
static bool testGraphviz(const QString &p_dot, QString &p_msg);
|
||||||
|
|
||||||
signals:
|
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);
|
||||||
|
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
#include <QThread>
|
#include <QThread>
|
||||||
|
|
||||||
#include "vconfigmanager.h"
|
#include "vconfigmanager.h"
|
||||||
|
#include "utils/vprocessutils.h"
|
||||||
|
|
||||||
extern VConfigManager *g_config;
|
extern VConfigManager *g_config;
|
||||||
|
|
||||||
@ -120,3 +121,35 @@ void VPlantUMLHelper::handleProcessFinished(int p_exitCode, QProcess::ExitStatus
|
|||||||
|
|
||||||
process->deleteLater();
|
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;
|
||||||
|
}
|
||||||
|
@ -21,6 +21,8 @@ public:
|
|||||||
|
|
||||||
void prepareCommand(QString &p_customCmd, QString &p_cmd, QStringList &p_args) const;
|
void prepareCommand(QString &p_customCmd, QString &p_cmd, QStringList &p_args) const;
|
||||||
|
|
||||||
|
static bool testPlantUMLJar(const QString &p_jar, QString &p_msg);
|
||||||
|
|
||||||
signals:
|
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);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user