diff --git a/src/dialog/vexportdialog.cpp b/src/dialog/vexportdialog.cpp index 9f7a4a08..0c41efc0 100644 --- a/src/dialog/vexportdialog.cpp +++ b/src/dialog/vexportdialog.cpp @@ -133,6 +133,8 @@ void VExportDialog::setupUI() if (m_inExport) { // Just cancel the export. Do not exit. m_askedToStop = true; + m_exporter->setAskedToStop(true); + appendLogLine(tr("Cancelling the export...")); } else { QDialog::reject(); } @@ -489,6 +491,7 @@ void VExportDialog::startExport() m_exportBtn->setEnabled(false); m_proBar->show(); m_askedToStop = false; + m_exporter->setAskedToStop(false); m_inExport = true; QString outputFolder = QDir::cleanPath(QDir(getOutputDirectory()).absolutePath()); @@ -579,6 +582,11 @@ void VExportDialog::startExport() s_opt.m_format = ExportFormat::OnePDF; + if (m_askedToStop) { + ret = 0; + goto exit; + } + Q_ASSERT(ret == files.size()); if (!files.isEmpty()) { ret = doExportPDFAllInOne(files, s_opt, outputFolder, &msg); @@ -611,6 +619,7 @@ exit: if (m_askedToStop) { appendLogLine(tr("User cancelled the export. Aborted!")); m_askedToStop = false; + m_exporter->setAskedToStop(false); } if (!msg.isEmpty()) { diff --git a/src/vexporter.cpp b/src/vexporter.cpp index 62d5d6c2..b551954d 100644 --- a/src/vexporter.cpp +++ b/src/vexporter.cpp @@ -7,6 +7,8 @@ #include #include #include +#include +#include #include "vconfigmanager.h" #include "vfile.h" @@ -25,7 +27,8 @@ extern VWebUtils *g_webUtils; VExporter::VExporter(QWidget *p_parent) : QObject(p_parent), m_webViewer(NULL), - m_state(ExportState::Idle) + m_state(ExportState::Idle), + m_askedToStop(false) { } @@ -666,8 +669,12 @@ bool VExporter::htmlsToPDFViaWK(const QList &p_htmlFiles, QString cmd = p_opt.m_wkPath + " " + combineArgs(args); emit outputLog(cmd); qDebug() << "wkhtmltopdf cmd:" << cmd; - int ret = QProcess::execute(p_opt.m_wkPath, args); + int ret = startProcess(p_opt.m_wkPath, args); qDebug() << "wkhtmltopdf returned" << ret; + if (m_askedToStop) { + return ret == 0; + } + switch (ret) { case -2: VUtils::addErrMsg(p_errMsg, tr("Fail to start wkhtmltopdf (%1).").arg(cmd)); @@ -695,3 +702,77 @@ int VExporter::exportPDFInOne(const QList &p_htmlFiles, return p_htmlFiles.size(); } + +int VExporter::startProcess(const QString &p_program, const QStringList &p_args) +{ + int ret = 0; + QScopedPointer process(new QProcess(this)); + process->start(p_program, p_args); + bool finished = false; + bool started = false; + while (true) { + QProcess::ProcessError err = process->error(); + if (err == QProcess::FailedToStart + || err == QProcess::Crashed) { + emit outputLog(tr("QProcess error %1.").arg(err)); + 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; + } + + QByteArray outBa = process->readAllStandardOutput(); + QByteArray errBa = process->readAllStandardError(); + QString msg; + if (!outBa.isEmpty()) { + msg += QString::fromLocal8Bit(outBa); + } + + if (!errBa.isEmpty()) { + msg += QString::fromLocal8Bit(errBa); + } + + if (!msg.isEmpty()) { + emit outputLog(msg); + } + + if (finished) { + QProcess::ExitStatus sta = process->exitStatus(); + if (sta == QProcess::CrashExit) { + ret = -1; + break; + } + + ret = process->exitCode(); + break; + } + + QCoreApplication::processEvents(); + + if (m_askedToStop) { + process->kill(); + ret = -1; + break; + } + } + + return ret; +} diff --git a/src/vexporter.h b/src/vexporter.h index d0ecc7f3..6a2be69a 100644 --- a/src/vexporter.h +++ b/src/vexporter.h @@ -36,6 +36,8 @@ public: const QString &p_outputFile, QString *p_errMsg = NULL); + void setAskedToStop(bool p_askedToStop); + signals: // Request to output log. void outputLog(const QString &p_log); @@ -107,6 +109,8 @@ private: void prepareWKArguments(const ExportPDFOption &p_opt); + int startProcess(const QString &p_program, const QStringList &p_args); + // Fix @p_html's resources like url("...") with "file" or "qrc" schema. // Copy the resource to @p_folder and fix the url string. static bool fixStyleResources(const QString &p_folder, @@ -144,6 +148,8 @@ private: // Arguments for wkhtmltopdf. QStringList m_wkArgs; + + bool m_askedToStop; }; inline void VExporter::clearNoteState() @@ -161,4 +167,8 @@ inline bool VExporter::isNoteStateFailed() const return m_noteState & NoteState::Failed; } +inline void VExporter::setAskedToStop(bool p_askedToStop) +{ + m_askedToStop = p_askedToStop; +} #endif // VEXPORTER_H