2026-08-17 00:05:20 +03:00
|
|
|
|
import QtQuick
|
|
|
|
|
|
import QtQuick.Controls
|
|
|
|
|
|
import QtQuick.Layouts
|
|
|
|
|
|
|
|
|
|
|
|
// Главное окно: меню вверху, три панели (дерево / редактор / правая).
|
2026-08-17 00:43:33 +03:00
|
|
|
|
// Фазы 0-1: каркас + мастер первого запуска. Контент панелей — в следующих фазах.
|
2026-08-17 00:05:20 +03:00
|
|
|
|
ApplicationWindow {
|
|
|
|
|
|
id: window
|
|
|
|
|
|
width: 1280
|
|
|
|
|
|
height: 800
|
|
|
|
|
|
visible: true
|
|
|
|
|
|
title: "Flora"
|
|
|
|
|
|
color: "white"
|
|
|
|
|
|
|
2026-08-17 00:43:33 +03:00
|
|
|
|
// Мастер первого запуска: показываем, если ещё нет ни одного хранилища.
|
|
|
|
|
|
WelcomeWizard {
|
|
|
|
|
|
id: welcomeWizard
|
|
|
|
|
|
firstRun: vaultManager.vaults.length === 0
|
|
|
|
|
|
onFinished: vaultSwitcher.close()
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Component.onCompleted: {
|
|
|
|
|
|
if (vaultManager.vaults.length === 0)
|
|
|
|
|
|
welcomeWizard.open()
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function openWizard() {
|
|
|
|
|
|
welcomeWizard.firstRun = false
|
|
|
|
|
|
welcomeWizard.open()
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-08-17 00:05:20 +03:00
|
|
|
|
menuBar: MenuBar {
|
|
|
|
|
|
Menu {
|
|
|
|
|
|
title: qsTr("&Файл")
|
2026-08-17 00:43:33 +03:00
|
|
|
|
Action { text: qsTr("Добавить хранилище…"); onTriggered: window.openWizard() }
|
2026-08-17 00:05:20 +03:00
|
|
|
|
Menu {
|
|
|
|
|
|
title: qsTr("Экспорт")
|
|
|
|
|
|
Action { text: qsTr("В HTML…"); enabled: false }
|
|
|
|
|
|
Action { text: qsTr("В PDF…"); enabled: false }
|
|
|
|
|
|
}
|
|
|
|
|
|
MenuSeparator { }
|
|
|
|
|
|
Action { text: qsTr("Выход"); onTriggered: window.close() }
|
|
|
|
|
|
}
|
|
|
|
|
|
Menu {
|
|
|
|
|
|
title: qsTr("&Правка")
|
|
|
|
|
|
Action { text: qsTr("Отменить"); shortcut: "Ctrl+Z"; enabled: false }
|
|
|
|
|
|
Action { text: qsTr("Повторить"); shortcut: "Ctrl+Shift+Z"; enabled: false }
|
|
|
|
|
|
MenuSeparator { }
|
|
|
|
|
|
Action {
|
|
|
|
|
|
text: qsTr("Вернуться к предыдущей версии…"); enabled: false
|
|
|
|
|
|
// Диалог истории с diff-режимом — Фаза 9.
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
Menu {
|
|
|
|
|
|
title: qsTr("&Вид")
|
|
|
|
|
|
Action { text: qsTr("Светлая тема"); checkable: true; checked: true }
|
|
|
|
|
|
Action { text: qsTr("Тёмная тема"); checkable: true }
|
|
|
|
|
|
}
|
|
|
|
|
|
Menu {
|
|
|
|
|
|
title: qsTr("&Справка")
|
|
|
|
|
|
Action {
|
|
|
|
|
|
text: qsTr("О программе")
|
|
|
|
|
|
onTriggered: aboutDialog.open()
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Dialog {
|
|
|
|
|
|
id: aboutDialog
|
|
|
|
|
|
title: qsTr("О программе")
|
|
|
|
|
|
standardButtons: Dialog.Ok
|
|
|
|
|
|
modal: true
|
|
|
|
|
|
anchors.centerIn: parent
|
|
|
|
|
|
Label {
|
|
|
|
|
|
text: "Flora\nМинималистичный markdown-заметочник (GPL-3.0)\n"
|
|
|
|
|
|
+ "Версия " + Qt.application.version
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-08-17 00:43:33 +03:00
|
|
|
|
// Переключатель хранилищ (кнопка внизу слева, в FileTreePanel)
|
2026-08-17 00:05:20 +03:00
|
|
|
|
Popup {
|
|
|
|
|
|
id: vaultSwitcher
|
|
|
|
|
|
x: 12
|
|
|
|
|
|
y: window.height - height - 12
|
2026-08-17 00:43:33 +03:00
|
|
|
|
width: 320
|
2026-08-17 00:05:20 +03:00
|
|
|
|
modal: false
|
|
|
|
|
|
closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutside
|
2026-08-17 00:43:33 +03:00
|
|
|
|
|
2026-08-17 00:05:20 +03:00
|
|
|
|
ColumnLayout {
|
|
|
|
|
|
width: parent.width
|
2026-08-17 00:43:33 +03:00
|
|
|
|
spacing: 6
|
|
|
|
|
|
|
|
|
|
|
|
Label {
|
|
|
|
|
|
text: qsTr("Хранилища")
|
|
|
|
|
|
font.bold: true
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
ListView {
|
|
|
|
|
|
id: vaultList
|
|
|
|
|
|
Layout.preferredHeight: Math.min(200, contentHeight)
|
|
|
|
|
|
Layout.fillWidth: true
|
|
|
|
|
|
model: vaultManager.vaults
|
|
|
|
|
|
clip: true
|
|
|
|
|
|
delegate: ItemDelegate {
|
|
|
|
|
|
width: ListView.view.width
|
|
|
|
|
|
text: modelData
|
|
|
|
|
|
highlighted: modelData === vaultManager.currentVault
|
|
|
|
|
|
onClicked: {
|
|
|
|
|
|
if (modelData !== vaultManager.currentVault) {
|
|
|
|
|
|
vaultManager.selectVault(modelData)
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Label {
|
|
|
|
|
|
visible: vaultList.count === 0
|
|
|
|
|
|
text: qsTr("Хранилищ пока нет")
|
|
|
|
|
|
color: "#888"
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Label {
|
|
|
|
|
|
text: qsTr("Текущее: %1").arg(vaultManager.currentVault.length > 0
|
|
|
|
|
|
? vaultManager.currentVault : "—")
|
|
|
|
|
|
color: "#666"
|
|
|
|
|
|
elide: Text.ElideMiddle
|
|
|
|
|
|
Layout.fillWidth: true
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-08-17 00:05:20 +03:00
|
|
|
|
Button {
|
2026-08-17 00:43:33 +03:00
|
|
|
|
Layout.fillWidth: true
|
2026-08-17 00:05:20 +03:00
|
|
|
|
text: qsTr("Добавить новое хранилище…")
|
2026-08-17 00:43:33 +03:00
|
|
|
|
onClicked: { vaultSwitcher.close(); window.openWizard() }
|
2026-08-17 00:05:20 +03:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
SplitView {
|
|
|
|
|
|
anchors.fill: parent
|
|
|
|
|
|
orientation: Qt.Horizontal
|
|
|
|
|
|
|
|
|
|
|
|
FileTreePanel {
|
|
|
|
|
|
id: leftPanel
|
|
|
|
|
|
SplitView.preferredWidth: window.width * 0.15
|
|
|
|
|
|
SplitView.minimumWidth: 120
|
|
|
|
|
|
SplitView.maximumWidth: 500
|
|
|
|
|
|
onOpenVaultRequested: vaultSwitcher.open()
|
|
|
|
|
|
onNewFileRequested: console.log("Новый файл (Фаза 3)")
|
|
|
|
|
|
onNewFolderRequested: console.log("Новая папка (Фаза 3)")
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
EditorPanel {
|
|
|
|
|
|
SplitView.fillWidth: true
|
|
|
|
|
|
SplitView.minimumWidth: 300
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
RightPanel {
|
|
|
|
|
|
SplitView.preferredWidth: window.width * 0.15
|
|
|
|
|
|
SplitView.minimumWidth: 140
|
|
|
|
|
|
SplitView.maximumWidth: 500
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|