feat: v0.9.0 —— 文件夹是 git 仓库时接入常用操作
编辑器 - 语言下拉挪到代码框右下角,复制仍在右上角 Git - 打开文件夹时检测 git 仓库(rev-parse --show-toplevel),是的话侧栏底部 出现工具条,显示当前分支,按钮:拉取(pull --ff-only)、获取(fetch --all --prune)、 推送(push)、暂存(add -A)、提交(commit -m) - 侧栏文件右键:打开 / 添加到提交(git add -- file) / 忽略(并从远端删除) - 忽略流程:写入 .gitignore → git rm --cached → 提交 → 推送,执行前弹确认框 逐条列出命令;本地文件保留,远端删除 - 新增 GitRunner:QProcess 异步执行,MergedChannels 收集输出,90 秒超时 - 多步操作走队列,按顺序执行,失败即中止并弹出 git 原始输出 其它 - 新增 29 条中英文翻译 - README 增加 Git 一节,代码结构更新 - 版本 0.9.0
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
|
||||
一个轻量的跨平台 Markdown 编辑器,基于 **Qt 5 / C++17** 构建。
|
||||
|
||||
当前版本 **0.8.1**。
|
||||
当前版本 **0.9.0**。
|
||||
|
||||
## 界面
|
||||
|
||||
@@ -45,6 +45,27 @@
|
||||
- 每 5 秒自动扫描一次:目录里新增 / 删除的 Markdown 会自动出现在列表里
|
||||
- 上次打开的文件夹会被记住,下次启动自动恢复
|
||||
|
||||
### Git
|
||||
|
||||
打开的文件夹如果是个 git 仓库,侧栏底部会出现一行 Git 工具条(显示当前分支):
|
||||
|
||||
| 按钮 | 实际执行 |
|
||||
| --- | --- |
|
||||
| 拉取 | `git pull --ff-only` |
|
||||
| 获取 | `git fetch --all --prune` |
|
||||
| 推送 | `git push` |
|
||||
| 暂存 | `git add -A` |
|
||||
| 提交 | 填说明后 `git commit -m` |
|
||||
|
||||
右键侧栏里的文件还有两项:
|
||||
|
||||
- **添加到提交** → `git add -- <file>`
|
||||
- **忽略(并从远端删除)** → 写进 `.gitignore` + `git rm --cached` + 提交 + 推送。
|
||||
**远端会真的删掉这个文件**,所以点之前会弹确认框,把要执行的命令逐条列出来;
|
||||
本地文件保留。
|
||||
|
||||
所有命令都是异步跑的,不会卡界面;失败时弹窗显示 git 的原始输出。
|
||||
|
||||
### 编辑模式 / 源代码模式
|
||||
|
||||
默认是**编辑模式**,按“写字”的排版来:
|
||||
@@ -195,16 +216,19 @@ VoiletMark --screenshot a.png # 渲染窗口截图后退出(调试 / 视觉
|
||||
|
||||
```
|
||||
src/
|
||||
├── main.cpp 入口:命令行解析、Fusion 样式、主题初始化
|
||||
├── main.cpp 入口:命令行解析、Fusion 样式、主题 / 语言初始化
|
||||
├── ThemeManager.{h,cpp} 四种主题模式 + 系统检测 + 调色板 / QSS 生成
|
||||
├── MainWindow.{h,cpp} 菜单、文件读写、文件夹侧栏、状态栏、设置
|
||||
├── MarkdownEditor.{h,cpp} 编辑器控件:行号、缩进、标题 / 代码块命令、源码模式
|
||||
├── MarkdownHighlighter.{h,cpp} Markdown 着色与就地渲染(隐藏标记、标题缩放)
|
||||
├── MarkdownRenderer.{h,cpp} 导出用的 Markdown → 富文本文档转换
|
||||
└── ExportDialog.{h,cpp} PDF 预览与保存对话框
|
||||
├── LanguageManager.{h,cpp} 中英文切换
|
||||
├── MainWindow.{h,cpp} 菜单、文件读写、侧栏、Git 工具栏、状态栏、设置
|
||||
├── MarkdownEditor.{h,cpp} 编辑器控件:行号、缩进、代码框装饰、源码模式
|
||||
├── MarkdownHighlighter.{h,cpp} Markdown 着色与就地渲染
|
||||
├── CodeHighlight.{h,cpp} 多语言语法高亮 tokenizer
|
||||
├── MarkdownRenderer.{h,cpp} 导出用的 Markdown → 富文本文档转换
|
||||
└── GitRunner.{h,cpp} 异步执行 git 命令
|
||||
|
||||
logo.png 图标源文件
|
||||
resources.qrc 窗口图标资源
|
||||
resources.qrc 窗口图标与翻译资源
|
||||
translations/ 中英文翻译(.ts / .qm)
|
||||
packaging/ 各平台图标(ico / icns / png)与 .desktop
|
||||
```
|
||||
|
||||
|
||||
+3
-1
@@ -1,6 +1,6 @@
|
||||
TEMPLATE = app
|
||||
TARGET = VoiletMark
|
||||
VERSION = 0.8.2
|
||||
VERSION = 0.9.0
|
||||
|
||||
QT += core gui widgets printsupport
|
||||
|
||||
@@ -24,6 +24,7 @@ SOURCES += \
|
||||
src/MarkdownHighlighter.cpp \
|
||||
src/MarkdownRenderer.cpp \
|
||||
src/CodeHighlight.cpp \
|
||||
src/GitRunner.cpp \
|
||||
src/LanguageManager.cpp \
|
||||
src/ThemeManager.cpp
|
||||
|
||||
@@ -33,6 +34,7 @@ HEADERS += \
|
||||
src/MarkdownHighlighter.h \
|
||||
src/MarkdownRenderer.h \
|
||||
src/CodeHighlight.h \
|
||||
src/GitRunner.h \
|
||||
src/LanguageManager.h \
|
||||
src/ThemeManager.h
|
||||
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
#include "GitRunner.h"
|
||||
|
||||
#include <QProcess>
|
||||
#include <QTimer>
|
||||
|
||||
GitRunner::GitRunner(QObject *parent)
|
||||
: QObject(parent)
|
||||
, m_process(new QProcess(this))
|
||||
, m_timeout(new QTimer(this))
|
||||
{
|
||||
m_process->setProcessChannelMode(QProcess::MergedChannels);
|
||||
|
||||
connect(m_process, &QProcess::readyReadStandardOutput, this, [this] {
|
||||
m_output += QString::fromLocal8Bit(m_process->readAllStandardOutput());
|
||||
});
|
||||
|
||||
connect(m_process, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished), this,
|
||||
[this](int code, QProcess::ExitStatus status) {
|
||||
report(code == 0 && status == QProcess::NormalExit);
|
||||
});
|
||||
|
||||
connect(m_process, &QProcess::errorOccurred, this, [this](QProcess::ProcessError error) {
|
||||
if (error == QProcess::FailedToStart)
|
||||
report(false);
|
||||
});
|
||||
|
||||
m_timeout->setSingleShot(true);
|
||||
m_timeout->setInterval(90000);
|
||||
connect(m_timeout, &QTimer::timeout, this, [this] {
|
||||
if (m_process->state() == QProcess::NotRunning)
|
||||
return;
|
||||
m_output += tr("\n(超时,已中止)");
|
||||
m_process->kill();
|
||||
});
|
||||
}
|
||||
|
||||
void GitRunner::setWorkingDirectory(const QString &directory)
|
||||
{
|
||||
m_directory = directory;
|
||||
}
|
||||
|
||||
bool GitRunner::isBusy() const
|
||||
{
|
||||
return m_process->state() != QProcess::NotRunning;
|
||||
}
|
||||
|
||||
void GitRunner::run(const QStringList &arguments, const QString &label)
|
||||
{
|
||||
if (isBusy())
|
||||
return;
|
||||
|
||||
m_label = label;
|
||||
m_output.clear();
|
||||
m_reported = false;
|
||||
|
||||
m_process->setWorkingDirectory(m_directory);
|
||||
m_process->start(QStringLiteral("git"), arguments);
|
||||
m_timeout->start();
|
||||
|
||||
emit started(label);
|
||||
}
|
||||
|
||||
void GitRunner::report(bool ok)
|
||||
{
|
||||
if (m_reported)
|
||||
return;
|
||||
m_reported = true;
|
||||
m_timeout->stop();
|
||||
emit finished(ok, m_label, m_output.trimmed());
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
#pragma once
|
||||
|
||||
#include <QObject>
|
||||
#include <QStringList>
|
||||
|
||||
class QProcess;
|
||||
class QTimer;
|
||||
|
||||
/// 异步执行 git 命令,避免 pull / push 这种网络操作把界面卡住。
|
||||
class GitRunner : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit GitRunner(QObject *parent = nullptr);
|
||||
|
||||
void setWorkingDirectory(const QString &directory);
|
||||
bool isBusy() const;
|
||||
|
||||
void run(const QStringList &arguments, const QString &label);
|
||||
|
||||
signals:
|
||||
void started(const QString &label);
|
||||
void finished(bool ok, const QString &label, const QString &output);
|
||||
|
||||
private:
|
||||
void report(bool ok);
|
||||
|
||||
QString m_directory;
|
||||
QProcess *m_process = nullptr;
|
||||
QTimer *m_timeout = nullptr;
|
||||
QString m_label;
|
||||
QString m_output;
|
||||
bool m_reported = false;
|
||||
};
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "MainWindow.h"
|
||||
|
||||
#include "GitRunner.h"
|
||||
#include "LanguageManager.h"
|
||||
#include "MarkdownEditor.h"
|
||||
#include "MarkdownRenderer.h"
|
||||
@@ -16,7 +17,9 @@
|
||||
#include <QFileDialog>
|
||||
#include <QFileInfo>
|
||||
#include <QFrame>
|
||||
#include <QGridLayout>
|
||||
#include <QHBoxLayout>
|
||||
#include <QInputDialog>
|
||||
#include <QLabel>
|
||||
#include <QListWidget>
|
||||
#include <QMenu>
|
||||
@@ -25,13 +28,16 @@
|
||||
#include <QPageLayout>
|
||||
#include <QPageSize>
|
||||
#include <QPixmap>
|
||||
#include <QProcess>
|
||||
#include <QPrinter>
|
||||
#include <QPushButton>
|
||||
#include <QSaveFile>
|
||||
#include <QSettings>
|
||||
#include <QSignalBlocker>
|
||||
#include <QStandardPaths>
|
||||
#include <QStatusBar>
|
||||
#include <QTextBlock>
|
||||
#include <QTextStream>
|
||||
#include <QTextCursor>
|
||||
#include <QTextDocument>
|
||||
#include <QTimer>
|
||||
@@ -141,6 +147,9 @@ MainWindow::MainWindow(QWidget *parent)
|
||||
m_editor = new MarkdownEditor(this);
|
||||
setCentralWidget(m_editor);
|
||||
|
||||
m_git = new GitRunner(this);
|
||||
connect(m_git, &GitRunner::finished, this, &MainWindow::onGitFinished);
|
||||
|
||||
createActions();
|
||||
createSidebar();
|
||||
createMenus();
|
||||
@@ -298,8 +307,50 @@ void MainWindow::createSidebar()
|
||||
m_fileList->setUniformItemSizes(true);
|
||||
m_fileList->setTextElideMode(Qt::ElideMiddle);
|
||||
m_fileList->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||||
m_fileList->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
layout->addWidget(m_fileList, 1);
|
||||
|
||||
// ---- Git 工具条:只有打开的是仓库时才显示 ----
|
||||
m_gitBar = new QWidget(content);
|
||||
QGridLayout *gitLayout = new QGridLayout(m_gitBar);
|
||||
gitLayout->setContentsMargins(0, 2, 0, 0);
|
||||
gitLayout->setSpacing(4);
|
||||
|
||||
m_gitStatusLabel = new QLabel(tr("Git 仓库"), m_gitBar);
|
||||
m_gitStatusLabel->setForegroundRole(QPalette::PlaceholderText);
|
||||
gitLayout->addWidget(m_gitStatusLabel, 0, 0, 1, 3);
|
||||
|
||||
auto makeGitButton = [this](const QString &text, const QString &tip) {
|
||||
QPushButton *button = new QPushButton(text, m_gitBar);
|
||||
button->setToolTip(tip);
|
||||
button->setCursor(Qt::PointingHandCursor);
|
||||
button->setStyleSheet(QStringLiteral("padding: 3px 6px; min-width: 0;"));
|
||||
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_gitCommitButton = makeGitButton(tr("提交"), tr("把暂存区的内容提交"));
|
||||
|
||||
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);
|
||||
|
||||
layout->addWidget(m_gitBar);
|
||||
m_gitBar->setVisible(false);
|
||||
|
||||
connect(m_gitPullButton, &QPushButton::clicked, this, &MainWindow::gitPull);
|
||||
connect(m_gitFetchButton, &QPushButton::clicked, this, &MainWindow::gitFetch);
|
||||
connect(m_gitPushButton, &QPushButton::clicked, this, &MainWindow::gitPush);
|
||||
connect(m_gitStageButton, &QPushButton::clicked, this, &MainWindow::gitStageAll);
|
||||
connect(m_gitCommitButton, &QPushButton::clicked, this, &MainWindow::gitCommit);
|
||||
connect(m_fileList, &QListWidget::customContextMenuRequested,
|
||||
this, &MainWindow::showFileContextMenu);
|
||||
|
||||
m_sidebar->setWidget(content);
|
||||
addDockWidget(Qt::LeftDockWidgetArea, m_sidebar);
|
||||
resizeDocks({m_sidebar}, {250}, Qt::Horizontal);
|
||||
@@ -470,6 +521,8 @@ void MainWindow::loadSettings()
|
||||
|
||||
const bool sourceMode = settings.value(QStringLiteral("editor/sourceMode"), false).toBool();
|
||||
setSourceModeEnabled(sourceMode);
|
||||
|
||||
updateGitState();
|
||||
}
|
||||
|
||||
void MainWindow::saveSettings()
|
||||
@@ -921,6 +974,7 @@ void MainWindow::openFolder(const QString &path)
|
||||
m_lastDirectory = m_folderPath;
|
||||
QSettings().setValue(QStringLiteral("files/folder"), m_folderPath);
|
||||
refreshFolder();
|
||||
updateGitState();
|
||||
|
||||
m_sidebar->setVisible(true);
|
||||
m_sidebarAction->setChecked(true);
|
||||
@@ -1062,3 +1116,241 @@ void MainWindow::setSourceModeEnabled(bool enabled)
|
||||
|
||||
QSettings().setValue(QStringLiteral("editor/sourceMode"), enabled);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------- Git
|
||||
|
||||
void MainWindow::updateGitState()
|
||||
{
|
||||
m_gitRoot.clear();
|
||||
m_gitBranch.clear();
|
||||
|
||||
if (!m_folderPath.isEmpty() && QFileInfo(m_folderPath).isDir()) {
|
||||
QProcess process;
|
||||
process.setWorkingDirectory(m_folderPath);
|
||||
process.start(QStringLiteral("git"),
|
||||
{QStringLiteral("rev-parse"), QStringLiteral("--show-toplevel")});
|
||||
if (process.waitForFinished(3000) && process.exitCode() == 0)
|
||||
m_gitRoot = QString::fromLocal8Bit(process.readAllStandardOutput()).trimmed();
|
||||
}
|
||||
|
||||
if (!m_gitRoot.isEmpty()) {
|
||||
QProcess branch;
|
||||
branch.setWorkingDirectory(m_gitRoot);
|
||||
branch.start(QStringLiteral("git"), {QStringLiteral("rev-parse"),
|
||||
QStringLiteral("--abbrev-ref"),
|
||||
QStringLiteral("HEAD")});
|
||||
if (branch.waitForFinished(3000) && branch.exitCode() == 0)
|
||||
m_gitBranch = QString::fromLocal8Bit(branch.readAllStandardOutput()).trimmed();
|
||||
}
|
||||
|
||||
if (m_git)
|
||||
m_git->setWorkingDirectory(m_gitRoot.isEmpty() ? m_folderPath : m_gitRoot);
|
||||
|
||||
if (m_gitBar) {
|
||||
m_gitBar->setVisible(!m_gitRoot.isEmpty());
|
||||
m_gitStatusLabel->setText(m_gitBranch.isEmpty() ? tr("Git 仓库") : m_gitBranch);
|
||||
m_gitStatusLabel->setToolTip(m_gitRoot);
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::setGitBusy(bool busy)
|
||||
{
|
||||
m_gitBusy = busy;
|
||||
const QList<QPushButton *> buttons = {m_gitPullButton, m_gitFetchButton, m_gitPushButton,
|
||||
m_gitStageButton, m_gitCommitButton};
|
||||
for (QPushButton *button : buttons) {
|
||||
if (button)
|
||||
button->setEnabled(!busy);
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::enqueueGit(const QStringList &arguments, const QString &label)
|
||||
{
|
||||
GitStep step;
|
||||
step.arguments = arguments;
|
||||
step.label = label;
|
||||
m_gitQueue.enqueue(step);
|
||||
if (!m_gitBusy)
|
||||
runNextGit();
|
||||
}
|
||||
|
||||
void MainWindow::runNextGit()
|
||||
{
|
||||
if (m_gitQueue.isEmpty()) {
|
||||
setGitBusy(false);
|
||||
statusBar()->clearMessage();
|
||||
return;
|
||||
}
|
||||
|
||||
const GitStep step = m_gitQueue.dequeue();
|
||||
setGitBusy(true);
|
||||
statusBar()->showMessage(tr("正在%1…").arg(step.label));
|
||||
m_git->run(step.arguments, step.label);
|
||||
}
|
||||
|
||||
void MainWindow::onGitFinished(bool ok, const QString &label, const QString &output)
|
||||
{
|
||||
if (!ok) {
|
||||
m_gitQueue.clear();
|
||||
setGitBusy(false);
|
||||
statusBar()->clearMessage();
|
||||
QMessageBox::warning(this, tr("Git 操作失败"),
|
||||
tr("%1失败:\n\n%2")
|
||||
.arg(label, output.isEmpty() ? tr("(没有输出)") : output));
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_gitQueue.isEmpty()) {
|
||||
setGitBusy(false);
|
||||
statusBar()->showMessage(tr("%1完成").arg(label), 3000);
|
||||
refreshFolder();
|
||||
} else {
|
||||
runNextGit();
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::gitPull()
|
||||
{
|
||||
if (m_gitRoot.isEmpty())
|
||||
return;
|
||||
enqueueGit({QStringLiteral("pull"), QStringLiteral("--ff-only")}, tr("拉取"));
|
||||
}
|
||||
|
||||
void MainWindow::gitFetch()
|
||||
{
|
||||
if (m_gitRoot.isEmpty())
|
||||
return;
|
||||
enqueueGit({QStringLiteral("fetch"), QStringLiteral("--all"), QStringLiteral("--prune")},
|
||||
tr("获取"));
|
||||
}
|
||||
|
||||
void MainWindow::gitPush()
|
||||
{
|
||||
if (m_gitRoot.isEmpty())
|
||||
return;
|
||||
enqueueGit({QStringLiteral("push")}, tr("推送"));
|
||||
}
|
||||
|
||||
void MainWindow::gitStageAll()
|
||||
{
|
||||
if (m_gitRoot.isEmpty())
|
||||
return;
|
||||
enqueueGit({QStringLiteral("add"), QStringLiteral("-A")}, tr("暂存"));
|
||||
}
|
||||
|
||||
void MainWindow::gitCommit()
|
||||
{
|
||||
if (m_gitRoot.isEmpty())
|
||||
return;
|
||||
|
||||
QProcess staged;
|
||||
staged.setWorkingDirectory(m_gitRoot);
|
||||
staged.start(QStringLiteral("git"), {QStringLiteral("diff"), QStringLiteral("--cached"),
|
||||
QStringLiteral("--quiet")});
|
||||
if (staged.waitForFinished(5000) && staged.exitCode() == 0) {
|
||||
QMessageBox::information(this, tr("提交"),
|
||||
tr("暂存区是空的,先点「暂存」把所有改动加进去。"));
|
||||
return;
|
||||
}
|
||||
|
||||
bool ok = false;
|
||||
const QString message = QInputDialog::getMultiLineText(
|
||||
this, tr("提交"), tr("提交说明:"), QString(), &ok);
|
||||
if (!ok || message.trimmed().isEmpty())
|
||||
return;
|
||||
|
||||
enqueueGit({QStringLiteral("commit"), QStringLiteral("-m"), message.trimmed()}, tr("提交"));
|
||||
}
|
||||
|
||||
void MainWindow::gitAddFile(const QString &path)
|
||||
{
|
||||
if (m_gitRoot.isEmpty())
|
||||
return;
|
||||
const QString relative = QDir(m_gitRoot).relativeFilePath(path);
|
||||
enqueueGit({QStringLiteral("add"), QStringLiteral("--"), relative}, tr("添加到提交"));
|
||||
}
|
||||
|
||||
void MainWindow::gitIgnoreFile(const QString &path)
|
||||
{
|
||||
if (m_gitRoot.isEmpty())
|
||||
return;
|
||||
|
||||
const QString relative = QDir(m_gitRoot).relativeFilePath(path);
|
||||
|
||||
QMessageBox box(QMessageBox::Warning, tr("忽略文件"),
|
||||
tr("忽略「%1」?\n\n"
|
||||
"会依次执行:\n"
|
||||
"1. 把路径写进 .gitignore\n"
|
||||
"2. git rm --cached(从仓库移除,本地文件保留)\n"
|
||||
"3. 提交并推送到远端——远端也会删掉这个文件\n\n"
|
||||
"其他人 pull 之后,本地的那份也会被删掉。")
|
||||
.arg(relative),
|
||||
QMessageBox::NoButton, this);
|
||||
QPushButton *confirm = box.addButton(tr("忽略并删除远端"), QMessageBox::AcceptRole);
|
||||
box.addButton(tr("取消"), QMessageBox::RejectRole);
|
||||
box.exec();
|
||||
if (box.clickedButton() != confirm)
|
||||
return;
|
||||
|
||||
const QString ignorePath = QDir(m_gitRoot).filePath(QStringLiteral(".gitignore"));
|
||||
QStringList lines;
|
||||
QFile ignoreFile(ignorePath);
|
||||
if (ignoreFile.open(QIODevice::ReadOnly | QIODevice::Text))
|
||||
lines = QString::fromUtf8(ignoreFile.readAll()).split(QLatin1Char('\n'));
|
||||
ignoreFile.close();
|
||||
|
||||
bool listed = false;
|
||||
for (const QString &line : lines) {
|
||||
if (line.trimmed() == relative) {
|
||||
listed = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!listed) {
|
||||
if (ignoreFile.open(QIODevice::Append | QIODevice::Text)) {
|
||||
QTextStream stream(&ignoreFile);
|
||||
stream << relative << "\n";
|
||||
ignoreFile.close();
|
||||
}
|
||||
}
|
||||
|
||||
bool tracked = false;
|
||||
QProcess check;
|
||||
check.setWorkingDirectory(m_gitRoot);
|
||||
check.start(QStringLiteral("git"), {QStringLiteral("ls-files"), QStringLiteral("--error-unmatch"),
|
||||
QStringLiteral("--"), relative});
|
||||
if (check.waitForFinished(5000))
|
||||
tracked = (check.exitCode() == 0);
|
||||
|
||||
if (tracked)
|
||||
enqueueGit({QStringLiteral("rm"), QStringLiteral("--cached"), QStringLiteral("--"), relative},
|
||||
tr("从仓库移除"));
|
||||
enqueueGit({QStringLiteral("add"), QStringLiteral("--"), QStringLiteral(".gitignore")},
|
||||
tr("更新忽略列表"));
|
||||
enqueueGit({QStringLiteral("commit"), QStringLiteral("-m"),
|
||||
tr("chore: 忽略 %1").arg(relative)},
|
||||
tr("提交"));
|
||||
enqueueGit({QStringLiteral("push")}, tr("推送"));
|
||||
}
|
||||
|
||||
void MainWindow::showFileContextMenu(const QPoint &pos)
|
||||
{
|
||||
QListWidgetItem *item = m_fileList->itemAt(pos);
|
||||
if (!item)
|
||||
return;
|
||||
const QString path = item->data(Qt::UserRole).toString();
|
||||
if (path.isEmpty())
|
||||
return;
|
||||
|
||||
QMenu menu(this);
|
||||
menu.addAction(tr("打开"), this, [this, path] { openPath(path); });
|
||||
|
||||
if (!m_gitRoot.isEmpty()) {
|
||||
menu.addSeparator();
|
||||
menu.addAction(tr("添加到提交"), this, [this, path] { gitAddFile(path); });
|
||||
menu.addAction(tr("忽略(并从远端删除)"), this, [this, path] { gitIgnoreFile(path); });
|
||||
}
|
||||
|
||||
menu.exec(m_fileList->viewport()->mapToGlobal(pos));
|
||||
}
|
||||
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
#pragma once
|
||||
|
||||
#include <QMainWindow>
|
||||
#include <QQueue>
|
||||
#include <QStringList>
|
||||
|
||||
class QAction;
|
||||
class QActionGroup;
|
||||
class QDockWidget;
|
||||
class QLabel;
|
||||
class QPushButton;
|
||||
class GitRunner;
|
||||
class QListWidget;
|
||||
class QListWidgetItem;
|
||||
class QMenu;
|
||||
@@ -58,6 +61,21 @@ private:
|
||||
void setSourceModeEnabled(bool enabled);
|
||||
void exportPdf();
|
||||
|
||||
// ---- Git ----
|
||||
void updateGitState();
|
||||
void showFileContextMenu(const QPoint &pos);
|
||||
void gitAddFile(const QString &path);
|
||||
void gitIgnoreFile(const QString &path);
|
||||
void gitCommit();
|
||||
void gitPull();
|
||||
void gitFetch();
|
||||
void gitPush();
|
||||
void gitStageAll();
|
||||
void enqueueGit(const QStringList &arguments, const QString &label);
|
||||
void runNextGit();
|
||||
void onGitFinished(bool ok, const QString &label, const QString &output);
|
||||
void setGitBusy(bool busy);
|
||||
|
||||
void changeZoom(int direction);
|
||||
void resetZoom();
|
||||
void setWordWrapEnabled(bool enabled);
|
||||
@@ -81,6 +99,24 @@ private:
|
||||
QLabel *m_folderLabel = nullptr;
|
||||
QToolButton *m_sourceButton = nullptr;
|
||||
QToolButton *m_sidebarButton = nullptr;
|
||||
|
||||
GitRunner *m_git = nullptr;
|
||||
QWidget *m_gitBar = nullptr;
|
||||
QLabel *m_gitStatusLabel = nullptr;
|
||||
QPushButton *m_gitPullButton = nullptr;
|
||||
QPushButton *m_gitFetchButton = nullptr;
|
||||
QPushButton *m_gitPushButton = nullptr;
|
||||
QPushButton *m_gitStageButton = nullptr;
|
||||
QPushButton *m_gitCommitButton = nullptr;
|
||||
QString m_gitRoot;
|
||||
QString m_gitBranch;
|
||||
|
||||
struct GitStep {
|
||||
QStringList arguments;
|
||||
QString label;
|
||||
};
|
||||
QQueue<GitStep> m_gitQueue;
|
||||
bool m_gitBusy = false;
|
||||
QTimer *m_folderRefreshTimer = nullptr;
|
||||
QString m_folderPath;
|
||||
QString m_displayedFolder;
|
||||
|
||||
@@ -594,7 +594,7 @@ QRectF MarkdownEditor::languageRect(int index) const
|
||||
const QString label = languageLabel(index) + QStringLiteral(" \u25be");
|
||||
const qreal width = metrics.horizontalAdvance(label) + 16;
|
||||
const qreal height = metrics.height() + 6;
|
||||
return QRectF(rect.left() + 8, rect.top() + 6, width, height);
|
||||
return QRectF(rect.right() - width - 8, rect.bottom() - height - 6, width, height);
|
||||
}
|
||||
|
||||
QString MarkdownEditor::languageLabel(int index) const
|
||||
|
||||
Binary file not shown.
+285
-106
@@ -1,373 +1,552 @@
|
||||
<?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" />
|
||||
<source>
|
||||
(超时,已中止)</source>
|
||||
<translation>
|
||||
(timed out, aborted)</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>MainWindow</name>
|
||||
<message>
|
||||
<location filename="../src/MainWindow.cpp" line="170" />
|
||||
<location filename="../src/MainWindow.cpp" line="784" />
|
||||
<location filename="../src/MainWindow.cpp" line="179" />
|
||||
<location filename="../src/MainWindow.cpp" line="837" />
|
||||
<source>新建</source>
|
||||
<translation>New</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/MainWindow.cpp" line="174" />
|
||||
<location filename="../src/MainWindow.cpp" line="785" />
|
||||
<location filename="../src/MainWindow.cpp" line="183" />
|
||||
<location filename="../src/MainWindow.cpp" line="838" />
|
||||
<source>打开…</source>
|
||||
<translation>Open…</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/MainWindow.cpp" line="178" />
|
||||
<location filename="../src/MainWindow.cpp" line="787" />
|
||||
<location filename="../src/MainWindow.cpp" line="187" />
|
||||
<location filename="../src/MainWindow.cpp" line="840" />
|
||||
<source>保存</source>
|
||||
<translation>Save</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/MainWindow.cpp" line="182" />
|
||||
<location filename="../src/MainWindow.cpp" line="788" />
|
||||
<location filename="../src/MainWindow.cpp" line="191" />
|
||||
<location filename="../src/MainWindow.cpp" line="841" />
|
||||
<source>另存为…</source>
|
||||
<translation>Save As…</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/MainWindow.cpp" line="186" />
|
||||
<location filename="../src/MainWindow.cpp" line="789" />
|
||||
<location filename="../src/MainWindow.cpp" line="195" />
|
||||
<location filename="../src/MainWindow.cpp" line="842" />
|
||||
<source>导出 PDF…</source>
|
||||
<translation>Export PDF…</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/MainWindow.cpp" line="190" />
|
||||
<location filename="../src/MainWindow.cpp" line="790" />
|
||||
<location filename="../src/MainWindow.cpp" line="199" />
|
||||
<location filename="../src/MainWindow.cpp" line="843" />
|
||||
<source>退出</source>
|
||||
<translation>Quit</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/MainWindow.cpp" line="194" />
|
||||
<location filename="../src/MainWindow.cpp" line="792" />
|
||||
<location filename="../src/MainWindow.cpp" line="203" />
|
||||
<location filename="../src/MainWindow.cpp" line="845" />
|
||||
<source>撤销</source>
|
||||
<translation>Undo</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/MainWindow.cpp" line="198" />
|
||||
<location filename="../src/MainWindow.cpp" line="793" />
|
||||
<location filename="../src/MainWindow.cpp" line="207" />
|
||||
<location filename="../src/MainWindow.cpp" line="846" />
|
||||
<source>重做</source>
|
||||
<translation>Redo</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/MainWindow.cpp" line="202" />
|
||||
<location filename="../src/MainWindow.cpp" line="794" />
|
||||
<location filename="../src/MainWindow.cpp" line="211" />
|
||||
<location filename="../src/MainWindow.cpp" line="847" />
|
||||
<source>剪切</source>
|
||||
<translation>Cut</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/MainWindow.cpp" line="206" />
|
||||
<location filename="../src/MainWindow.cpp" line="795" />
|
||||
<location filename="../src/MainWindow.cpp" line="215" />
|
||||
<location filename="../src/MainWindow.cpp" line="848" />
|
||||
<source>复制</source>
|
||||
<translation>Copy</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/MainWindow.cpp" line="210" />
|
||||
<location filename="../src/MainWindow.cpp" line="796" />
|
||||
<location filename="../src/MainWindow.cpp" line="219" />
|
||||
<location filename="../src/MainWindow.cpp" line="849" />
|
||||
<source>粘贴</source>
|
||||
<translation>Paste</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/MainWindow.cpp" line="214" />
|
||||
<location filename="../src/MainWindow.cpp" line="797" />
|
||||
<location filename="../src/MainWindow.cpp" line="223" />
|
||||
<location filename="../src/MainWindow.cpp" line="850" />
|
||||
<source>全选</source>
|
||||
<translation>Select All</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/MainWindow.cpp" line="218" />
|
||||
<location filename="../src/MainWindow.cpp" line="801" />
|
||||
<location filename="../src/MainWindow.cpp" line="227" />
|
||||
<location filename="../src/MainWindow.cpp" line="854" />
|
||||
<source>自动换行</source>
|
||||
<translation>Word Wrap</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/MainWindow.cpp" line="223" />
|
||||
<location filename="../src/MainWindow.cpp" line="802" />
|
||||
<location filename="../src/MainWindow.cpp" line="232" />
|
||||
<location filename="../src/MainWindow.cpp" line="855" />
|
||||
<source>放大</source>
|
||||
<translation>Zoom In</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/MainWindow.cpp" line="227" />
|
||||
<location filename="../src/MainWindow.cpp" line="803" />
|
||||
<location filename="../src/MainWindow.cpp" line="236" />
|
||||
<location filename="../src/MainWindow.cpp" line="856" />
|
||||
<source>缩小</source>
|
||||
<translation>Zoom Out</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/MainWindow.cpp" line="231" />
|
||||
<location filename="../src/MainWindow.cpp" line="804" />
|
||||
<location filename="../src/MainWindow.cpp" line="240" />
|
||||
<location filename="../src/MainWindow.cpp" line="857" />
|
||||
<source>实际大小</source>
|
||||
<translation>Actual Size</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/MainWindow.cpp" line="240" />
|
||||
<location filename="../src/MainWindow.cpp" line="786" />
|
||||
<location filename="../src/MainWindow.cpp" line="249" />
|
||||
<location filename="../src/MainWindow.cpp" line="839" />
|
||||
<source>打开文件夹…</source>
|
||||
<translation>Open Folder…</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/MainWindow.cpp" line="244" />
|
||||
<location filename="../src/MainWindow.cpp" line="410" />
|
||||
<location filename="../src/MainWindow.cpp" line="799" />
|
||||
<location filename="../src/MainWindow.cpp" line="820" />
|
||||
<location filename="../src/MainWindow.cpp" line="253" />
|
||||
<location filename="../src/MainWindow.cpp" line="461" />
|
||||
<location filename="../src/MainWindow.cpp" line="852" />
|
||||
<location filename="../src/MainWindow.cpp" line="873" />
|
||||
<source>侧栏</source>
|
||||
<translation>Sidebar</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/MainWindow.cpp" line="258" />
|
||||
<location filename="../src/MainWindow.cpp" line="800" />
|
||||
<location filename="../src/MainWindow.cpp" line="267" />
|
||||
<location filename="../src/MainWindow.cpp" line="853" />
|
||||
<source>源代码模式</source>
|
||||
<translation>Source Mode</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/MainWindow.cpp" line="263" />
|
||||
<location filename="../src/MainWindow.cpp" line="816" />
|
||||
<location filename="../src/MainWindow.cpp" line="272" />
|
||||
<location filename="../src/MainWindow.cpp" line="869" />
|
||||
<source>代码块</source>
|
||||
<translation>Code Block</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/MainWindow.cpp" line="270" />
|
||||
<location filename="../src/MainWindow.cpp" line="814" />
|
||||
<location filename="../src/MainWindow.cpp" line="279" />
|
||||
<location filename="../src/MainWindow.cpp" line="867" />
|
||||
<source>标题 %1</source>
|
||||
<translation>Heading %1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/MainWindow.cpp" line="281" />
|
||||
<location filename="../src/MainWindow.cpp" line="290" />
|
||||
<source>文件夹</source>
|
||||
<translation>Folder</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/MainWindow.cpp" line="292" />
|
||||
<location filename="../src/MainWindow.cpp" line="964" />
|
||||
<location filename="../src/MainWindow.cpp" line="301" />
|
||||
<location filename="../src/MainWindow.cpp" line="1018" />
|
||||
<source>未打开文件夹</source>
|
||||
<translation>No folder open</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/MainWindow.cpp" line="318" />
|
||||
<location filename="../src/MainWindow.cpp" line="774" />
|
||||
<location filename="../src/MainWindow.cpp" line="319" />
|
||||
<location filename="../src/MainWindow.cpp" line="1151" />
|
||||
<source>Git 仓库</source>
|
||||
<translation>Git repository</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/MainWindow.cpp" line="331" />
|
||||
<location filename="../src/MainWindow.cpp" line="1216" />
|
||||
<source>拉取</source>
|
||||
<translation>Pull</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/MainWindow.cpp" line="331" />
|
||||
<source>git pull --ff-only</source>
|
||||
<translation>git pull --ff-only</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/MainWindow.cpp" line="332" />
|
||||
<location filename="../src/MainWindow.cpp" line="1224" />
|
||||
<source>获取</source>
|
||||
<translation>Fetch</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/MainWindow.cpp" line="332" />
|
||||
<source>git fetch --all --prune</source>
|
||||
<translation>git fetch --all --prune</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/MainWindow.cpp" line="333" />
|
||||
<location filename="../src/MainWindow.cpp" line="1231" />
|
||||
<location filename="../src/MainWindow.cpp" line="1333" />
|
||||
<source>推送</source>
|
||||
<translation>Push</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/MainWindow.cpp" line="333" />
|
||||
<source>git push</source>
|
||||
<translation>git push</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/MainWindow.cpp" line="334" />
|
||||
<location filename="../src/MainWindow.cpp" line="1238" />
|
||||
<source>暂存</source>
|
||||
<translation>Stage</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/MainWindow.cpp" line="334" />
|
||||
<source>git add -A</source>
|
||||
<translation>git add -A</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/MainWindow.cpp" line="335" />
|
||||
<location filename="../src/MainWindow.cpp" line="1251" />
|
||||
<location filename="../src/MainWindow.cpp" line="1258" />
|
||||
<location filename="../src/MainWindow.cpp" line="1262" />
|
||||
<location filename="../src/MainWindow.cpp" line="1332" />
|
||||
<source>提交</source>
|
||||
<translation>Commit</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/MainWindow.cpp" line="335" />
|
||||
<source>把暂存区的内容提交</source>
|
||||
<translation>Commit the staged changes</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/MainWindow.cpp" line="369" />
|
||||
<location filename="../src/MainWindow.cpp" line="827" />
|
||||
<source>文件</source>
|
||||
<translation>File</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/MainWindow.cpp" line="322" />
|
||||
<location filename="../src/MainWindow.cpp" line="779" />
|
||||
<location filename="../src/MainWindow.cpp" line="373" />
|
||||
<location filename="../src/MainWindow.cpp" line="832" />
|
||||
<source>最近打开</source>
|
||||
<translation>Recent Files</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/MainWindow.cpp" line="330" />
|
||||
<location filename="../src/MainWindow.cpp" line="775" />
|
||||
<location filename="../src/MainWindow.cpp" line="381" />
|
||||
<location filename="../src/MainWindow.cpp" line="828" />
|
||||
<source>编辑</source>
|
||||
<translation>Edit</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/MainWindow.cpp" line="340" />
|
||||
<location filename="../src/MainWindow.cpp" line="776" />
|
||||
<location filename="../src/MainWindow.cpp" line="391" />
|
||||
<location filename="../src/MainWindow.cpp" line="829" />
|
||||
<source>视图</source>
|
||||
<translation>View</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/MainWindow.cpp" line="351" />
|
||||
<location filename="../src/MainWindow.cpp" line="780" />
|
||||
<location filename="../src/MainWindow.cpp" line="402" />
|
||||
<location filename="../src/MainWindow.cpp" line="833" />
|
||||
<source>主题</source>
|
||||
<translation>Theme</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/MainWindow.cpp" line="359" />
|
||||
<location filename="../src/MainWindow.cpp" line="810" />
|
||||
<location filename="../src/MainWindow.cpp" line="410" />
|
||||
<location filename="../src/MainWindow.cpp" line="863" />
|
||||
<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="377" />
|
||||
<location filename="../src/MainWindow.cpp" line="782" />
|
||||
<location filename="../src/MainWindow.cpp" line="428" />
|
||||
<location filename="../src/MainWindow.cpp" line="835" />
|
||||
<source>语言</source>
|
||||
<translation>Language</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/MainWindow.cpp" line="394" />
|
||||
<location filename="../src/MainWindow.cpp" line="777" />
|
||||
<location filename="../src/MainWindow.cpp" line="445" />
|
||||
<location filename="../src/MainWindow.cpp" line="830" />
|
||||
<source>格式</source>
|
||||
<translation>Format</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/MainWindow.cpp" line="395" />
|
||||
<location filename="../src/MainWindow.cpp" line="781" />
|
||||
<location filename="../src/MainWindow.cpp" line="446" />
|
||||
<location filename="../src/MainWindow.cpp" line="834" />
|
||||
<source>标题</source>
|
||||
<translation>Heading</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/MainWindow.cpp" line="402" />
|
||||
<location filename="../src/MainWindow.cpp" line="778" />
|
||||
<location filename="../src/MainWindow.cpp" line="453" />
|
||||
<location filename="../src/MainWindow.cpp" line="831" />
|
||||
<source>帮助</source>
|
||||
<translation>Help</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/MainWindow.cpp" line="403" />
|
||||
<location filename="../src/MainWindow.cpp" line="817" />
|
||||
<location filename="../src/MainWindow.cpp" line="847" />
|
||||
<location filename="../src/MainWindow.cpp" line="454" />
|
||||
<location filename="../src/MainWindow.cpp" line="870" />
|
||||
<location filename="../src/MainWindow.cpp" line="900" />
|
||||
<source>关于 VoiletMark</source>
|
||||
<translation>About VoiletMark</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/MainWindow.cpp" line="414" />
|
||||
<location filename="../src/MainWindow.cpp" line="821" />
|
||||
<location filename="../src/MainWindow.cpp" line="465" />
|
||||
<location filename="../src/MainWindow.cpp" line="874" />
|
||||
<source>显示 / 隐藏文件夹侧栏(Ctrl+B)</source>
|
||||
<translation>Show / hide the folder sidebar (Ctrl+B)</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/MainWindow.cpp" line="422" />
|
||||
<location filename="../src/MainWindow.cpp" line="824" />
|
||||
<location filename="../src/MainWindow.cpp" line="473" />
|
||||
<location filename="../src/MainWindow.cpp" line="877" />
|
||||
<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="500" />
|
||||
<location filename="../src/MainWindow.cpp" line="615" />
|
||||
<location filename="../src/MainWindow.cpp" line="553" />
|
||||
<location filename="../src/MainWindow.cpp" line="668" />
|
||||
<source>未命名</source>
|
||||
<translation>Untitled</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/MainWindow.cpp" line="549" />
|
||||
<location filename="../src/MainWindow.cpp" line="602" />
|
||||
<source>打开 Markdown 文件</source>
|
||||
<translation>Open Markdown File</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/MainWindow.cpp" line="550" />
|
||||
<location filename="../src/MainWindow.cpp" line="603" />
|
||||
<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="567" />
|
||||
<location filename="../src/MainWindow.cpp" line="620" />
|
||||
<source>无法打开文件</source>
|
||||
<translation>Cannot Open File</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/MainWindow.cpp" line="568" />
|
||||
<location filename="../src/MainWindow.cpp" line="621" />
|
||||
<source>读取「%1」失败:%2</source>
|
||||
<translation>Could not read "%1": %2</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/MainWindow.cpp" line="602" />
|
||||
<location filename="../src/MainWindow.cpp" line="655" />
|
||||
<source>另存为</source>
|
||||
<translation>Save As</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/MainWindow.cpp" line="603" />
|
||||
<location filename="../src/MainWindow.cpp" line="656" />
|
||||
<source>Markdown 文件 (*.md);;文本文件 (*.txt);;所有文件 (*)</source>
|
||||
<translation>Markdown files (*.md);;Text files (*.txt);;All files (*)</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/MainWindow.cpp" line="620" />
|
||||
<location filename="../src/MainWindow.cpp" line="673" />
|
||||
<source>导出 PDF</source>
|
||||
<translation>Export PDF</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/MainWindow.cpp" line="621" />
|
||||
<location filename="../src/MainWindow.cpp" line="674" />
|
||||
<source>PDF 文件 (*.pdf)</source>
|
||||
<translation>PDF files (*.pdf)</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/MainWindow.cpp" line="640" />
|
||||
<location filename="../src/MainWindow.cpp" line="693" />
|
||||
<source>导出失败</source>
|
||||
<translation>Export Failed</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/MainWindow.cpp" line="641" />
|
||||
<location filename="../src/MainWindow.cpp" line="694" />
|
||||
<source>没能写出「%1」,换个位置再试一次。</source>
|
||||
<translation>Could not write "%1". Try another location.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/MainWindow.cpp" line="645" />
|
||||
<location filename="../src/MainWindow.cpp" line="698" />
|
||||
<source>已导出 %1</source>
|
||||
<translation>Exported to %1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/MainWindow.cpp" line="660" />
|
||||
<location filename="../src/MainWindow.cpp" line="667" />
|
||||
<location filename="../src/MainWindow.cpp" line="672" />
|
||||
<location filename="../src/MainWindow.cpp" line="713" />
|
||||
<location filename="../src/MainWindow.cpp" line="720" />
|
||||
<location filename="../src/MainWindow.cpp" line="725" />
|
||||
<source>无法保存文件</source>
|
||||
<translation>Cannot Save File</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/MainWindow.cpp" line="661" />
|
||||
<location filename="../src/MainWindow.cpp" line="714" />
|
||||
<source>写入「%1」失败:%2</source>
|
||||
<translation>Could not write "%1": %2</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/MainWindow.cpp" line="668" />
|
||||
<location filename="../src/MainWindow.cpp" line="721" />
|
||||
<source>写入「%1」时发生错误。</source>
|
||||
<translation>An error occurred while writing "%1".</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/MainWindow.cpp" line="673" />
|
||||
<location filename="../src/MainWindow.cpp" line="726" />
|
||||
<source>提交「%1」失败:%2</source>
|
||||
<translation>Could not commit "%1": %2</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/MainWindow.cpp" line="681" />
|
||||
<location filename="../src/MainWindow.cpp" line="734" />
|
||||
<source>已保存 %1</source>
|
||||
<translation>Saved to %1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/MainWindow.cpp" line="691" />
|
||||
<location filename="../src/MainWindow.cpp" line="744" />
|
||||
<source>VoiletMark</source>
|
||||
<translation>VoiletMark</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/MainWindow.cpp" line="692" />
|
||||
<location filename="../src/MainWindow.cpp" line="745" />
|
||||
<source>「%1」有未保存的修改,是否保存?</source>
|
||||
<translation>"%1" has unsaved changes. Save them?</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/MainWindow.cpp" line="716" />
|
||||
<location filename="../src/MainWindow.cpp" line="769" />
|
||||
<source>%1[*] — VoiletMark</source>
|
||||
<translation>%1[*] — VoiletMark</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/MainWindow.cpp" line="735" />
|
||||
<location filename="../src/MainWindow.cpp" line="788" />
|
||||
<source>行 %1,列 %2</source>
|
||||
<translation>Line %1, Col %2</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/MainWindow.cpp" line="737" />
|
||||
<location filename="../src/MainWindow.cpp" line="790" />
|
||||
<source> 已选 %1 字</source>
|
||||
<translation> %1 selected</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/MainWindow.cpp" line="738" />
|
||||
<location filename="../src/MainWindow.cpp" line="791" />
|
||||
<source> %1 字</source>
|
||||
<translation> %1 chars</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/MainWindow.cpp" line="851" />
|
||||
<location filename="../src/MainWindow.cpp" line="904" />
|
||||
<source><h3>VoiletMark %1</h3><p>一个轻量的跨平台 Markdown 编辑器。</p><p>基于 Qt %2 与 C++17 构建。</p></source>
|
||||
<translation><h3>VoiletMark %1</h3><p>A lightweight cross-platform Markdown editor.</p><p>Built with Qt %2 and C++17.</p></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/MainWindow.cpp" line="886" />
|
||||
<location filename="../src/MainWindow.cpp" line="939" />
|
||||
<source>(暂无记录)</source>
|
||||
<translation>(none)</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/MainWindow.cpp" line="899" />
|
||||
<location filename="../src/MainWindow.cpp" line="952" />
|
||||
<source>清空列表</source>
|
||||
<translation>Clear List</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/MainWindow.cpp" line="909" />
|
||||
<location filename="../src/MainWindow.cpp" line="962" />
|
||||
<source>打开文件夹</source>
|
||||
<translation>Open Folder</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/MainWindow.cpp" line="965" />
|
||||
<location filename="../src/MainWindow.cpp" line="1019" />
|
||||
<source>文件 → 打开文件夹…</source>
|
||||
<translation>File → Open Folder…</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/MainWindow.cpp" line="1001" />
|
||||
<location filename="../src/MainWindow.cpp" line="1055" />
|
||||
<source>(没有 Markdown 文件)</source>
|
||||
<translation>(no Markdown files)</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/MainWindow.cpp" line="1187" />
|
||||
<source>正在%1…</source>
|
||||
<translation>%1…</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/MainWindow.cpp" line="1197" />
|
||||
<source>Git 操作失败</source>
|
||||
<translation>Git Operation Failed</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/MainWindow.cpp" line="1198" />
|
||||
<source>%1失败:
|
||||
|
||||
%2</source>
|
||||
<translation>%1 failed:
|
||||
|
||||
%2</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/MainWindow.cpp" line="1199" />
|
||||
<source>(没有输出)</source>
|
||||
<translation>(no output)</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/MainWindow.cpp" line="1205" />
|
||||
<source>%1完成</source>
|
||||
<translation>%1 finished</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/MainWindow.cpp" line="1252" />
|
||||
<source>暂存区是空的,先点「暂存」把所有改动加进去。</source>
|
||||
<translation>Nothing is staged yet. Click "Stage" first to add all changes.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/MainWindow.cpp" line="1258" />
|
||||
<source>提交说明:</source>
|
||||
<translation>Commit message:</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/MainWindow.cpp" line="1270" />
|
||||
<location filename="../src/MainWindow.cpp" line="1350" />
|
||||
<source>添加到提交</source>
|
||||
<translation>Add to commit</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/MainWindow.cpp" line="1280" />
|
||||
<source>忽略文件</source>
|
||||
<translation>Ignore File</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/MainWindow.cpp" line="1281" />
|
||||
<source>忽略「%1」?
|
||||
|
||||
会依次执行:
|
||||
1. 把路径写进 .gitignore
|
||||
2. git rm --cached(从仓库移除,本地文件保留)
|
||||
3. 提交并推送到远端——远端也会删掉这个文件
|
||||
|
||||
其他人 pull 之后,本地的那份也会被删掉。</source>
|
||||
<translation>Ignore "%1"?
|
||||
|
||||
This will:
|
||||
1. Add the path to .gitignore
|
||||
2. Run git rm --cached (removes it from the repo, keeps your local file)
|
||||
3. Commit and push - the file is deleted on the remote too
|
||||
|
||||
Anyone who pulls afterwards will lose their local copy.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/MainWindow.cpp" line="1289" />
|
||||
<source>忽略并删除远端</source>
|
||||
<translation>Ignore and delete remote</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/MainWindow.cpp" line="1290" />
|
||||
<source>取消</source>
|
||||
<translation>Cancel</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/MainWindow.cpp" line="1327" />
|
||||
<source>从仓库移除</source>
|
||||
<translation>Remove from repository</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/MainWindow.cpp" line="1329" />
|
||||
<source>更新忽略列表</source>
|
||||
<translation>Update ignore list</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/MainWindow.cpp" line="1331" />
|
||||
<source>chore: 忽略 %1</source>
|
||||
<translation>chore: ignore %1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/MainWindow.cpp" line="1346" />
|
||||
<source>打开</source>
|
||||
<translation>Open</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/MainWindow.cpp" line="1351" />
|
||||
<source>忽略(并从远端删除)</source>
|
||||
<translation>Ignore (and delete from remote)</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>MarkdownEditor</name>
|
||||
|
||||
Reference in New Issue
Block a user