feat: v0.11.0 —— 侧栏加「目录」页签,展示文档大纲

- 侧栏顶部两个页签:文件(默认)/ 目录,切换状态会记住
- 目录页遍历当前文档的 1–6 级标题:按层级用全角空格缩进,
  H1/H2 加粗,深层级字号略小,鼠标悬停显示完整标题
- 围栏代码块里的 # 不会被当成标题(扫描时跟踪围栏状态)
- 点目录项跳到对应行并居中;编辑停下 250ms 后自动重建目录
- 目录模式下隐藏文件夹名和 Git 工具条
- 新增 4 条翻译(目录 / Outline、没有标题 等)
- 版本 0.11.0
This commit is contained in:
2026-10-23 10:51:35 +08:00
parent 4f5fd0eeaa
commit 09e8f13901
11 changed files with 379 additions and 190 deletions
+4 -1
View File
@@ -2,7 +2,7 @@
一个轻量的跨平台 Markdown 编辑器,基于 **Qt 5 / C++17** 构建。
当前版本 **0.10.5**。
当前版本 **0.11.0**。
## 界面
@@ -43,6 +43,9 @@
- **文件 → 打开文件夹…**(`Ctrl+Shift+O`)选一个目录,递归扫描
`*.md` / `*.markdown` / `*.mdown` / `*.mkd`
- 侧栏顶部两个页签:**文件**(默认)/ **目录**
- **目录**页把当前文档的 1–6 级标题列成大纲(代码块里的 `#` 不算),
按层级缩进,点一下跳到对应行;编辑时自动刷新
- 状态栏左下角的「侧栏」按钮或 `Ctrl+B` 显示 / 隐藏
- 点文件名即打开,当前文件在列表里高亮
- 每 5 秒自动扫描一次:目录里新增 / 删除的 Markdown 会自动出现在列表里
+1 -1
View File
@@ -1,6 +1,6 @@
TEMPLATE = app
TARGET = VoiletMark
VERSION = 0.10.6
VERSION = 0.11.0
QT += core gui widgets
Binary file not shown.

Before

Width:  |  Height:  |  Size: 110 KiB

After

Width:  |  Height:  |  Size: 111 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 110 KiB

After

Width:  |  Height:  |  Size: 111 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 126 KiB

After

Width:  |  Height:  |  Size: 126 KiB

