feat: v0.10.2 —— PDF 表格与代码高亮,Git 按钮重排

PDF 导出
- 表格用 QTextTable 渲染:表头灰底加粗、单元格边框、按 :---: 保留对齐
- 代码块接入 CodeHighlight:关键字/字符串/数字/注释/预处理指令分色
- 修掉 MarkdownRenderer 里表格分隔行正则丢失反斜杠的问题

侧栏 Git
- 按钮重排:第一行 获取 / 拉取 / 添加,第二行 提交 / 推送
- 「暂存」改名为「添加」,和右键菜单用词一致

其它
- 默认欢迎文档里的示例表格确认可用(编辑模式渲染成表格控件)
- README 同步,版本 0.10.2
This commit is contained in:
2026-10-22 18:39:03 +08:00
parent 742bbf4a2b
commit cf05de24f5
5 changed files with 368 additions and 199 deletions
+10 -7
View File
@@ -2,7 +2,7 @@
一个轻量的跨平台 Markdown 编辑器,基于 **Qt 5 / C++17** 构建。
当前版本 **0.10.1**。
当前版本 **0.10.2**。
## 界面
@@ -54,11 +54,13 @@
| 按钮 | 实际执行 |
| --- | --- |
| 拉取 | `git pull --ff-only` |
| 获取 | `git fetch --all --prune` |
| 推送 | `git push` |
| 暂存 | `git add -A` |
| 拉取 | `git pull --ff-only` |
| 添加 | `git add -A` |
| 提交 | 填说明后 `git commit -m` |
| 推送 | `git push` |
排列是两行:第一行 获取 / 拉取 / 添加,第二行 提交 和 推送。
右键侧栏里的文件有三项:
@@ -94,10 +96,11 @@ A4 纸、16mm 页边距。
导出用的是 Qt 自带的 `QPrinter` + `QTextDocument`,不需要额外的 PDF 库。
支持标题、列表(含任务列表)、引用、代码块、行内代码、粗体 / 斜体 / 删除线、
链接;图片只输出 alt 文字,表格暂时按原文输出。
链接、表格;图片只输出 alt 文字。
代码块在 PDF 里是**一整块带边框的面板**(不是一行一条底色),
右上角标注语言名(C++ / Python …,取围栏上的标记)。
- 代码块是**一整块带边框的面板**(不是一行一条底色),右上角标注语言名,
块内按语言做语法高亮
- 表格渲染成真正的表格:表头灰底加粗、单元格边框、按 `:---:` 保留对齐
### 语言
+1 -1
View File
@@ -1,6 +1,6 @@
TEMPLATE = app
TARGET = VoiletMark
VERSION = 0.10.1
VERSION = 0.10.2
QT += core gui widgets printsupport
+8 -8
View File
@@ -340,17 +340,17 @@ void MainWindow::createSidebar()
return button;
};
m_gitPullButton = makeGitButton(tr("拉取"), tr("git pull --ff-only"));
m_gitFetchButton = makeGitButton(tr("获取"), tr("git fetch --all --prune"));
m_gitPushButton = makeGitButton(tr("推送"), tr("git push"));
m_gitStageButton = makeGitButton(tr("暂存"), tr("git add -A"));
m_gitPullButton = makeGitButton(tr("拉取"), tr("git pull --ff-only"));
m_gitStageButton = makeGitButton(tr("添加"), tr("git add -A"));
m_gitCommitButton = makeGitButton(tr("提交"), tr("把暂存区的内容提交"));
m_gitPushButton = makeGitButton(tr("推送"), tr("git push"));
gitLayout->addWidget(m_gitPullButton, 1, 0);
gitLayout->addWidget(m_gitFetchButton, 1, 1);
gitLayout->addWidget(m_gitPushButton, 1, 2);
gitLayout->addWidget(m_gitStageButton, 2, 0);
gitLayout->addWidget(m_gitCommitButton, 2, 1, 1, 2);
gitLayout->addWidget(m_gitFetchButton, 1, 0);
gitLayout->addWidget(m_gitPullButton, 1, 1);
gitLayout->addWidget(m_gitStageButton, 1, 2);
gitLayout->addWidget(m_gitCommitButton, 2, 0, 1, 2);
gitLayout->addWidget(m_gitPushButton, 2, 2);
layout->addWidget(m_gitBar);
m_gitBar->setVisible(false);
+166 -1
View File
@@ -8,6 +8,7 @@
#include <QTextBlockFormat>
#include <QTextCharFormat>
#include <QTextFrame>
#include <QTextTable>
#include <QTextCursor>
#include <QTextDocument>
@@ -43,6 +44,12 @@ struct Style
QColor codeText = hex("#24292f");
QColor codeBg = hex("#f3f4f6");
QColor border = hex("#d0d7de");
QColor tableHeader = hex("#f6f8fa");
QColor keyword = hex("#0550ae");
QColor string = hex("#0a7d3a");
QColor number = hex("#953800");
QColor comment = hex("#6e7781");
QColor preprocessor = hex("#8250df");
QColor link = hex("#0969da");
QColor marker = hex("#0969da");
};
@@ -50,6 +57,26 @@ struct Style
constexpr qreal kBodySize = 11.5;
constexpr qreal kCodeSize = 10.5;
bool isTableSeparator(const QString &text)
{
static const QRegularExpression pattern(
QStringLiteral(R"(^\s*\|?\s*:?-{2,}:?\s*(?:\|\s*:?-{2,}:?\s*)+\|?\s*$)"));
return pattern.match(text).hasMatch();
}
QStringList splitTableRow(const QString &line)
{
QString text = line.trimmed();
if (text.startsWith(QLatin1Char('|')))
text.remove(0, 1);
if (text.endsWith(QLatin1Char('|')))
text.chop(1);
QStringList cells = text.split(QLatin1Char('|'));
for (QString &cell : cells)
cell = cell.trimmed();
return cells;
}
class Renderer
{
public:
@@ -67,6 +94,8 @@ private:
void renderParagraph(const QString &text, int quoteDepth);
void renderListItem(const QString &marker, const QString &text, int indentLevel);
void renderCodeBlock(const QStringList &lines, const QString &info);
void renderTable(const QStringList &rows, const QString &separator);
QColor tokenColor(CodeHighlight::Token token) const;
void renderRule();
void renderInline(const QString &text, const QTextCharFormat &base);
@@ -217,9 +246,34 @@ void Renderer::renderCodeBlock(const QStringList &lines, const QString &info)
if (content.isEmpty())
content << QString();
const CodeHighlight::Language codeLanguage = CodeHighlight::fromInfoString(info);
bool inComment = false;
for (const QString &line : content) {
insideBlock(codeBlock, format);
frameCursor.insertText(line.isEmpty() ? QStringLiteral(" ") : line, format);
bool endsInComment = inComment;
int position = 0;
if (codeLanguage != CodeHighlight::Language::None) {
const QVector<CodeHighlight::Span> spans =
CodeHighlight::tokenize(line, codeLanguage, inComment, &endsInComment);
for (const CodeHighlight::Span &span : spans) {
if (span.start > position)
frameCursor.insertText(line.mid(position, span.start - position), format);
QTextCharFormat tokenFormat = format;
tokenFormat.setForeground(tokenColor(span.token));
frameCursor.insertText(line.mid(span.start, span.length), tokenFormat);
position = span.start + span.length;
}
}
inComment = endsInComment;
if (position < line.size())
frameCursor.insertText(line.mid(position), format);
if (line.isEmpty())
frameCursor.insertText(QStringLiteral(" "), format);
}
// 光标挪到边框外面,后面的内容接着写
@@ -227,6 +281,102 @@ void Renderer::renderCodeBlock(const QStringList &lines, const QString &info)
m_cursor.setPosition(frame->lastPosition());
}
QColor Renderer::tokenColor(CodeHighlight::Token token) const
{
switch (token) {
case CodeHighlight::Token::Keyword:
case CodeHighlight::Token::Type:
return m_style.keyword;
case CodeHighlight::Token::String:
return m_style.string;
case CodeHighlight::Token::Number:
return m_style.number;
case CodeHighlight::Token::Comment:
return m_style.comment;
case CodeHighlight::Token::Preprocessor:
return m_style.preprocessor;
}
return m_style.codeText;
}
void Renderer::renderTable(const QStringList &rows, const QString &separator)
{
if (rows.isEmpty())
return;
if (m_firstBlock) {
QTextBlockFormat emptyFormat;
beginBlock(emptyFormat, bodyFormat());
}
const QStringList headerCells = splitTableRow(rows.first());
const int columns = qMax(1, headerCells.size());
QVector<Qt::Alignment> alignments;
for (const QString &cell : splitTableRow(separator)) {
const bool left = cell.startsWith(QLatin1Char(':'));
const bool right = cell.endsWith(QLatin1Char(':'));
if (left && right)
alignments.append(Qt::AlignHCenter);
else if (right)
alignments.append(Qt::AlignRight);
else
alignments.append(Qt::AlignLeft);
}
QTextTableFormat tableFormat;
tableFormat.setBorder(1);
tableFormat.setBorderBrush(m_style.border);
tableFormat.setBorderStyle(QTextFrameFormat::BorderStyle_Solid);
tableFormat.setCellSpacing(0);
tableFormat.setCellPadding(6);
tableFormat.setWidth(QTextLength(QTextLength::PercentageLength, 100));
tableFormat.setTopMargin(6);
tableFormat.setBottomMargin(12);
QTextTable *table = m_cursor.insertTable(rows.size(), columns, tableFormat);
for (int row = 0; row < rows.size(); ++row) {
const QStringList cells = (row == 0) ? headerCells : splitTableRow(rows.at(row));
for (int column = 0; column < columns; ++column) {
QTextTableCell cell = table->cellAt(row, column);
QTextTableCellFormat cellFormat = cell.format().toTableCellFormat();
cellFormat.setBackground(row == 0 ? m_style.tableHeader : m_style.codeBg.lighter(104));
cellFormat.setTopBorder(1);
cellFormat.setBottomBorder(1);
cellFormat.setLeftBorder(1);
cellFormat.setRightBorder(1);
cellFormat.setTopBorderBrush(m_style.border);
cellFormat.setBottomBorderBrush(m_style.border);
cellFormat.setLeftBorderBrush(m_style.border);
cellFormat.setRightBorderBrush(m_style.border);
cellFormat.setTopBorderStyle(QTextFrameFormat::BorderStyle_Solid);
cellFormat.setBottomBorderStyle(QTextFrameFormat::BorderStyle_Solid);
cellFormat.setLeftBorderStyle(QTextFrameFormat::BorderStyle_Solid);
cellFormat.setRightBorderStyle(QTextFrameFormat::BorderStyle_Solid);
cell.setFormat(cellFormat);
QTextCursor cellCursor = cell.firstCursorPosition();
QTextBlockFormat blockFormat;
blockFormat.setAlignment(alignments.value(column, Qt::AlignLeft));
cellCursor.setBlockFormat(blockFormat);
QTextCharFormat charFormat;
charFormat.setFontFamilies(proseFamilies());
charFormat.setFontPointSize(kBodySize);
charFormat.setForeground(m_style.text);
if (row == 0) {
charFormat.setFontWeight(QFont::Bold);
charFormat.setForeground(m_style.heading);
}
cellCursor.insertText(cells.value(column), charFormat);
}
}
m_cursor = QTextCursor(m_document);
m_cursor.setPosition(table->lastPosition());
}
void Renderer::renderRule()
{
QTextBlockFormat blockFormat;
@@ -365,6 +515,21 @@ void Renderer::run(const QString &markdown)
while (index < lines.size()) {
const QString line = lines.at(index);
// 表格:当前行有 |,下一行是 |---|
if (line.contains(QLatin1Char('|')) && index + 1 < lines.size()
&& isTableSeparator(lines.at(index + 1))) {
QStringList rows{line};
int next = index + 2;
while (next < lines.size() && !lines.at(next).trimmed().isEmpty()
&& lines.at(next).contains(QLatin1Char('|'))) {
rows << lines.at(next);
++next;
}
renderTable(rows, lines.at(index + 1));
index = next;
continue;
}
const QRegularExpressionMatch fence = fencePattern.match(line);
if (fence.hasMatch()) {
QStringList code;
+183 -182
View File
@@ -1,9 +1,10 @@
<?xml version='1.0' encoding='utf-8'?>
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1" language="en_US">
<context>
<name>GitRunner</name>
<message>
<location filename="../src/GitRunner.cpp" line="32" />
<location filename="../src/GitRunner.cpp" line="32"/>
<source>
(超时,已中止)</source>
<translation>
@@ -13,448 +14,447 @@
<context>
<name>MainWindow</name>
<message>
<location filename="../src/MainWindow.cpp" line="191" />
<location filename="../src/MainWindow.cpp" line="849" />
<location filename="../src/MainWindow.cpp" line="191"/>
<location filename="../src/MainWindow.cpp" line="849"/>
<source>新建</source>
<translation>New</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="195" />
<location filename="../src/MainWindow.cpp" line="850" />
<location filename="../src/MainWindow.cpp" line="195"/>
<location filename="../src/MainWindow.cpp" line="850"/>
<source>打开…</source>
<translation>Open…</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="199" />
<location filename="../src/MainWindow.cpp" line="852" />
<location filename="../src/MainWindow.cpp" line="199"/>
<location filename="../src/MainWindow.cpp" line="852"/>
<source>保存</source>
<translation>Save</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="203" />
<location filename="../src/MainWindow.cpp" line="853" />
<location filename="../src/MainWindow.cpp" line="203"/>
<location filename="../src/MainWindow.cpp" line="853"/>
<source>另存为…</source>
<translation>Save As…</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="207" />
<location filename="../src/MainWindow.cpp" line="854" />
<location filename="../src/MainWindow.cpp" line="207"/>
<location filename="../src/MainWindow.cpp" line="854"/>
<source>导出 PDF…</source>
<translation>Export PDF…</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="211" />
<location filename="../src/MainWindow.cpp" line="855" />
<location filename="../src/MainWindow.cpp" line="211"/>
<location filename="../src/MainWindow.cpp" line="855"/>
<source>退出</source>
<translation>Quit</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="215" />
<location filename="../src/MainWindow.cpp" line="857" />
<location filename="../src/MainWindow.cpp" line="215"/>
<location filename="../src/MainWindow.cpp" line="857"/>
<source>撤销</source>
<translation>Undo</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="219" />
<location filename="../src/MainWindow.cpp" line="858" />
<location filename="../src/MainWindow.cpp" line="219"/>
<location filename="../src/MainWindow.cpp" line="858"/>
<source>重做</source>
<translation>Redo</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="223" />
<location filename="../src/MainWindow.cpp" line="859" />
<location filename="../src/MainWindow.cpp" line="223"/>
<location filename="../src/MainWindow.cpp" line="859"/>
<source>剪切</source>
<translation>Cut</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="227" />
<location filename="../src/MainWindow.cpp" line="860" />
<location filename="../src/MainWindow.cpp" line="227"/>
<location filename="../src/MainWindow.cpp" line="860"/>
<source>复制</source>
<translation>Copy</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="231" />
<location filename="../src/MainWindow.cpp" line="861" />
<location filename="../src/MainWindow.cpp" line="231"/>
<location filename="../src/MainWindow.cpp" line="861"/>
<source>粘贴</source>
<translation>Paste</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="235" />
<location filename="../src/MainWindow.cpp" line="862" />
<location filename="../src/MainWindow.cpp" line="235"/>
<location filename="../src/MainWindow.cpp" line="862"/>
<source>全选</source>
<translation>Select All</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="239" />
<location filename="../src/MainWindow.cpp" line="866" />
<location filename="../src/MainWindow.cpp" line="239"/>
<location filename="../src/MainWindow.cpp" line="866"/>
<source>自动换行</source>
<translation>Word Wrap</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="244" />
<location filename="../src/MainWindow.cpp" line="867" />
<location filename="../src/MainWindow.cpp" line="244"/>
<location filename="../src/MainWindow.cpp" line="867"/>
<source>放大</source>
<translation>Zoom In</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="248" />
<location filename="../src/MainWindow.cpp" line="868" />
<location filename="../src/MainWindow.cpp" line="248"/>
<location filename="../src/MainWindow.cpp" line="868"/>
<source>缩小</source>
<translation>Zoom Out</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="252" />
<location filename="../src/MainWindow.cpp" line="869" />
<location filename="../src/MainWindow.cpp" line="252"/>
<location filename="../src/MainWindow.cpp" line="869"/>
<source>实际大小</source>
<translation>Actual Size</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="261" />
<location filename="../src/MainWindow.cpp" line="851" />
<location filename="../src/MainWindow.cpp" line="261"/>
<location filename="../src/MainWindow.cpp" line="851"/>
<source>打开文件夹…</source>
<translation>Open Folder…</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="265" />
<location filename="../src/MainWindow.cpp" line="473" />
<location filename="../src/MainWindow.cpp" line="864" />
<location filename="../src/MainWindow.cpp" line="885" />
<location filename="../src/MainWindow.cpp" line="265"/>
<location filename="../src/MainWindow.cpp" line="473"/>
<location filename="../src/MainWindow.cpp" line="864"/>
<location filename="../src/MainWindow.cpp" line="885"/>
<source>侧栏</source>
<translation>Sidebar</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="279" />
<location filename="../src/MainWindow.cpp" line="865" />
<location filename="../src/MainWindow.cpp" line="279"/>
<location filename="../src/MainWindow.cpp" line="865"/>
<source>源代码模式</source>
<translation>Source Mode</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="284" />
<location filename="../src/MainWindow.cpp" line="881" />
<location filename="../src/MainWindow.cpp" line="284"/>
<location filename="../src/MainWindow.cpp" line="881"/>
<source>代码块</source>
<translation>Code Block</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="291" />
<location filename="../src/MainWindow.cpp" line="879" />
<location filename="../src/MainWindow.cpp" line="291"/>
<location filename="../src/MainWindow.cpp" line="879"/>
<source>标题 %1</source>
<translation>Heading %1</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="302" />
<location filename="../src/MainWindow.cpp" line="302"/>
<source>文件夹</source>
<translation>Folder</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="313" />
<location filename="../src/MainWindow.cpp" line="1030" />
<location filename="../src/MainWindow.cpp" line="313"/>
<location filename="../src/MainWindow.cpp" line="1030"/>
<source>未打开文件夹</source>
<translation>No folder open</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="331" />
<location filename="../src/MainWindow.cpp" line="1163" />
<location filename="../src/MainWindow.cpp" line="331"/>
<location filename="../src/MainWindow.cpp" line="1163"/>
<source>Git 仓库</source>
<translation>Git repository</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="343" />
<location filename="../src/MainWindow.cpp" line="1228" />
<location filename="../src/MainWindow.cpp" line="344"/>
<location filename="../src/MainWindow.cpp" line="1228"/>
<source>拉取</source>
<translation>Pull</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="343" />
<location filename="../src/MainWindow.cpp" line="344"/>
<source>git pull --ff-only</source>
<translation>git pull --ff-only</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="344" />
<location filename="../src/MainWindow.cpp" line="1236" />
<location filename="../src/MainWindow.cpp" line="343"/>
<location filename="../src/MainWindow.cpp" line="1236"/>
<source>获取</source>
<translation>Fetch</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="344" />
<location filename="../src/MainWindow.cpp" line="343"/>
<source>git fetch --all --prune</source>
<translation>git fetch --all --prune</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="345" />
<location filename="../src/MainWindow.cpp" line="1243" />
<location filename="../src/MainWindow.cpp" line="1351" />
<location filename="../src/MainWindow.cpp" line="347"/>
<location filename="../src/MainWindow.cpp" line="1243"/>
<location filename="../src/MainWindow.cpp" line="1351"/>
<source>推送</source>
<translation>Push</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="345" />
<location filename="../src/MainWindow.cpp" line="347"/>
<source>git push</source>
<translation>git push</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="346" />
<location filename="../src/MainWindow.cpp" line="1250" />
<location filename="../src/MainWindow.cpp" line="1250"/>
<source>暂存</source>
<translation>Stage</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="346" />
<location filename="../src/MainWindow.cpp" line="345"/>
<source>git add -A</source>
<translation>git add -A</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="347" />
<location filename="../src/MainWindow.cpp" line="1263" />
<location filename="../src/MainWindow.cpp" line="1270" />
<location filename="../src/MainWindow.cpp" line="1274" />
<location filename="../src/MainWindow.cpp" line="1350" />
<location filename="../src/MainWindow.cpp" line="346"/>
<location filename="../src/MainWindow.cpp" line="1263"/>
<location filename="../src/MainWindow.cpp" line="1270"/>
<location filename="../src/MainWindow.cpp" line="1274"/>
<location filename="../src/MainWindow.cpp" line="1350"/>
<source>提交</source>
<translation>Commit</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="347" />
<location filename="../src/MainWindow.cpp" line="346"/>
<source>把暂存区的内容提交</source>
<translation>Commit the staged changes</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="381" />
<location filename="../src/MainWindow.cpp" line="839" />
<location filename="../src/MainWindow.cpp" line="381"/>
<location filename="../src/MainWindow.cpp" line="839"/>
<source>文件</source>
<translation>File</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="385" />
<location filename="../src/MainWindow.cpp" line="844" />
<location filename="../src/MainWindow.cpp" line="385"/>
<location filename="../src/MainWindow.cpp" line="844"/>
<source>最近打开</source>
<translation>Recent Files</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="393" />
<location filename="../src/MainWindow.cpp" line="840" />
<location filename="../src/MainWindow.cpp" line="393"/>
<location filename="../src/MainWindow.cpp" line="840"/>
<source>编辑</source>
<translation>Edit</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="403" />
<location filename="../src/MainWindow.cpp" line="841" />
<location filename="../src/MainWindow.cpp" line="403"/>
<location filename="../src/MainWindow.cpp" line="841"/>
<source>视图</source>
<translation>View</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="414" />
<location filename="../src/MainWindow.cpp" line="845" />
<location filename="../src/MainWindow.cpp" line="414"/>
<location filename="../src/MainWindow.cpp" line="845"/>
<source>主题</source>
<translation>Theme</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="422" />
<location filename="../src/MainWindow.cpp" line="875" />
<location filename="../src/MainWindow.cpp" line="422"/>
<location filename="../src/MainWindow.cpp" line="875"/>
<source>6:00–18:00 使用浅色,其余时间使用深色</source>
<translation>Light from 6:00 to 18:00, dark the rest of the day</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="440" />
<location filename="../src/MainWindow.cpp" line="847" />
<location filename="../src/MainWindow.cpp" line="440"/>
<location filename="../src/MainWindow.cpp" line="847"/>
<source>语言</source>
<translation>Language</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="457" />
<location filename="../src/MainWindow.cpp" line="842" />
<location filename="../src/MainWindow.cpp" line="457"/>
<location filename="../src/MainWindow.cpp" line="842"/>
<source>格式</source>
<translation>Format</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="458" />
<location filename="../src/MainWindow.cpp" line="846" />
<location filename="../src/MainWindow.cpp" line="458"/>
<location filename="../src/MainWindow.cpp" line="846"/>
<source>标题</source>
<translation>Heading</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="465" />
<location filename="../src/MainWindow.cpp" line="843" />
<location filename="../src/MainWindow.cpp" line="465"/>
<location filename="../src/MainWindow.cpp" line="843"/>
<source>帮助</source>
<translation>Help</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="466" />
<location filename="../src/MainWindow.cpp" line="882" />
<location filename="../src/MainWindow.cpp" line="912" />
<location filename="../src/MainWindow.cpp" line="466"/>
<location filename="../src/MainWindow.cpp" line="882"/>
<location filename="../src/MainWindow.cpp" line="912"/>
<source>关于 VoiletMark</source>
<translation>About VoiletMark</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="477" />
<location filename="../src/MainWindow.cpp" line="886" />
<location filename="../src/MainWindow.cpp" line="477"/>
<location filename="../src/MainWindow.cpp" line="886"/>
<source>显示 / 隐藏文件夹侧栏(Ctrl+B)</source>
<translation>Show / hide the folder sidebar (Ctrl+B)</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="485" />
<location filename="../src/MainWindow.cpp" line="889" />
<location filename="../src/MainWindow.cpp" line="485"/>
<location filename="../src/MainWindow.cpp" line="889"/>
<source>源代码模式:关闭语法高亮与行号(Ctrl+Shift+M)</source>
<translation>Source mode: turn off highlighting and line numbers (Ctrl+Shift+M)</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="565" />
<location filename="../src/MainWindow.cpp" line="680" />
<location filename="../src/MainWindow.cpp" line="565"/>
<location filename="../src/MainWindow.cpp" line="680"/>
<source>未命名</source>
<translation>Untitled</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="614" />
<location filename="../src/MainWindow.cpp" line="614"/>
<source>打开 Markdown 文件</source>
<translation>Open Markdown File</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="615" />
<location filename="../src/MainWindow.cpp" line="615"/>
<source>Markdown 文件 (*.md *.markdown *.mdown *.mkd);;文本文件 (*.txt);;所有文件 (*)</source>
<translation>Markdown files (*.md *.markdown *.mdown *.mkd);;Text files (*.txt);;All files (*)</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="632" />
<location filename="../src/MainWindow.cpp" line="632"/>
<source>无法打开文件</source>
<translation>Cannot Open File</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="633" />
<location filename="../src/MainWindow.cpp" line="633"/>
<source>读取「%1」失败:%2</source>
<translation>Could not read "%1": %2</translation>
<translation>Could not read &quot;%1&quot;: %2</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="667" />
<location filename="../src/MainWindow.cpp" line="667"/>
<source>另存为</source>
<translation>Save As</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="668" />
<location filename="../src/MainWindow.cpp" line="668"/>
<source>Markdown 文件 (*.md);;文本文件 (*.txt);;所有文件 (*)</source>
<translation>Markdown files (*.md);;Text files (*.txt);;All files (*)</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="685" />
<location filename="../src/MainWindow.cpp" line="685"/>
<source>导出 PDF</source>
<translation>Export PDF</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="686" />
<location filename="../src/MainWindow.cpp" line="686"/>
<source>PDF 文件 (*.pdf)</source>
<translation>PDF files (*.pdf)</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="705" />
<location filename="../src/MainWindow.cpp" line="705"/>
<source>导出失败</source>
<translation>Export Failed</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="706" />
<location filename="../src/MainWindow.cpp" line="706"/>
<source>没能写出「%1」,换个位置再试一次。</source>
<translation>Could not write "%1". Try another location.</translation>
<translation>Could not write &quot;%1&quot;. Try another location.</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="710" />
<location filename="../src/MainWindow.cpp" line="710"/>
<source>已导出 %1</source>
<translation>Exported to %1</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="725" />
<location filename="../src/MainWindow.cpp" line="732" />
<location filename="../src/MainWindow.cpp" line="737" />
<location filename="../src/MainWindow.cpp" line="725"/>
<location filename="../src/MainWindow.cpp" line="732"/>
<location filename="../src/MainWindow.cpp" line="737"/>
<source>无法保存文件</source>
<translation>Cannot Save File</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="726" />
<location filename="../src/MainWindow.cpp" line="726"/>
<source>写入「%1」失败:%2</source>
<translation>Could not write "%1": %2</translation>
<translation>Could not write &quot;%1&quot;: %2</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="733" />
<location filename="../src/MainWindow.cpp" line="733"/>
<source>写入「%1」时发生错误。</source>
<translation>An error occurred while writing "%1".</translation>
<translation>An error occurred while writing &quot;%1&quot;.</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="738" />
<location filename="../src/MainWindow.cpp" line="738"/>
<source>提交「%1」失败:%2</source>
<translation>Could not commit "%1": %2</translation>
<translation>Could not commit &quot;%1&quot;: %2</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="746" />
<location filename="../src/MainWindow.cpp" line="746"/>
<source>已保存 %1</source>
<translation>Saved to %1</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="756" />
<location filename="../src/MainWindow.cpp" line="756"/>
<source>VoiletMark</source>
<translation>VoiletMark</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="757" />
<location filename="../src/MainWindow.cpp" line="757"/>
<source>「%1」有未保存的修改,是否保存?</source>
<translation>"%1" has unsaved changes. Save them?</translation>
<translation>&quot;%1&quot; has unsaved changes. Save them?</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="781" />
<location filename="../src/MainWindow.cpp" line="781"/>
<source>%1[*] — VoiletMark</source>
<translation>%1[*] — VoiletMark</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="800" />
<location filename="../src/MainWindow.cpp" line="800"/>
<source>行 %1,列 %2</source>
<translation>Line %1, Col %2</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="802" />
<location filename="../src/MainWindow.cpp" line="802"/>
<source> 已选 %1 字</source>
<translation> %1 selected</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="803" />
<location filename="../src/MainWindow.cpp" line="803"/>
<source> %1 字</source>
<translation> %1 chars</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="916" />
<location filename="../src/MainWindow.cpp" line="916"/>
<source>&lt;h3&gt;VoiletMark %1&lt;/h3&gt;&lt;p&gt;一个轻量的跨平台 Markdown 编辑器。&lt;/p&gt;&lt;p&gt;基于 Qt %2 与 C++17 构建。&lt;/p&gt;</source>
<translation>&lt;h3&gt;VoiletMark %1&lt;/h3&gt;&lt;p&gt;A lightweight cross-platform Markdown editor.&lt;/p&gt;&lt;p&gt;Built with Qt %2 and C++17.&lt;/p&gt;</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="951" />
<location filename="../src/MainWindow.cpp" line="951"/>
<source>(暂无记录)</source>
<translation>(none)</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="964" />
<location filename="../src/MainWindow.cpp" line="964"/>
<source>清空列表</source>
<translation>Clear List</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="974" />
<location filename="../src/MainWindow.cpp" line="974"/>
<source>打开文件夹</source>
<translation>Open Folder</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="1031" />
<location filename="../src/MainWindow.cpp" line="1031"/>
<source>文件 → 打开文件夹…</source>
<translation>File → Open Folder…</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="1067" />
<location filename="../src/MainWindow.cpp" line="1067"/>
<source>(没有 Markdown 文件)</source>
<translation>(no Markdown files)</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="1199" />
<location filename="../src/MainWindow.cpp" line="1199"/>
<source>正在%1…</source>
<translation>%1…</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="1209" />
<location filename="../src/MainWindow.cpp" line="1209"/>
<source>Git 操作失败</source>
<translation>Git Operation Failed</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="1210" />
<location filename="../src/MainWindow.cpp" line="1210"/>
<source>%1失败:
%2</source>
@@ -463,118 +463,119 @@
%2</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="1211" />
<location filename="../src/MainWindow.cpp" line="1211"/>
<source>(没有输出)</source>
<translation>(no output)</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="1217" />
<location filename="../src/MainWindow.cpp" line="1217"/>
<source>%1完成</source>
<translation>%1 finished</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="1264" />
<location filename="../src/MainWindow.cpp" line="1264"/>
<source>暂存区是空的,先点「暂存」把所有改动加进去。</source>
<translation>Nothing is staged yet. Click "Stage" first to add all changes.</translation>
<translation>Nothing is staged yet. Click &quot;Stage&quot; first to add all changes.</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="1270" />
<location filename="../src/MainWindow.cpp" line="1270"/>
<source>提交说明:</source>
<translation>Commit message:</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="1282" />
<location filename="../src/MainWindow.cpp" line="1282"/>
<source>添加到提交</source>
<translation>Add to commit</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="1301" />
<location filename="../src/MainWindow.cpp" line="1301"/>
<source>「%1」已经在 .gitignore 里了</source>
<translation>"%1" is already in .gitignore</translation>
<translation>&quot;%1&quot; is already in .gitignore</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="1307" />
<location filename="../src/MainWindow.cpp" line="1307"/>
<source>忽略文件</source>
<translation>Ignore File</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="1308" />
<location filename="../src/MainWindow.cpp" line="1308"/>
<source>打不开 .gitignore:%1</source>
<translation>Cannot open .gitignore: %1</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="1315" />
<location filename="../src/MainWindow.cpp" line="1315"/>
<source>已把 %1 写进 .gitignore</source>
<translation>Added %1 to .gitignore</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="1330" />
<location filename="../src/MainWindow.cpp" line="1335" />
<location filename="../src/MainWindow.cpp" line="1373" />
<location filename="../src/MainWindow.cpp" line="1330"/>
<location filename="../src/MainWindow.cpp" line="1335"/>
<location filename="../src/MainWindow.cpp" line="1373"/>
<source>删除远端</source>
<translation>Delete from remote</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="1331" />
<location filename="../src/MainWindow.cpp" line="1331"/>
<source>「%1」没有被 git 跟踪,远端本来就没有它。</source>
<translation>"%1" is not tracked by git, so the remote never had it.</translation>
<translation>&quot;%1&quot; is not tracked by git, so the remote never had it.</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="1336" />
<location filename="../src/MainWindow.cpp" line="1336"/>
<source>从仓库删除「%1」并推送到远端?
本地文件会保留,远端和别人 pull 下来的仓库里会删掉它。</source>
<translation>Remove "%1" from the repository and push?
<translation>Remove &quot;%1&quot; from the repository and push?
Your local file is kept, but the remote copy and everyone else's will be deleted.</translation>
Your local file is kept, but the remote copy and everyone else&apos;s will be deleted.</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="1340" />
<location filename="../src/MainWindow.cpp" line="1340"/>
<source>删除并推送</source>
<translation>Delete and push</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="1349" />
<location filename="../src/MainWindow.cpp" line="1349"/>
<source>chore: 从仓库删除 %1</source>
<translation>chore: remove %1 from repository</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="1368" />
<location filename="../src/MainWindow.cpp" line="345"/>
<location filename="../src/MainWindow.cpp" line="1368"/>
<source>添加</source>
<translation>Add</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="1369" />
<location filename="../src/MainWindow.cpp" line="1369"/>
<source>git add 这个文件</source>
<translation>git add this file</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="1370" />
<location filename="../src/MainWindow.cpp" line="1370"/>
<source>忽略</source>
<translation>Ignore</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="1371" />
<location filename="../src/MainWindow.cpp" line="1371"/>
<source>把路径写进 .gitignore(不改仓库里已跟踪的文件)</source>
<translation>Add the path to .gitignore (does not untrack files already in the repo)</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="1374" />
<location filename="../src/MainWindow.cpp" line="1374"/>
<source>git rm --cached 后提交并推送:远端删除,本地保留</source>
<translation>git rm --cached, then commit and push: gone from the remote, kept locally</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="1341" />
<location filename="../src/MainWindow.cpp" line="1341"/>
<source>取消</source>
<translation>Cancel</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="1347" />
<location filename="../src/MainWindow.cpp" line="1347"/>
<source>从仓库移除</source>
<translation>Remove from repository</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="1364" />
<location filename="../src/MainWindow.cpp" line="1364"/>
<source>打开</source>
<translation>Open</translation>
</message>
@@ -582,40 +583,40 @@ Your local file is kept, but the remote copy and everyone else's will be deleted
<context>
<name>MarkdownEditor</name>
<message>
<location filename="../src/MarkdownEditor.cpp" line="577" />
<location filename="../src/MarkdownEditor.cpp" line="701" />
<location filename="../src/MarkdownEditor.cpp" line="577"/>
<location filename="../src/MarkdownEditor.cpp" line="701"/>
<source>已复制</source>
<translation>Copied</translation>
</message>
<message>
<location filename="../src/MarkdownEditor.cpp" line="577" />
<location filename="../src/MarkdownEditor.cpp" line="701" />
<location filename="../src/MarkdownEditor.cpp" line="577"/>
<location filename="../src/MarkdownEditor.cpp" line="701"/>
<source>复制</source>
<translation>Copy</translation>
</message>
<message>
<location filename="../src/MarkdownEditor.cpp" line="632" />
<location filename="../src/MarkdownEditor.cpp" line="643" />
<location filename="../src/MarkdownEditor.cpp" line="632"/>
<location filename="../src/MarkdownEditor.cpp" line="643"/>
<source>纯文本</source>
<translation>Plain text</translation>
</message>
<message>
<location filename="../src/MarkdownEditor.cpp" line="1095" />
<location filename="../src/MarkdownEditor.cpp" line="1095"/>
<source>插入行</source>
<translation>Insert row</translation>
</message>
<message>
<location filename="../src/MarkdownEditor.cpp" line="1110" />
<location filename="../src/MarkdownEditor.cpp" line="1110"/>
<source>删除行</source>
<translation>Delete row</translation>
</message>
<message>
<location filename="../src/MarkdownEditor.cpp" line="1120" />
<location filename="../src/MarkdownEditor.cpp" line="1120"/>
<source>插入列</source>
<translation>Insert column</translation>
</message>
<message>
<location filename="../src/MarkdownEditor.cpp" line="1135" />
<location filename="../src/MarkdownEditor.cpp" line="1135"/>
<source>删除列</source>
<translation>Delete column</translation>
</message>
@@ -623,24 +624,24 @@ Your local file is kept, but the remote copy and everyone else's will be deleted
<context>
<name>QObject</name>
<message>
<location filename="../src/ThemeManager.cpp" line="364" />
<location filename="../src/ThemeManager.cpp" line="364"/>
<source>浅色</source>
<translation>Light</translation>
</message>
<message>
<location filename="../src/ThemeManager.cpp" line="365" />
<location filename="../src/ThemeManager.cpp" line="365"/>
<source>深色</source>
<translation>Dark</translation>
</message>
<message>
<location filename="../src/ThemeManager.cpp" line="366" />
<location filename="../src/ThemeManager.cpp" line="366"/>
<source>按时段自动</source>
<translation>Scheduled</translation>
</message>
<message>
<location filename="../src/ThemeManager.cpp" line="369" />
<location filename="../src/ThemeManager.cpp" line="369"/>
<source>跟随系统</source>
<translation>Follow System</translation>
</message>
</context>
</TS>
</TS>