Инкрементальный индекс, пресеты автосейва, диалог Настройки
- VaultIndex: updateFile/removeFile/syncIncremental (mtime+size), полный рескан только на старте/смене/внешних изменениях; relink висячих [[ссылок]] при создании файла; FileStore.externalChanged для внешних правок - QML: сейвы и правки идут точечно, дерево — через syncIncremental - Настройки: пресеты safe/balanced/eco/manual (диск 2/5/10с/выкл, коммит после паузы 5/15/60с/вручную), диалог с +/-, шкалами и подсказкой; коммит только в простое, в manual — по Ctrl+S - Удалены highlightedCode, словный merge, fileDiffText/Html, 2-arg fileHistory; renderInner без побочек - Тесты: инкремент индекса, пресеты, autosaveEnabled, ~~~-блоки
This commit is contained in:
@@ -129,6 +129,26 @@ int main(int argc, char *argv[])
|
||||
|| dm.isTextForEditor("/x/a.pdf"))
|
||||
return fail("isTextForEditor");
|
||||
|
||||
// --- autosaveEnabled (ручной режим настроек) ---
|
||||
if (!dm.autosaveEnabled())
|
||||
return fail("autosave enabled by default");
|
||||
{
|
||||
QTimer *t = dm.findChild<QTimer*>();
|
||||
if (!t || !t->isActive())
|
||||
return fail("autosave timer active");
|
||||
}
|
||||
dm.setAutosaveEnabled(false);
|
||||
if (dm.autosaveEnabled())
|
||||
return fail("autosave disabled");
|
||||
{
|
||||
QTimer *t = dm.findChild<QTimer*>();
|
||||
if (!t || t->isActive())
|
||||
return fail("autosave timer stopped");
|
||||
}
|
||||
dm.setAutosaveEnabled(true);
|
||||
if (!dm.autosaveEnabled())
|
||||
return fail("autosave re-enabled");
|
||||
|
||||
std::printf("DOCUMENT MANAGER TEST OK\n");
|
||||
return 0;
|
||||
}
|
||||
@@ -138,11 +138,11 @@ int main(int argc, char *argv[])
|
||||
|
||||
// Подсветка: переносы строк — явные <br/>, иначе RichText склеит в одну строку
|
||||
{
|
||||
QString hl = p.highlightedCode("int a = 1;\nint b = 2;\n", "cpp");
|
||||
auto b = p.parseBlocks("```cpp\nint a = 1;\nint b = 2;\n```\n", vault, fileDir);
|
||||
if (b.size() != 1) return fail("br блок");
|
||||
const QString hl = b[0].toMap().value("highlightedText").toString();
|
||||
if (!hl.contains("<br/>")) return fail("highlighted без <br/>", hl.left(200));
|
||||
if (hl.contains("\n")) return fail("highlighted с сырым \\n", hl.left(200));
|
||||
QString plain = p.highlightedCode("a\nb", "неизвестный-язык-xyz");
|
||||
if (!plain.contains("<br/>")) return fail("plain highlight без <br/>", plain);
|
||||
}
|
||||
|
||||
// parseBlocksWithDiff: версия old vs текущее new
|
||||
|
||||
@@ -124,6 +124,28 @@ int main(int argc, char *argv[])
|
||||
if (after.contains(vault + "|" + "old.md")) return fail("old key not migrated");
|
||||
}
|
||||
|
||||
// autosave presets
|
||||
if (s.autosavePreset() != "balanced") return fail("default preset");
|
||||
if (s.autosaveDiskMs() != 5000) return fail("balanced disk");
|
||||
if (s.autocommitIdleMs() != 15000) return fail("balanced idle");
|
||||
if (!s.autosaveEnabled() || !s.autocommitEnabled()) return fail("balanced enabled");
|
||||
s.setAutosavePreset("safe");
|
||||
if (s.autosavePreset() != "safe") return fail("safe preset");
|
||||
if (s.autosaveDiskMs() != 2000 || s.autocommitIdleMs() != 5000) return fail("safe values");
|
||||
s.setAutosavePreset("eco");
|
||||
if (s.autosaveDiskMs() != 10000 || s.autocommitIdleMs() != 60000) return fail("eco values");
|
||||
s.setAutosavePreset("manual");
|
||||
if (s.autosaveEnabled() || s.autocommitEnabled()) return fail("manual disabled");
|
||||
if (s.autosaveDiskMs() != 0 || s.autocommitIdleMs() != 0) return fail("manual zeros");
|
||||
s.setAutosavePreset(" wat? ");
|
||||
if (s.autosavePreset() != "balanced") return fail("invalid preset fallback");
|
||||
s.setAutosavePreset("eco");
|
||||
{
|
||||
SettingsStore s2;
|
||||
if (s2.autosavePreset() != "eco") return fail("preset persistence");
|
||||
if (s2.autosaveDiskMs() != 10000) return fail("preset values persistence");
|
||||
}
|
||||
|
||||
std::printf("SETTINGS TEST OK\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -87,6 +87,75 @@ int main(int argc, char *argv[])
|
||||
if (files2.size() != 2)
|
||||
return fail("filesWithTag(тег2)", QString::number(files2.size()));
|
||||
|
||||
// --- инкремент: updateFile меняет только один файл (убираем теги из a.md) ---
|
||||
put("a.md", "# Заголовок\n\nСсылка на [[b]].\n");
|
||||
idx.updateFile(a);
|
||||
if (idx.fileCount() != 3)
|
||||
return fail("updateFile fileCount", QString::number(idx.fileCount()));
|
||||
// a.md теперь без тегов — тег1 остался только... нигде: filesWithTag пуст
|
||||
if (!idx.filesWithTag("тег1").isEmpty())
|
||||
return fail("updateFile снял тег1", idx.filesWithTag("тег1").join(","));
|
||||
if (idx.tagsOfFile(a).size() != 0)
|
||||
return fail("updateFile tagsOfFile", idx.tagsOfFile(a).join(","));
|
||||
// b.md не трогали — его теги на месте
|
||||
if (!idx.tagsOfFile(b).contains("тег2"))
|
||||
return fail("updateFile не тронул b");
|
||||
|
||||
// --- инкремент: новый файл чинит висячую ссылку (relink) ---
|
||||
put("d.md", "Ссылка на [[future]].\n");
|
||||
const QString d = dir.path() + "/d.md";
|
||||
idx.updateFile(d);
|
||||
if (idx.fileCount() != 4)
|
||||
return fail("updateFile new fileCount", QString::number(idx.fileCount()));
|
||||
if (!idx.linksOfFile(d).isEmpty())
|
||||
return fail("висячая ссылка должна быть пустой");
|
||||
put("sub/future.md", "# Future\n");
|
||||
const QString future = dir.path() + "/sub/future.md";
|
||||
idx.updateFile(future);
|
||||
{
|
||||
bool foundFuture = false;
|
||||
for (const auto &l : idx.linksOfFile(d))
|
||||
if (l.toMap().value("path").toString() == future)
|
||||
foundFuture = true;
|
||||
if (!foundFuture)
|
||||
return fail("relink не починил [[future]]");
|
||||
}
|
||||
|
||||
// --- инкремент: removeFile чистит теги/ссылки/узел ---
|
||||
// (в реальности вызывается потому что файл удалён — удаляем и с диска)
|
||||
QFile::remove(future);
|
||||
idx.removeFile(future);
|
||||
if (idx.fileCount() != 4)
|
||||
return fail("removeFile fileCount", QString::number(idx.fileCount()));
|
||||
{
|
||||
bool foundFuture = false;
|
||||
for (const auto &l : idx.linksOfFile(d))
|
||||
if (l.toMap().value("path").toString() == future)
|
||||
foundFuture = true;
|
||||
if (foundFuture)
|
||||
return fail("removeFile не убрал входящую ссылку");
|
||||
}
|
||||
// removeFile несуществующего — тихо, без падения
|
||||
idx.removeFile(dir.path() + "/нет-такого.md");
|
||||
idx.updateFile(dir.path() + "/нет-такого.md");
|
||||
|
||||
// --- инкремент: syncIncremental догоняет внешние изменения ---
|
||||
put("ext.md", "Внешний #внешний\n");
|
||||
const QString ext = dir.path() + "/ext.md";
|
||||
if (idx.fileCount() != 4)
|
||||
return fail("до sync файл не виден", QString::number(idx.fileCount()));
|
||||
idx.syncIncremental();
|
||||
if (idx.fileCount() != 5)
|
||||
return fail("sync подхватил файл", QString::number(idx.fileCount()));
|
||||
if (!idx.tagsOfFile(ext).contains("внешний"))
|
||||
return fail("sync теги");
|
||||
QFile::remove(ext);
|
||||
idx.syncIncremental();
|
||||
if (idx.fileCount() != 4)
|
||||
return fail("sync убрал файл", QString::number(idx.fileCount()));
|
||||
if (idx.tagsOfFile(ext).size() != 0)
|
||||
return fail("sync теги удалены");
|
||||
|
||||
std::printf("VAULTINDEX TEST OK\n");
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user