Фаза 0: каркас — CMake (cmark-gfm, libgit2+SSH, libssh2), QML-скелет (меню, 3 панели, кнопка «+»), VaultManager, LICENSE GPL-3.0

This commit is contained in:
Flora (opencode)
2026-08-17 00:05:20 +03:00
parent d4734506cb
commit 980fbcedcb
10 changed files with 1251 additions and 0 deletions
+106
View File
@@ -0,0 +1,106 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
// Главное окно: меню вверху, три панели (дерево / редактор / правая).
// Фаза 0: каркас. Содержимое панелей наполняется в следующих фазах.
ApplicationWindow {
id: window
width: 1280
height: 800
visible: true
title: "Flora"
color: "white"
menuBar: MenuBar {
Menu {
title: qsTr("&Файл")
Action { text: qsTr("Открыть хранилище…"); onTriggered: vaultSwitcher.open() }
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: 280
modal: false
closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutside
ColumnLayout {
width: parent.width
Label { text: qsTr("Хранилища (Фаза 2)") }
Button { text: qsTr("Это окно: %1").arg(vaultManager.currentVault) }
Button {
text: qsTr("Добавить новое хранилище…")
onClicked: { vaultSwitcher.close(); vaultManager.setCurrentVault("/") }
}
}
}
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
}
}
}
+62
View File
@@ -0,0 +1,62 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
// Центральная панель: панель вкладок + редактор.
// Фаза 0 — каркас: вкладки, два столбца «открыть рядом» (задел),
// переключение режимов редактирование/просмотр (задел).
Item {
id: root
readonly property bool editMode: true // Фаза 4: реальный переключатель
ColumnLayout {
anchors.fill: parent
spacing: 0
// Панель вкладок
Rectangle {
Layout.fillWidth: true
implicitHeight: 32
color: "whitesmoke"
RowLayout {
anchors.fill: parent
anchors.leftMargin: 4
spacing: 4
Repeater {
model: 0 // открытые вкладки наполняются в Фазе 4
}
Label {
Layout.fillWidth: true
text: qsTr("— нет открытых файлов —")
color: "#bbb"
}
ToolButton {
text: "▮▮" // «открыть рядом» (Фаза 4)
ToolTip.visible: hovered
ToolTip.text: qsTr("Открыть рядом (две панели)")
enabled: false
}
}
}
// Область редактирования
Rectangle {
Layout.fillWidth: true
Layout.fillHeight: true
color: "white"
Label {
anchors.centerIn: parent
text: root.editMode
? qsTr("Редактор\nОткройте файл из дерева (Фаза 4)")
: qsTr("Просмотр\n(Фаза 4)")
horizontalAlignment: Text.AlignHCenter
color: "#bbb"
}
}
}
}
+85
View File
@@ -0,0 +1,85 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
// Левая панель: файловое дерево. Фаза 0 — каркас:
// кнопка «+» над деревом с меню-бутербродом («Файл»/«Папка»),
// кнопка хранилища внизу слева. Само дерево и операции — Фаза 3.
Item {
id: root
signal openVaultRequested()
signal newFileRequested()
signal newFolderRequested()
ColumnLayout {
anchors.fill: parent
spacing: 0
// Заголовок панели: кнопка «+» + название
Rectangle {
Layout.fillWidth: true
implicitHeight: 36
color: "whitesmoke"
RowLayout {
anchors.fill: parent
anchors.leftMargin: 4
spacing: 4
Button {
id: addButton
text: "+"
implicitWidth: 28
implicitHeight: 26
ToolTip.visible: hovered
ToolTip.text: qsTr("Создать")
onClicked: addMenu.popup()
}
Label {
text: qsTr("Файлы")
Layout.fillWidth: true
elide: Text.ElideRight
color: "#555"
}
}
}
// Место файлового дерева (Фаза 3)
Rectangle {
Layout.fillWidth: true
Layout.fillHeight: true
color: "#fafafa"
Label {
anchors.centerIn: parent
text: qsTr("Дерево файлов\n(Фаза 3)")
horizontalAlignment: Text.AlignHCenter
color: "#bbb"
}
}
// Кнопка хранилища внизу слева
Button {
id: vaultButton
Layout.fillWidth: true
text: qsTr("▨ Хранилище…")
onClicked: root.openVaultRequested()
}
}
// Меню-«бутерброд» при нажатии «+»
Menu {
id: addMenu
x: addButton.x
y: addButton.y + addButton.height
width: 140
Action {
text: qsTr("Файл")
onTriggered: root.newFileRequested()
}
Action {
text: qsTr("Папка")
onTriggered: root.newFolderRequested()
}
}
}
+38
View File
@@ -0,0 +1,38 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
// Правая панель: календарь + ссылки/теги + граф связей.
// Фаза 0 — каркас; контент наполняется в Фазах 7 и 8.
Item {
id: root
ColumnLayout {
anchors.fill: parent
spacing: 0
Rectangle {
Layout.fillWidth: true
Layout.fillHeight: true
color: "#fafafa"
Label {
anchors.centerIn: parent
text: qsTr("Календарь\n(Фаза 7)")
horizontalAlignment: Text.AlignHCenter
color: "#bbb"
}
}
Rectangle {
Layout.fillWidth: true
Layout.fillHeight: true
color: "#f5f5f5"
Label {
anchors.centerIn: parent
text: qsTr("Граф связей\n(Фаза 7)")
horizontalAlignment: Text.AlignHCenter
color: "#bbb"
}
}
}
}