SQLite-база хранилища: свойства, ~sql-блоки, настройки хранилища
- Frontmatter: шапка --- ключ: значение (источник правды свойств) - VaultSettings: .flora/settings.json (журнал, sqlEnabled, sqlMaxRows) - Database: files/tags/file_tags/links/properties, только SELECT/WITH на read-only соединении (mode=ro + query_only + зонд), лимит строк - MdParser: ~sql-блоки таблицей (parseBlocks + Renderer), шапка скрыта в просмотре - Окно: per-window Database/VaultSettings, sync при сохранении, дебаунс reindex - QML: VaultSettingsDialog, FilePropertiesDialog, меню, автообновление ~sql - FileStore.journalDir, DocumentManager.reloadDocument - Тест flora_db_test (23/23 зелёных)
This commit is contained in:
@@ -0,0 +1,163 @@
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
import Flora
|
||||
|
||||
// Настройки одного хранилища: лежат в <vault>/.flora/settings.json,
|
||||
// в git не попадают (как и сама база). Применяются живьём через vaultSettings.
|
||||
Dialog {
|
||||
id: root
|
||||
|
||||
title: qsTr("Настройки хранилища")
|
||||
modal: true
|
||||
width: 560
|
||||
height: 640
|
||||
anchors.centerIn: parent
|
||||
closePolicy: Dialog.CloseOnEscape | Dialog.CloseOnPressOutside
|
||||
standardButtons: Dialog.NoButton
|
||||
background: Rectangle { color: Theme.surface; border.color: Theme.borderStrong; radius: 10 }
|
||||
|
||||
footer: RowLayout {
|
||||
spacing: 8
|
||||
Item { Layout.fillWidth: true }
|
||||
Button {
|
||||
text: qsTr("Отмена")
|
||||
onClicked: {
|
||||
// откатить живьём применённое (сеттеры уже ушли в базу через changed)
|
||||
vaultSettings.open(fileStore.vault)
|
||||
root.reject()
|
||||
}
|
||||
}
|
||||
Button {
|
||||
text: qsTr("Сохранить")
|
||||
highlighted: true
|
||||
onClicked: root.saveSettings()
|
||||
}
|
||||
}
|
||||
|
||||
onOpened: {
|
||||
journalField.text = vaultSettings.journalDir
|
||||
sqlCheck.checked = vaultSettings.sqlEnabled
|
||||
maxRowsSpin.value = vaultSettings.sqlMaxRows
|
||||
root.refreshStats()
|
||||
statusLabel.text = ""
|
||||
}
|
||||
|
||||
function saveSettings() {
|
||||
vaultSettings.journalDir = journalField.text
|
||||
vaultSettings.sqlEnabled = sqlCheck.checked
|
||||
vaultSettings.sqlMaxRows = maxRowsSpin.value
|
||||
// Флаги уже ушли в базу живьём (сигнал changed); здесь только persist
|
||||
if (!vaultSettings.save()) {
|
||||
statusLabel.text = qsTr("Не удалось записать .flora/settings.json")
|
||||
return
|
||||
}
|
||||
root.accept()
|
||||
}
|
||||
|
||||
function refreshStats() {
|
||||
const s = vaultDatabase.stats()
|
||||
statFiles.text = s.files
|
||||
statTags.text = s.tags
|
||||
statLinks.text = s.links
|
||||
statProps.text = s.properties
|
||||
const kb = Math.round(s.dbSize / 1024)
|
||||
statDb.text = kb < 1024 ? kb + " КБ" : (kb / 1024).toFixed(1) + " МБ"
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
anchors.fill: parent
|
||||
spacing: 10
|
||||
|
||||
Label {
|
||||
Layout.fillWidth: true
|
||||
wrapMode: Text.Wrap
|
||||
color: Theme.textSecondary
|
||||
font.pixelSize: 11
|
||||
text: fileStore.ready ? fileStore.vault : qsTr("Хранилище не открыто")
|
||||
elide: Text.ElideMiddle
|
||||
}
|
||||
|
||||
GroupBox {
|
||||
Layout.fillWidth: true
|
||||
title: qsTr("Заметки дня")
|
||||
background: Rectangle { color: Theme.bgAlt; border.color: Theme.border; radius: 8 }
|
||||
label: Label { text: parent.title; color: Theme.text; font.bold: true; leftPadding: 6 }
|
||||
RowLayout {
|
||||
anchors.fill: parent
|
||||
anchors.margins: 8
|
||||
Label { text: qsTr("Папка:"); color: Theme.textSecondary }
|
||||
TextField {
|
||||
id: journalField
|
||||
Layout.fillWidth: true
|
||||
placeholderText: qsTr("Журнал")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GroupBox {
|
||||
Layout.fillWidth: true
|
||||
title: qsTr("SQL-блоки (~sql)")
|
||||
background: Rectangle { color: Theme.bgAlt; border.color: Theme.border; radius: 8 }
|
||||
label: Label { text: parent.title; color: Theme.text; font.bold: true; leftPadding: 6 }
|
||||
ColumnLayout {
|
||||
anchors.fill: parent
|
||||
anchors.margins: 8
|
||||
spacing: 6
|
||||
CheckBox {
|
||||
id: sqlCheck
|
||||
text: qsTr("Выполнять ~sql-запросы в просмотре")
|
||||
}
|
||||
RowLayout {
|
||||
Label { text: qsTr("Строк в результате:"); color: Theme.textSecondary }
|
||||
SpinBox { id: maxRowsSpin; from: 5; to: 500; stepSize: 5; editable: true }
|
||||
}
|
||||
Label {
|
||||
Layout.fillWidth: true
|
||||
wrapMode: Text.Wrap
|
||||
color: Theme.textFaint
|
||||
font.pixelSize: 11
|
||||
text: qsTr("Таблицы: files(path,title,mtime,size), tags(name), file_tags, links, properties(file_id,key,value). Только чтение (SELECT / WITH).")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GroupBox {
|
||||
Layout.fillWidth: true
|
||||
title: qsTr("База хранилища")
|
||||
background: Rectangle { color: Theme.bgAlt; border.color: Theme.border; radius: 8 }
|
||||
label: Label { text: parent.title; color: Theme.text; font.bold: true; leftPadding: 6 }
|
||||
ColumnLayout {
|
||||
anchors.fill: parent
|
||||
anchors.margins: 8
|
||||
spacing: 4
|
||||
GridLayout {
|
||||
columns: 2
|
||||
columnSpacing: 12
|
||||
Label { text: qsTr("Файлов:"); color: Theme.textSecondary }
|
||||
Label { id: statFiles; color: Theme.text }
|
||||
Label { text: qsTr("Тегов:"); color: Theme.textSecondary }
|
||||
Label { id: statTags; color: Theme.text }
|
||||
Label { text: qsTr("Связей:"); color: Theme.textSecondary }
|
||||
Label { id: statLinks; color: Theme.text }
|
||||
Label { text: qsTr("Свойств:"); color: Theme.textSecondary }
|
||||
Label { id: statProps; color: Theme.text }
|
||||
Label { text: qsTr("База:"); color: Theme.textSecondary }
|
||||
Label { id: statDb; color: Theme.text }
|
||||
}
|
||||
Button {
|
||||
text: qsTr("Обновить статистику")
|
||||
onClicked: root.refreshStats()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Label {
|
||||
id: statusLabel
|
||||
Layout.fillWidth: true
|
||||
wrapMode: Text.Wrap
|
||||
color: "#e5484d"
|
||||
font.pixelSize: 11
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user