fix: v0.10.5 —— 导出前先定页面尺寸,并给导出过程加日志
- 之前是先渲染文档、后设置页面尺寸;表格用的是百分比宽度, 页面宽度为 0 时插入表格,某些 Qt 构建会在打印排版阶段死循环 - 改成先建 QPdfWriter、量出页面宽高、设好 document 的 pageSize,再开始渲染 - 增加排版结果健全性检查(NaN / 高度 <= 0 直接中止并提示) - 新增导出日志:%APPDATA%/VoiletMark/VoiletMark/export.log(Linux 在 ~/.local/share/...),逐步记录 对话框关闭 / 渲染开始 / 渲染结束 / 写入完成 - 版本 0.10.5
This commit is contained in:
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
一个轻量的跨平台 Markdown 编辑器,基于 **Qt 5 / C++17** 构建。
|
一个轻量的跨平台 Markdown 编辑器,基于 **Qt 5 / C++17** 构建。
|
||||||
|
|
||||||
当前版本 **0.10.4**。
|
当前版本 **0.10.5**。
|
||||||
|
|
||||||
## 界面
|
## 界面
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
TEMPLATE = app
|
TEMPLATE = app
|
||||||
TARGET = VoiletMark
|
TARGET = VoiletMark
|
||||||
VERSION = 0.10.4
|
VERSION = 0.10.5
|
||||||
|
|
||||||
QT += core gui widgets
|
QT += core gui widgets
|
||||||
|
|
||||||
|
|||||||
+47
-7
@@ -10,6 +10,7 @@
|
|||||||
#include <QActionGroup>
|
#include <QActionGroup>
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
#include <QCloseEvent>
|
#include <QCloseEvent>
|
||||||
|
#include <QDateTime>
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
#include <QDirIterator>
|
#include <QDirIterator>
|
||||||
#include <QDockWidget>
|
#include <QDockWidget>
|
||||||
@@ -688,6 +689,20 @@ bool MainWindow::saveFileAs()
|
|||||||
return writeToFile(path);
|
return writeToFile(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MainWindow::logExport(const QString &message)
|
||||||
|
{
|
||||||
|
const QString directory = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
|
||||||
|
if (directory.isEmpty())
|
||||||
|
return;
|
||||||
|
QDir().mkpath(directory);
|
||||||
|
|
||||||
|
QFile file(QDir(directory).filePath(QStringLiteral("export.log")));
|
||||||
|
if (!file.open(QIODevice::Append | QIODevice::Text))
|
||||||
|
return;
|
||||||
|
QTextStream stream(&file);
|
||||||
|
stream << QDateTime::currentDateTime().toString(Qt::ISODate) << " " << message << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
void MainWindow::exportPdf()
|
void MainWindow::exportPdf()
|
||||||
{
|
{
|
||||||
QString suggested = m_currentPath.isEmpty() ? tr("未命名")
|
QString suggested = m_currentPath.isEmpty() ? tr("未命名")
|
||||||
@@ -702,12 +717,10 @@ void MainWindow::exportPdf()
|
|||||||
if (!target.endsWith(QStringLiteral(".pdf"), Qt::CaseInsensitive))
|
if (!target.endsWith(QStringLiteral(".pdf"), Qt::CaseInsensitive))
|
||||||
target += QStringLiteral(".pdf");
|
target += QStringLiteral(".pdf");
|
||||||
|
|
||||||
|
logExport(QStringLiteral("dialog closed, target=%1").arg(target));
|
||||||
statusBar()->showMessage(tr("正在导出 PDF…"));
|
statusBar()->showMessage(tr("正在导出 PDF…"));
|
||||||
|
QApplication::processEvents();
|
||||||
|
|
||||||
QTextDocument document;
|
|
||||||
MarkdownRenderer::render(m_editor->toPlainText(), &document);
|
|
||||||
|
|
||||||
{
|
|
||||||
// 用 QPdfWriter 直接写 PDF,不碰任何平台的打印子系统:
|
// 用 QPdfWriter 直接写 PDF,不碰任何平台的打印子系统:
|
||||||
// Windows 的打印后台、Linux 的 CUPS 在没有打印机或服务异常时都可能卡住。
|
// Windows 的打印后台、Linux 的 CUPS 在没有打印机或服务异常时都可能卡住。
|
||||||
QPdfWriter writer(target);
|
QPdfWriter writer(target);
|
||||||
@@ -715,14 +728,41 @@ void MainWindow::exportPdf()
|
|||||||
writer.setPageMargins(QMarginsF(16, 16, 16, 16), QPageLayout::Millimeter);
|
writer.setPageMargins(QMarginsF(16, 16, 16, 16), QPageLayout::Millimeter);
|
||||||
writer.setTitle(QFileInfo(target).completeBaseName());
|
writer.setTitle(QFileInfo(target).completeBaseName());
|
||||||
|
|
||||||
|
// 先把页面尺寸定下来再渲染:表格用的是百分比宽度,
|
||||||
|
// 页面宽度为 0 时插入表格会让某些平台的排版循环算不出结果。
|
||||||
|
QSizeF pageSize(672.76, 1001.57);
|
||||||
const QRectF paintRect = writer.pageLayout().paintRectPixels(writer.resolution());
|
const QRectF paintRect = writer.pageLayout().paintRectPixels(writer.resolution());
|
||||||
const qreal scale = 96.0 / writer.resolution();
|
const qreal resolution = qMax(1, writer.resolution());
|
||||||
document.setPageSize(QSizeF(paintRect.width() * scale, paintRect.height() * scale));
|
if (paintRect.width() > 100 && paintRect.height() > 100) {
|
||||||
|
const qreal scale = 96.0 / resolution;
|
||||||
|
pageSize = QSizeF(paintRect.width() * scale, paintRect.height() * scale);
|
||||||
|
}
|
||||||
|
|
||||||
|
QTextDocument document;
|
||||||
|
document.setPageSize(pageSize);
|
||||||
|
logExport(QStringLiteral("rendering, page size=%1x%2").arg(pageSize.width()).arg(pageSize.height()));
|
||||||
|
|
||||||
QApplication::setOverrideCursor(Qt::WaitCursor);
|
QApplication::setOverrideCursor(Qt::WaitCursor);
|
||||||
|
MarkdownRenderer::render(m_editor->toPlainText(), &document);
|
||||||
|
const QSizeF documentSize = document.size();
|
||||||
|
logExport(QStringLiteral("rendered, blocks=%1 height=%2")
|
||||||
|
.arg(document.blockCount())
|
||||||
|
.arg(documentSize.height()));
|
||||||
|
|
||||||
|
if (!qIsFinite(documentSize.width()) || !qIsFinite(documentSize.height())
|
||||||
|
|| documentSize.height() <= 0) {
|
||||||
|
QApplication::restoreOverrideCursor();
|
||||||
|
logExport(QStringLiteral("aborted: bad document size %1x%2")
|
||||||
|
.arg(documentSize.width())
|
||||||
|
.arg(documentSize.height()));
|
||||||
|
QMessageBox::warning(this, tr("导出失败"), tr("文档排版结果异常,已中止导出。"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
document.print(&writer);
|
document.print(&writer);
|
||||||
QApplication::restoreOverrideCursor();
|
QApplication::restoreOverrideCursor();
|
||||||
}
|
|
||||||
|
logExport(QStringLiteral("printed, size=%1").arg(QFileInfo(target).size()));
|
||||||
|
|
||||||
if (!QFileInfo::exists(target) || QFileInfo(target).size() <= 0) {
|
if (!QFileInfo::exists(target) || QFileInfo(target).size() <= 0) {
|
||||||
QMessageBox::warning(this, tr("导出失败"),
|
QMessageBox::warning(this, tr("导出失败"),
|
||||||
|
|||||||
@@ -60,6 +60,7 @@ private:
|
|||||||
QStringList scanFolder() const;
|
QStringList scanFolder() const;
|
||||||
void setSourceModeEnabled(bool enabled);
|
void setSourceModeEnabled(bool enabled);
|
||||||
void exportPdf();
|
void exportPdf();
|
||||||
|
void logExport(const QString &message);
|
||||||
|
|
||||||
// ---- Git ----
|
// ---- Git ----
|
||||||
void updateGitState();
|
void updateGitState();
|
||||||
|
|||||||
Reference in New Issue
Block a user