feat: v0.9.1 —— 右键菜单拆成 添加 / 忽略 / 删除远端 三项

- 添加:git add -- <file>,只暂存这个文件
- 忽略:把路径写进 .gitignore,不碰索引也不碰远端
- 删除远端:git rm --cached + 提交 + 推送,确认后执行;本地文件保留
- 原来的「忽略(并从远端删除)」合并项去掉
- 新增 13 条中英文翻译,清理 5 条过期条目
- README 同步,版本 0.9.1
This commit is contained in:
2026-10-22 18:23:52 +08:00
parent 047dcd2b2f
commit e24474abd1
6 changed files with 129 additions and 86 deletions
+6 -6
View File
@@ -2,7 +2,7 @@
一个轻量的跨平台 Markdown 编辑器,基于 **Qt 5 / C++17** 构建。 一个轻量的跨平台 Markdown 编辑器,基于 **Qt 5 / C++17** 构建。
当前版本 **0.9.0**。 当前版本 **0.9.1**。
## 界面 ## 界面
@@ -57,12 +57,12 @@
| 暂存 | `git add -A` | | 暂存 | `git add -A` |
| 提交 | 填说明后 `git commit -m` | | 提交 | 填说明后 `git commit -m` |
右键侧栏里的文件还有两项: 右键侧栏里的文件有三项:
- **添加到提交** → `git add -- <file>` - **添加** → `git add -- <file>`,只暂存这一个文件
- **忽略(并从远端删除)** → 写进 `.gitignore` + `git rm --cached` + 提交 + 推送。 - **忽略** → 把路径写进 `.gitignore`(不改已跟踪的文件,也不碰远端)
**远端会真的删掉这个文件**,所以点之前会弹确认框,把要执行的命令逐条列出来; - **删除远端** → `git rm --cached` + 提交 + 推送。**远端会真的删掉这个文件**,
本地文件保留。 本地文件保留;执行前弹确认框。
所有命令都是异步跑的,不会卡界面;失败时弹窗显示 git 的原始输出。 所有命令都是异步跑的,不会卡界面;失败时弹窗显示 git 的原始输出。
+1 -1
View File
@@ -1,6 +1,6 @@
TEMPLATE = app TEMPLATE = app
TARGET = VoiletMark TARGET = VoiletMark
VERSION = 0.9.0 VERSION = 0.9.1
QT += core gui widgets printsupport QT += core gui widgets printsupport
+46 -35
View File
@@ -1276,59 +1276,65 @@ void MainWindow::gitIgnoreFile(const QString &path)
return; return;
const QString relative = QDir(m_gitRoot).relativeFilePath(path); 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")); const QString ignorePath = QDir(m_gitRoot).filePath(QStringLiteral(".gitignore"));
QStringList lines; QStringList lines;
QFile ignoreFile(ignorePath); QFile ignoreFile(ignorePath);
if (ignoreFile.open(QIODevice::ReadOnly | QIODevice::Text)) if (ignoreFile.open(QIODevice::ReadOnly | QIODevice::Text))
lines = QString::fromUtf8(ignoreFile.readAll()).split(QLatin1Char('\n')); lines = QString::fromUtf8(ignoreFile.readAll()).split(QLatin1Char('\n'));
ignoreFile.close(); ignoreFile.close();
bool listed = false;
for (const QString &line : lines) { for (const QString &line : lines) {
if (line.trimmed() == relative) { if (line.trimmed() == relative) {
listed = true; statusBar()->showMessage(tr("「%1」已经在 .gitignore 里了").arg(relative), 4000);
break; return;
}
}
if (!listed) {
if (ignoreFile.open(QIODevice::Append | QIODevice::Text)) {
QTextStream stream(&ignoreFile);
stream << relative << "\n";
ignoreFile.close();
} }
} }
bool tracked = false; if (!ignoreFile.open(QIODevice::Append | QIODevice::Text)) {
QMessageBox::warning(this, tr("忽略文件"),
tr("打不开 .gitignore:%1").arg(ignoreFile.errorString()));
return;
}
QTextStream stream(&ignoreFile);
stream << relative << "\n";
ignoreFile.close();
statusBar()->showMessage(tr("已把 %1 写进 .gitignore").arg(relative), 4000);
}
void MainWindow::gitRemoveRemote(const QString &path)
{
if (m_gitRoot.isEmpty())
return;
const QString relative = QDir(m_gitRoot).relativeFilePath(path);
QProcess check; QProcess check;
check.setWorkingDirectory(m_gitRoot); check.setWorkingDirectory(m_gitRoot);
check.start(QStringLiteral("git"), {QStringLiteral("ls-files"), QStringLiteral("--error-unmatch"), check.start(QStringLiteral("git"), {QStringLiteral("ls-files"), QStringLiteral("--error-unmatch"),
QStringLiteral("--"), relative}); QStringLiteral("--"), relative});
if (check.waitForFinished(5000)) if (!(check.waitForFinished(5000) && check.exitCode() == 0)) {
tracked = (check.exitCode() == 0); QMessageBox::information(this, tr("删除远端"),
tr("「%1」没有被 git 跟踪,远端本来就没有它。").arg(relative));
return;
}
QMessageBox box(QMessageBox::Warning, tr("删除远端"),
tr("从仓库删除「%1」并推送到远端?\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;
if (tracked)
enqueueGit({QStringLiteral("rm"), QStringLiteral("--cached"), QStringLiteral("--"), relative}, enqueueGit({QStringLiteral("rm"), QStringLiteral("--cached"), QStringLiteral("--"), relative},
tr("从仓库移除")); tr("从仓库移除"));
enqueueGit({QStringLiteral("add"), QStringLiteral("--"), QStringLiteral(".gitignore")},
tr("更新忽略列表"));
enqueueGit({QStringLiteral("commit"), QStringLiteral("-m"), enqueueGit({QStringLiteral("commit"), QStringLiteral("-m"),
tr("chore: 忽略 %1").arg(relative)}, tr("chore: 从仓库删除 %1").arg(relative)},
tr("提交")); tr("提交"));
enqueueGit({QStringLiteral("push")}, tr("推送")); enqueueGit({QStringLiteral("push")}, tr("推送"));
} }
@@ -1347,8 +1353,13 @@ void MainWindow::showFileContextMenu(const QPoint &pos)
if (!m_gitRoot.isEmpty()) { if (!m_gitRoot.isEmpty()) {
menu.addSeparator(); menu.addSeparator();
menu.addAction(tr("添加到提交"), this, [this, path] { gitAddFile(path); }); QAction *addAction = menu.addAction(tr("添加"), this, [this, path] { gitAddFile(path); });
menu.addAction(tr("忽略(并从远端删除)"), this, [this, path] { gitIgnoreFile(path); }); addAction->setToolTip(tr("git add 这个文件"));
QAction *ignoreAction = menu.addAction(tr("忽略"), this, [this, path] { gitIgnoreFile(path); });
ignoreAction->setToolTip(tr("把路径写进 .gitignore(不改仓库里已跟踪的文件)"));
QAction *removeAction =
menu.addAction(tr("删除远端"), this, [this, path] { gitRemoveRemote(path); });
removeAction->setToolTip(tr("git rm --cached 后提交并推送:远端删除,本地保留"));
} }
menu.exec(m_fileList->viewport()->mapToGlobal(pos)); menu.exec(m_fileList->viewport()->mapToGlobal(pos));
+1
View File
@@ -66,6 +66,7 @@ private:
void showFileContextMenu(const QPoint &pos); void showFileContextMenu(const QPoint &pos);
void gitAddFile(const QString &path); void gitAddFile(const QString &path);
void gitIgnoreFile(const QString &path); void gitIgnoreFile(const QString &path);
void gitRemoveRemote(const QString &path);
void gitCommit(); void gitCommit();
void gitPull(); void gitPull();
void gitFetch(); void gitFetch();
Binary file not shown.
+73 -42
View File
@@ -182,7 +182,7 @@
<message> <message>
<location filename="../src/MainWindow.cpp" line="333" /> <location filename="../src/MainWindow.cpp" line="333" />
<location filename="../src/MainWindow.cpp" line="1231" /> <location filename="../src/MainWindow.cpp" line="1231" />
<location filename="../src/MainWindow.cpp" line="1333" /> <location filename="../src/MainWindow.cpp" line="1339" />
<source>推送</source> <source>推送</source>
<translation>Push</translation> <translation>Push</translation>
</message> </message>
@@ -207,7 +207,7 @@
<location filename="../src/MainWindow.cpp" line="1251" /> <location filename="../src/MainWindow.cpp" line="1251" />
<location filename="../src/MainWindow.cpp" line="1258" /> <location filename="../src/MainWindow.cpp" line="1258" />
<location filename="../src/MainWindow.cpp" line="1262" /> <location filename="../src/MainWindow.cpp" line="1262" />
<location filename="../src/MainWindow.cpp" line="1332" /> <location filename="../src/MainWindow.cpp" line="1338" />
<source>提交</source> <source>提交</source>
<translation>Commit</translation> <translation>Commit</translation>
</message> </message>
@@ -484,69 +484,100 @@
</message> </message>
<message> <message>
<location filename="../src/MainWindow.cpp" line="1270" /> <location filename="../src/MainWindow.cpp" line="1270" />
<location filename="../src/MainWindow.cpp" line="1350" />
<source>添加到提交</source> <source>添加到提交</source>
<translation>Add to commit</translation> <translation>Add to commit</translation>
</message> </message>
<message> <message>
<location filename="../src/MainWindow.cpp" line="1280" /> <location filename="../src/MainWindow.cpp" line="1289" />
<source>「%1」已经在 .gitignore 里了</source>
<translation>"%1" is already in .gitignore</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="1295" />
<source>忽略文件</source> <source>忽略文件</source>
<translation>Ignore File</translation> <translation>Ignore File</translation>
</message> </message>
<message> <message>
<location filename="../src/MainWindow.cpp" line="1281" /> <location filename="../src/MainWindow.cpp" line="1296" />
<source>忽略「%1」? <source>打不开 .gitignore:%1</source>
<translation>Cannot open .gitignore: %1</translation>
会依次执行:
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>
<message> <message>
<location filename="../src/MainWindow.cpp" line="1289" /> <location filename="../src/MainWindow.cpp" line="1303" />
<source>忽略并删除远端</source> <source>已把 %1 写进 .gitignore</source>
<translation>Ignore and delete remote</translation> <translation>Added %1 to .gitignore</translation>
</message> </message>
<message> <message>
<location filename="../src/MainWindow.cpp" line="1290" /> <location filename="../src/MainWindow.cpp" line="1318" />
<location filename="../src/MainWindow.cpp" line="1323" />
<location filename="../src/MainWindow.cpp" line="1361" />
<source>删除远端</source>
<translation>Delete from remote</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="1319" />
<source>「%1」没有被 git 跟踪,远端本来就没有它。</source>
<translation>"%1" is not tracked by git, so the remote never had it.</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="1324" />
<source>从仓库删除「%1」并推送到远端?
本地文件会保留,远端和别人 pull 下来的仓库里会删掉它。</source>
<translation>Remove "%1" from the repository and push?
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="1328" />
<source>删除并推送</source>
<translation>Delete and push</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="1337" />
<source>chore: 从仓库删除 %1</source>
<translation>chore: remove %1 from repository</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="1356" />
<source>添加</source>
<translation>Add</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="1357" />
<source>git add 这个文件</source>
<translation>git add this file</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="1358" />
<source>忽略</source>
<translation>Ignore</translation>
</message>
<message>
<location filename="../src/MainWindow.cpp" line="1359" />
<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="1362" />
<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="1329" />
<source>取消</source> <source>取消</source>
<translation>Cancel</translation> <translation>Cancel</translation>
</message> </message>
<message> <message>
<location filename="../src/MainWindow.cpp" line="1327" /> <location filename="../src/MainWindow.cpp" line="1335" />
<source>从仓库移除</source> <source>从仓库移除</source>
<translation>Remove from repository</translation> <translation>Remove from repository</translation>
</message> </message>
<message> <message>
<location filename="../src/MainWindow.cpp" line="1329" /> <location filename="../src/MainWindow.cpp" line="1352" />
<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> <source>打开</source>
<translation>Open</translation> <translation>Open</translation>
</message> </message>
<message>
<location filename="../src/MainWindow.cpp" line="1351" />
<source>忽略(并从远端删除)</source>
<translation>Ignore (and delete from remote)</translation>
</message>
</context> </context>
<context> <context>
<name>MarkdownEditor</name> <name>MarkdownEditor</name>