import QtQuick import QtQuick.Controls import QtQuick.Layouts // Главное окно: меню вверху, три панели (дерево / редактор / правая). // Мульти-хранилища: каждое окно привязано к своему хранилищу (windowVault). ApplicationWindow { id: window width: 1280 height: 800 visible: true title: "Flora" color: "white" // Хранилище этого окна (задаётся WindowController); у основного окна // может быть пустым — тогда берём основное хранилище из настроек. property string windowVault: "" readonly property string activeVault: { if (fileStore.ready) return fileStore.vault if (windowVault.length > 0) return windowVault return vaultManager.currentVault } WelcomeWizard { id: welcomeWizard firstRun: vaultManager.vaults.length === 0 onFinished: { if (fileStore.ready) { // Добавлено новое хранилище при уже открытом — новое окно. windowController.openWindow(welcomeWizard.vaultPath) } else { // Первый запуск: применяем хранилище к этому окну. fileStore.openVault(welcomeWizard.vaultPath) root_status("Хранилище открыто") } } } function openWizard() { welcomeWizard.firstRun = false welcomeWizard.open() } function root_status(msg, ok) { console.log(msg) } Component.onCompleted: { if (windowVault.length > 0) { fileStore.openVault(windowVault) } else if (vaultManager.currentVault.length > 0) { fileStore.openVault(vaultManager.currentVault) } // Если хранилищ нет — мастер откроется автоматически. if (vaultManager.vaults.length === 0) welcomeWizard.open() } menuBar: MenuBar { Menu { title: qsTr("&Файл") Action { text: qsTr("Добавить хранилище…"); onTriggered: window.openWizard() } 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 } } // Переключатель хранилищ (кнопка внизу слева) Popup { id: vaultSwitcher x: 12 y: window.height - height - 12 width: 320 modal: false closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutside ColumnLayout { width: parent.width 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 === window.activeVault onClicked: { if (modelData === window.activeVault) { vaultSwitcher.close() } else { windowController.openWindow(modelData) vaultSwitcher.close() } } } } Label { visible: vaultList.count === 0 text: qsTr("Хранилищ пока нет") color: "#888" } Label { text: qsTr("Текущее: %1").arg(window.activeVault.length > 0 ? window.activeVault : "—") color: "#666" elide: Text.ElideMiddle Layout.fillWidth: true } Button { Layout.fillWidth: true text: qsTr("Добавить новое хранилище…") onClicked: { vaultSwitcher.close(); window.openWizard() } } } } 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() onOpenFileRequested: (path) => { // Фаза 4: открытие вкладки в редакторе. Пока — лог. console.log("Открыть файл: " + path) } } EditorPanel { SplitView.fillWidth: true SplitView.minimumWidth: 300 } RightPanel { SplitView.preferredWidth: window.width * 0.15 SplitView.minimumWidth: 140 SplitView.maximumWidth: 500 } } }