+139 -3
View File
@@ -35,6 +35,7 @@
#include <QSaveFile>
#include <QSettings>
#include <QSignalBlocker>
#include <QStackedWidget>
#include <QStandardPaths>
#include <QStatusBar>
#include <QTextBlock>
@@ -322,17 +323,65 @@ void MainWindow::createSidebar()
layout->setContentsMargins(8, 8, 8, 8);
layout->setSpacing(6);
// 侧栏两种模式:文件 / 目录
QHBoxLayout *modeLayout = new QHBoxLayout();
modeLayout->setContentsMargins(0, 0, 0, 0);
modeLayout->setSpacing(4);
auto makeModeButton = [this, content](const QString &text) {
QToolButton *button = new QToolButton(content);
button->setText(text);
button->setCheckable(true);
button->setCursor(Qt::PointingHandCursor);
button->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
return button;
};
m_fileModeButton = makeModeButton(tr("文件"));
m_tocModeButton = makeModeButton(tr("目录"));
m_fileModeButton->setChecked(true);
modeLayout->addWidget(m_fileModeButton);
modeLayout->addWidget(m_tocModeButton);
layout->addLayout(modeLayout);
connect(m_fileModeButton, &QToolButton::clicked, this, [this] { switchSidebarMode(0); });
connect(m_tocModeButton, &QToolButton::clicked, this, [this] { switchSidebarMode(1); });
m_folderLabel = new QLabel(tr("未打开文件夹"), content);
m_folderLabel->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Preferred);
layout->addWidget(m_folderLabel);
m_fileList = new QListWidget(content);
m_sidebarStack = new QStackedWidget(content);
m_fileList = new QListWidget(m_sidebarStack);
m_fileList->setFrameShape(QFrame::NoFrame);
m_fileList->setUniformItemSizes(true);
m_fileList->setTextElideMode(Qt::ElideMiddle);
m_fileList->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
m_fileList->setContextMenuPolicy(Qt::CustomContextMenu);
layout->addWidget(m_fileList, 1);
m_sidebarStack->addWidget(m_fileList);
m_tocList = new QListWidget(m_sidebarStack);
m_tocList->setFrameShape(QFrame::NoFrame);
m_tocList->setTextElideMode(Qt::ElideRight);
m_tocList->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
m_sidebarStack->addWidget(m_tocList);
layout->addWidget(m_sidebarStack, 1);
connect(m_tocList, &QListWidget::itemClicked, this, &MainWindow::goToTocItem);
m_tocTimer = new QTimer(this);
m_tocTimer->setSingleShot(true);
m_tocTimer->setInterval(250);
connect(m_tocTimer, &QTimer::timeout, this, [this] {
if (m_sidebarMode == 1)
rebuildToc();
});
connect(m_editor, &QPlainTextEdit::textChanged, this, [this] {
if (m_sidebarMode == 1)
m_tocTimer->start();
});
// ---- Git 工具条:只有打开的是仓库时才显示 ----
m_gitBar = new QWidget(content);
@@ -532,6 +581,10 @@ void MainWindow::loadSettings()
m_themeDarkAction->setChecked(mode == ThemeManager::Mode::Dark);
m_themeScheduleAction->setChecked(mode == ThemeManager::Mode::Schedule);
const int sidebarMode =
settings.value(QStringLiteral("window/sidebarMode"), 0).toInt();
switchSidebarMode(sidebarMode);
m_folderPath = settings.value(QStringLiteral("files/folder")).toString();
if (!m_folderPath.isEmpty() && QFileInfo(m_folderPath).isDir())
refreshFolder();
@@ -1223,7 +1276,7 @@ void MainWindow::updateGitState()
m_git->setWorkingDirectory(m_gitRoot.isEmpty() ? m_folderPath : m_gitRoot);
if (m_gitBar) {
m_gitBar->setVisible(!m_gitRoot.isEmpty());
m_gitBar->setVisible(!m_gitRoot.isEmpty() && m_sidebarMode == 0);
m_gitStatusLabel->setText(m_gitBranch.isEmpty() ? tr("Git 仓库") : m_gitBranch);
m_gitStatusLabel->setToolTip(m_gitRoot);
}
@@ -1285,6 +1338,89 @@ void MainWindow::onGitFinished(bool ok, const QString &label, const QString &out
}
}
void MainWindow::switchSidebarMode(int mode)
{
m_sidebarMode = qBound(0, mode, 1);
if (m_sidebarStack)
m_sidebarStack->setCurrentIndex(m_sidebarMode);
if (m_fileModeButton && m_tocModeButton) {
m_fileModeButton->setChecked(m_sidebarMode == 0);
m_tocModeButton->setChecked(m_sidebarMode == 1);
}
if (m_folderLabel)
m_folderLabel->setVisible(m_sidebarMode == 0);
if (m_gitBar)
m_gitBar->setVisible(m_sidebarMode == 0 && !m_gitRoot.isEmpty());
if (m_sidebarMode == 1)
rebuildToc();
QSettings().setValue(QStringLiteral("window/sidebarMode"), m_sidebarMode);
}
void MainWindow::rebuildToc()
{
if (!m_tocList || !m_editor)
return;
m_tocList->clear();
static const QRegularExpression headingPattern(
QStringLiteral(R"(^\s{0,3}(#{1,6})\s+(.+?)\s*#*\s*$)"));
static const QRegularExpression fencePattern(
QStringLiteral("^\\s{0,3}(?:\\x60\\x60\\x60|~~~)"));
bool inFence = false;
QTextBlock block = m_editor->document()->firstBlock();
while (block.isValid()) {
const QString text = block.text();
if (fencePattern.match(text).hasMatch()) {
inFence = !inFence;
block = block.next();
continue;
}
if (!inFence) {
const QRegularExpressionMatch match = headingPattern.match(text);
if (match.hasMatch()) {
const int level = match.capturedLength(1);
QListWidgetItem *item = new QListWidgetItem(
QString(level - 1, QChar(0x2003)) + match.captured(2).trimmed(), m_tocList);
item->setData(Qt::UserRole, block.blockNumber());
item->setToolTip(match.captured(2).trimmed());
if (level <= 2) {
QFont font = item->font();
font.setBold(true);
item->setFont(font);
} else {
QFont font = item->font();
font.setPointSizeF(qMax(7.0, font.pointSizeF() - 0.5));
item->setFont(font);
}
}
}
block = block.next();
}
if (m_tocList->count() == 0) {
QListWidgetItem *empty = new QListWidgetItem(tr("(没有标题)"), m_tocList);
empty->setFlags(Qt::NoItemFlags);
}
}
void MainWindow::goToTocItem(QListWidgetItem *item)
{
if (!item)
return;
const QVariant data = item->data(Qt::UserRole);
if (!data.isValid())
return;
m_editor->goToBlock(data.toInt());
}
void MainWindow::gitPull()
{
if (m_gitRoot.isEmpty())
+13
View File
@@ -9,6 +9,8 @@ class QActionGroup;
class QDockWidget;
class QLabel;
class QPushButton;
class QStackedWidget;
class QToolButton;
class GitRunner;
class QListWidget;
class QListWidgetItem;
@@ -69,6 +71,10 @@ private:
void gitIgnoreFile(const QString &path);
void gitRemoveRemote(const QString &path);
void gitCommit();
void switchSidebarMode(int mode);
void rebuildToc();
void goToTocItem(QListWidgetItem *item);
void gitPull();
void gitFetch();
void gitPush();
@@ -102,6 +108,13 @@ private:
QToolButton *m_sourceButton = nullptr;
QToolButton *m_sidebarButton = nullptr;
QStackedWidget *m_sidebarStack = nullptr;
QToolButton *m_fileModeButton = nullptr;
QToolButton *m_tocModeButton = nullptr;
QListWidget *m_tocList = nullptr;
QTimer *m_tocTimer = nullptr;
int m_sidebarMode = 0;
GitRunner *m_git = nullptr;
QWidget *m_gitBar = nullptr;
QLabel *m_gitStatusLabel = nullptr;
+13
View File
@@ -367,6 +367,19 @@ void MarkdownEditor::selectBlocks(int firstBlock, int lastBlock)
setTextCursor(cursor);
}
void MarkdownEditor::goToBlock(int blockNumber)
{
const QTextBlock block = document()->findBlockByNumber(blockNumber);
if (!block.isValid())
return;
QTextCursor cursor(block);
cursor.movePosition(QTextCursor::StartOfBlock);
setTextCursor(cursor);
centerCursor();
setFocus();
}
void MarkdownEditor::setHeadingLevel(int level)
{
level = qBound(0, level, 6);
+3
View File
@@ -39,6 +39,9 @@ public:
/// 把选中内容包成围栏代码块;如果已经围起来了则拆掉。
void toggleCodeBlock();
/// 把光标移到指定行并居中显示(目录跳转用)。
void goToBlock(int blockNumber);
signals:
void zoomStepRequested(int direction);
void fileDropped(const QString &path);
Binary file not shown.
+206 -185
View File
@@ -1,10 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<?xml version='1.0' encoding='utf-8'?>
<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>
@@ -14,447 +13,464 @@
<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="204" />
<location filename="../src/MainWindow.cpp" line="965" />
<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="208" />
<location filename="../src/MainWindow.cpp" line="966" />
<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="212" />
<location filename="../src/MainWindow.cpp" line="968" />
<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="216" />
<location filename="../src/MainWindow.cpp" line="969" />
<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="220" />
<location filename="../src/MainWindow.cpp" line="970" />
<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="224" />
<location filename="../src/MainWindow.cpp" line="971" />
<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="228" />
<location filename="../src/MainWindow.cpp" line="973" />
<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="232" />
<location filename="../src/MainWindow.cpp" line="974" />
<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="236" />
<location filename="../src/MainWindow.cpp" line="975" />
<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="240" />
<location filename="../src/MainWindow.cpp" line="976" />
<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="244" />
<location filename="../src/MainWindow.cpp" line="977" />
<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="248" />
<location filename="../src/MainWindow.cpp" line="978" />
<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="252" />
<location filename="../src/MainWindow.cpp" line="982" />
<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="257" />
<location filename="../src/MainWindow.cpp" line="983" />
<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="261" />
<location filename="../src/MainWindow.cpp" line="984" />
<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="265" />
<location filename="../src/MainWindow.cpp" line="985" />
<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="274" />
<location filename="../src/MainWindow.cpp" line="967" />
<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="278" />
<location filename="../src/MainWindow.cpp" line="534" />
<location filename="../src/MainWindow.cpp" line="980" />
<location filename="../src/MainWindow.cpp" line="1001" />
<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="292" />
<location filename="../src/MainWindow.cpp" line="981" />
<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="297" />
<location filename="../src/MainWindow.cpp" line="997" />
<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="304" />
<location filename="../src/MainWindow.cpp" line="995" />
<source>标题 %1</source>
<translation>Heading %1</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="302"/>
<location filename="../src/MainWindow.cpp" line="315" />
<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="350" />
<location filename="../src/MainWindow.cpp" line="1147" />
<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="392" />
<location filename="../src/MainWindow.cpp" line="1280" />
<source>Git 仓库</source>
<translation>Git repository</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="344"/>
<location filename="../src/MainWindow.cpp" line="1228"/>
<location filename="../src/MainWindow.cpp" line="405" />
<location filename="../src/MainWindow.cpp" line="1428" />
<source>拉取</source>
<translation>Pull</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="344"/>
<location filename="../src/MainWindow.cpp" line="405" />
<source>git pull --ff-only</source>
<translation>git pull --ff-only</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="343"/>
<location filename="../src/MainWindow.cpp" line="1236"/>
<location filename="../src/MainWindow.cpp" line="404" />
<location filename="../src/MainWindow.cpp" line="1436" />
<source>获取</source>
<translation>Fetch</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="343"/>
<location filename="../src/MainWindow.cpp" line="404" />
<source>git fetch --all --prune</source>
<translation>git fetch --all --prune</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="347"/>
<location filename="../src/MainWindow.cpp" line="1243"/>
<location filename="../src/MainWindow.cpp" line="1351"/>
<location filename="../src/MainWindow.cpp" line="408" />
<location filename="../src/MainWindow.cpp" line="1443" />
<location filename="../src/MainWindow.cpp" line="1551" />
<source>推送</source>
<translation>Push</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="347"/>
<location filename="../src/MainWindow.cpp" line="408" />
<source>git push</source>
<translation>git push</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="1250"/>
<location filename="../src/MainWindow.cpp" line="1450" />
<source>暂存</source>
<translation>Stage</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="345"/>
<location filename="../src/MainWindow.cpp" line="406" />
<source>git add -A</source>
<translation>git add -A</translation>
</message>
<message>
<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"/>
<location filename="../src/MainWindow.cpp" line="407" />
<location filename="../src/MainWindow.cpp" line="1463" />
<location filename="../src/MainWindow.cpp" line="1470" />
<location filename="../src/MainWindow.cpp" line="1474" />
<location filename="../src/MainWindow.cpp" line="1550" />
<source>提交</source>
<translation>Commit</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="346"/>
<location filename="../src/MainWindow.cpp" line="407" />
<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="340" />
<location filename="../src/MainWindow.cpp" line="442" />
<location filename="../src/MainWindow.cpp" line="955" />
<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="341" />
<source>目录</source>
<translation>Outline</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="446" />
<location filename="../src/MainWindow.cpp" line="960" />
<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="454" />
<location filename="../src/MainWindow.cpp" line="956" />
<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="464" />
<location filename="../src/MainWindow.cpp" line="957" />
<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="475" />
<location filename="../src/MainWindow.cpp" line="961" />
<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="483" />
<location filename="../src/MainWindow.cpp" line="991" />
<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="501" />
<location filename="../src/MainWindow.cpp" line="963" />
<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="518" />
<location filename="../src/MainWindow.cpp" line="958" />
<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="519" />
<location filename="../src/MainWindow.cpp" line="962" />
<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="526" />
<location filename="../src/MainWindow.cpp" line="959" />
<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="527" />
<location filename="../src/MainWindow.cpp" line="998" />
<location filename="../src/MainWindow.cpp" line="1028" />
<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="538" />
<location filename="../src/MainWindow.cpp" line="1002" />
<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="546" />
<location filename="../src/MainWindow.cpp" line="1005" />
<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="630" />
<location filename="../src/MainWindow.cpp" line="761" />
<source>未命名</source>
<translation>Untitled</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="614"/>
<location filename="../src/MainWindow.cpp" line="679" />
<source>打开 Markdown 文件</source>
<translation>Open Markdown File</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="615"/>
<location filename="../src/MainWindow.cpp" line="680" />
<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="698" />
<source>无法打开文件</source>
<translation>Cannot Open File</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="633"/>
<location filename="../src/MainWindow.cpp" line="699" />
<source>读取「%1」失败:%2</source>
<translation>Could not read &quot;%1&quot;: %2</translation>
<translation>Could not read "%1": %2</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="667"/>
<location filename="../src/MainWindow.cpp" line="733" />
<source>另存为</source>
<translation>Save As</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="668"/>
<location filename="../src/MainWindow.cpp" line="734" />
<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="766" />
<source>导出 PDF</source>
<translation>Export PDF</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="686"/>
<location filename="../src/MainWindow.cpp" line="767" />
<source>PDF 文件 (*.pdf)</source>
<translation>PDF files (*.pdf)</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="705"/>
<location filename="../src/MainWindow.cpp" line="774" />
<source>正在导出 PDF…</source>
<translation>Exporting PDF…</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="811" />
<location filename="../src/MainWindow.cpp" line="821" />
<source>导出失败</source>
<translation>Export Failed</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="706"/>
<source>没能写出「%1」,换个位置再试一次。</source>
<translation>Could not write &quot;%1&quot;. Try another location.</translation>
<location filename="../src/MainWindow.cpp" line="811" />
<source>文档排版结果异常,已中止导出。</source>
<translation>The document layout looks broken; export was aborted.</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="710"/>
<location filename="../src/MainWindow.cpp" line="822" />
<source>没能写出「%1」,换个位置再试一次。</source>
<translation>Could not write "%1". Try another location.</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="826" />
<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="841" />
<location filename="../src/MainWindow.cpp" line="848" />
<location filename="../src/MainWindow.cpp" line="853" />
<source>无法保存文件</source>
<translation>Cannot Save File</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="726"/>
<location filename="../src/MainWindow.cpp" line="842" />
<source>写入「%1」失败:%2</source>
<translation>Could not write &quot;%1&quot;: %2</translation>
<translation>Could not write "%1": %2</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="733"/>
<location filename="../src/MainWindow.cpp" line="849" />
<source>写入「%1」时发生错误。</source>
<translation>An error occurred while writing &quot;%1&quot;.</translation>
<translation>An error occurred while writing "%1".</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="738"/>
<location filename="../src/MainWindow.cpp" line="854" />
<source>提交「%1」失败:%2</source>
<translation>Could not commit &quot;%1&quot;: %2</translation>
<translation>Could not commit "%1": %2</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="746"/>
<location filename="../src/MainWindow.cpp" line="862" />
<source>已保存 %1</source>
<translation>Saved to %1</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="756"/>
<location filename="../src/MainWindow.cpp" line="872" />
<source>VoiletMark</source>
<translation>VoiletMark</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="757"/>
<location filename="../src/MainWindow.cpp" line="873" />
<source>「%1」有未保存的修改,是否保存?</source>
<translation>&quot;%1&quot; has unsaved changes. Save them?</translation>
<translation>"%1" has unsaved changes. Save them?</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="781"/>
<location filename="../src/MainWindow.cpp" line="897" />
<source>%1[*] — VoiletMark</source>
<translation>%1[*] — VoiletMark</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="800"/>
<location filename="../src/MainWindow.cpp" line="916" />
<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="918" />
<source> 已选 %1 字</source>
<translation> %1 selected</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="803"/>
<location filename="../src/MainWindow.cpp" line="919" />
<source> %1 字</source>
<translation> %1 chars</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="916"/>
<location filename="../src/MainWindow.cpp" line="1032" />
<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="1067" />
<source>(暂无记录)</source>
<translation>(none)</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="964"/>
<location filename="../src/MainWindow.cpp" line="1080" />
<source>清空列表</source>
<translation>Clear List</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="974"/>
<location filename="../src/MainWindow.cpp" line="1090" />
<source>打开文件夹</source>
<translation>Open Folder</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="1031"/>
<location filename="../src/MainWindow.cpp" line="1148" />
<source>文件 → 打开文件夹…</source>
<translation>File → Open Folder…</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="1067"/>
<location filename="../src/MainWindow.cpp" line="1184" />
<source>(没有 Markdown 文件)</source>
<translation>(no Markdown files)</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="1199"/>
<location filename="../src/MainWindow.cpp" line="1316" />
<source>正在%1…</source>
<translation>%1…</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="1209"/>
<location filename="../src/MainWindow.cpp" line="1326" />
<source>Git 操作失败</source>
<translation>Git Operation Failed</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="1210"/>
<location filename="../src/MainWindow.cpp" line="1327" />
<source>%1失败:
%2</source>
@@ -463,119 +479,124 @@
%2</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="1211"/>
<location filename="../src/MainWindow.cpp" line="1328" />
<source>(没有输出)</source>
<translation>(no output)</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="1217"/>
<location filename="../src/MainWindow.cpp" line="1334" />
<source>%1完成</source>
<translation>%1 finished</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="1264"/>
<source>暂存区是空的,先点「暂存」把所有改动加进去。</source>
<translation>Nothing is staged yet. Click &quot;Stage&quot; first to add all changes.</translation>
<location filename="../src/MainWindow.cpp" line="1409" />
<source>(没有标题)</source>
<translation>(no headings)</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="1270"/>
<location filename="../src/MainWindow.cpp" line="1464" />
<source>暂存区是空的,先点「暂存」把所有改动加进去。</source>
<translation>Nothing is staged yet. Click "Stage" first to add all changes.</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="1470" />
<source>提交说明:</source>
<translation>Commit message:</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="1282"/>
<location filename="../src/MainWindow.cpp" line="1482" />
<source>添加到提交</source>
<translation>Add to commit</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="1301"/>
<location filename="../src/MainWindow.cpp" line="1501" />
<source>「%1」已经在 .gitignore 里了</source>
<translation>&quot;%1&quot; is already in .gitignore</translation>
<translation>"%1" is already in .gitignore</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="1307"/>
<location filename="../src/MainWindow.cpp" line="1507" />
<source>忽略文件</source>
<translation>Ignore File</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="1308"/>
<location filename="../src/MainWindow.cpp" line="1508" />
<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="1515" />
<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="1530" />
<location filename="../src/MainWindow.cpp" line="1535" />
<location filename="../src/MainWindow.cpp" line="1573" />
<source>删除远端</source>
<translation>Delete from remote</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="1331"/>
<location filename="../src/MainWindow.cpp" line="1531" />
<source>「%1」没有被 git 跟踪,远端本来就没有它。</source>
<translation>&quot;%1&quot; is not tracked by git, so the remote never had it.</translation>
<translation>"%1" 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="1536" />
<source>从仓库删除「%1」并推送到远端?
本地文件会保留,远端和别人 pull 下来的仓库里会删掉它。</source>
<translation>Remove &quot;%1&quot; from the repository and push?
<translation>Remove "%1" from the repository and push?
Your local file is kept, but the remote copy and everyone else&apos;s will be deleted.</translation>
Your local file is kept, but the remote copy and everyone else's will be deleted.</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="1340"/>
<location filename="../src/MainWindow.cpp" line="1540" />
<source>删除并推送</source>
<translation>Delete and push</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="1349"/>
<location filename="../src/MainWindow.cpp" line="1549" />
<source>chore: 从仓库删除 %1</source>
<translation>chore: remove %1 from repository</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="345"/>
<location filename="../src/MainWindow.cpp" line="1368"/>
<location filename="../src/MainWindow.cpp" line="406" />
<location filename="../src/MainWindow.cpp" line="1568" />
<source>添加</source>
<translation>Add</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="1369"/>
<location filename="../src/MainWindow.cpp" line="1569" />
<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="1570" />
<source>忽略</source>
<translation>Ignore</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="1371"/>
<location filename="../src/MainWindow.cpp" line="1571" />
<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="1574" />
<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="1541" />
<source>取消</source>
<translation>Cancel</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="1347"/>
<location filename="../src/MainWindow.cpp" line="1547" />
<source>从仓库移除</source>
<translation>Remove from repository</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="1364"/>
<location filename="../src/MainWindow.cpp" line="1564" />
<source>打开</source>
<translation>Open</translation>
</message>
@@ -583,40 +604,40 @@ Your local file is kept, but the remote copy and everyone else&apos;s will be de
<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="590" />
<location filename="../src/MarkdownEditor.cpp" line="714" />
<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="590" />
<location filename="../src/MarkdownEditor.cpp" line="714" />
<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="645" />
<location filename="../src/MarkdownEditor.cpp" line="656" />
<source>纯文本</source>
<translation>Plain text</translation>
</message>
<message>
<location filename="../src/MarkdownEditor.cpp" line="1095"/>
<location filename="../src/MarkdownEditor.cpp" line="1108" />
<source>插入行</source>
<translation>Insert row</translation>
</message>
<message>
<location filename="../src/MarkdownEditor.cpp" line="1110"/>
<location filename="../src/MarkdownEditor.cpp" line="1123" />
<source>删除行</source>
<translation>Delete row</translation>
</message>
<message>
<location filename="../src/MarkdownEditor.cpp" line="1120"/>
<location filename="../src/MarkdownEditor.cpp" line="1133" />
<source>插入列</source>
<translation>Insert column</translation>
</message>
<message>
<location filename="../src/MarkdownEditor.cpp" line="1135"/>
<location filename="../src/MarkdownEditor.cpp" line="1148" />
<source>删除列</source>
<translation>Delete column</translation>
</message>
@@ -624,24 +645,24 @@ Your local file is kept, but the remote copy and everyone else&apos;s will be de
<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>