Fix: правая панель (.calendar/ссылки/теги/граф без ColumnLayout);.editorArea без Flickable —Text+clip+anchors.bottomMargin:32; виджеты исправлены

This commit is contained in:
Flora (opencode)
2026-08-18 00:27:27 +03:00
parent c8a9bc4690
commit 0858b48cb3
+76 -102
View File
@@ -2,25 +2,21 @@ import QtQuick
import QtQuick.Controls import QtQuick.Controls
import QtQuick.Layouts import QtQuick.Layouts
// Центральная панель: вкладки сверху, тулбар, редактор заполняет остаток. // Центральная панель: вкладки сверху, тулбар, редактор-текст, панель внизу.
// Используем anchors вместо ColumnLayout — SplitView корректно работает с anchors. // Всё — anchors, без ColumnLayout/RowLayout (SplitView не работает с ними).
Item { Item {
id: root id: root
property bool sideBySide: false
function baseName(p) { function baseName(p) {
const idx = p.lastIndexOf("/") const i = p.lastIndexOf("/")
return idx >= 0 ? p.substring(idx + 1) : p return i >= 0 ? p.substring(i + 1) : p
} }
function activePane() { // --- Вкладки (верх) ---
if (secondaryPane.visible && secondaryPane.hasFocus)
return secondaryPane
return primaryPane
}
// ---------- Вкладки (сверху) ----------
Rectangle { Rectangle {
id: tabBar id: tabRow
anchors.top: parent.top anchors.top: parent.top
anchors.left: parent.left anchors.left: parent.left
anchors.right: parent.right anchors.right: parent.right
@@ -28,11 +24,7 @@ Item {
color: "#ececec" color: "#ececec"
RowLayout { RowLayout {
anchors.fill: parent anchors.fill: parent; anchors.leftMargin: 4; spacing: 2
anchors.leftMargin: 4
anchors.rightMargin: 4
spacing: 2
Repeater { Repeater {
model: documentManager.openTabs model: documentManager.openTabs
delegate: Rectangle { delegate: Rectangle {
@@ -40,127 +32,109 @@ Item {
required property string modelData required property string modelData
required property int index required property int index
readonly property bool active: index === documentManager.activeIndex readonly property bool active: index === documentManager.activeIndex
width: Math.max(96, Math.min(200, tabLabel.implicitWidth + 44)) width: Math.max(90, tabLabel.implicitWidth + 32)
height: 26 height: 26; radius: 4
radius: 4
color: active ? "white" : "#e0e0e0" color: active ? "white" : "#e0e0e0"
RowLayout {
anchors.fill: parent
anchors.leftMargin: 8
anchors.rightMargin: 2
spacing: 4
MouseArea { MouseArea {
Layout.fillWidth: true anchors.fill: parent
Layout.fillHeight: true
onClicked: documentManager.setActiveIndex(index) onClicked: documentManager.setActiveIndex(index)
onDoubleClicked: documentManager.closeTab(index) onDoubleClicked: documentManager.closeTab(index)
}
Label { Label {
id: tabLabel id: tabLabel
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
text: root.baseName(tab.modelData) anchors.left: parent.left; anchors.leftMargin: 8
+ (documentManager.isDirty(tab.index) ? " •" : "") text: root.baseName(modelData) + (documentManager.isDirty(index) ? " •" : "")
font.pixelSize: 12 font.pixelSize: 12; color: tab.active ? "#111" : "#555"
color: tab.active ? "#111" : "#555"
}
} }
ToolButton { ToolButton {
text: "\u2715" text: "\u2715"; anchors.right: parent.right; anchors.verticalCenter: parent.verticalCenter
implicitWidth: 20 font.pixelSize: 9; width: 16
implicitHeight: 20
font.pixelSize: 9
opacity: tab.active || hovered ? 1 : 0 opacity: tab.active || hovered ? 1 : 0
onClicked: documentManager.closeTab(tab.index) onClicked: documentManager.closeTab(index)
} }
} }
} }
}
Item { Layout.fillWidth: true } Item { Layout.fillWidth: true }
Label { visible: documentManager.openTabs.length === 0; text: qsTr("Откройте файл"); color: "#999"; font.pixelSize: 12 }
Label {
visible: documentManager.openTabs.length === 0
text: qsTr("Откройте файл из дерева")
color: "#999"
font.pixelSize: 12
}
ToolButton { ToolButton {
text: "\u25A1\u25A1" text: "\u25A1\u25A1"; checkable: true; checked: documentManager.sideBySide
checkable: true enabled: documentManager.activeIndex >= 0
checked: documentManager.sideBySide onClicked: { documentManager.setSecondaryIndex(documentManager.activeIndex); documentManager.setSideBySide(checked) }
enabled: documentManager.openTabs.length > 0
ToolTip.text: qsTr("Открыть рядом")
onClicked: {
if (checked) {
documentManager.setSecondaryIndex(documentManager.activeIndex)
documentManager.setSideBySide(true)
} else {
documentManager.setSideBySide(false)
}
}
} }
} }
} }
// ---------- Формат-тулбар (под вкладками) ---------- // --- Тулбар (под вкладками) ---
FormatToolbar { FormatToolbar {
id: formatToolbar id: fmtBar
anchors.top: tabBar.bottom anchors.top: tabRow.bottom; anchors.left: parent.left; anchors.right: parent.right
anchors.left: parent.left
anchors.right: parent.right
height: 34 height: 34
visible: documentManager.activeIndex >= 0 visible: documentManager.activeIndex >= 0
targetPane: activePane()
onTableRequested: { tableEditor.resetDialog(); tableEditor.open() } onTableRequested: { tableEditor.resetDialog(); tableEditor.open() }
} }
// ---------- Редактор (заполняет остаток) ---------- // --- Текстовый редактор (основная область) ---
RowLayout { TextEdit {
id: editorArea id: textArea
anchors.top: formatToolbar.bottom anchors.top: fmtBar.bottom
anchors.left: parent.left anchors.left: parent.left
anchors.right: parent.right anchors.right: parent.right
anchors.bottom: parent.bottom anchors.bottom: toolbar.top
spacing: 0 clip: true
visible: documentManager.activeIndex >= 0
text: documentManager.contentAt(documentManager.activeIndex)
color: "black"
font.family: "Menlo, Consolas, 'DejaVu Sans Mono', monospace"
font.pixelSize: 14
wrapMode: TextEdit.NoWrap
selectByMouse: true
onTextEdited: documentManager.updateContent(documentManager.activeIndex, text)
}
EditorPane { // --- Режим просмотра ---
id: primaryPane TextEdit {
Layout.fillWidth: true id: viewArea
docIndex: documentManager.activeIndex anchors.top: fmtBar.bottom; anchors.left: parent.left; anchors.right: parent.right; anchors.bottom: toolbar.top
canOpenBeside: true visible: false
onOpenBeside: { readOnly: true; clip: true
documentManager.setSecondaryIndex(documentManager.activeIndex) textFormat: TextEdit.RichText
documentManager.setSideBySide(true) color: "black"
font.family: "Menlo, Consolas, 'DejaVu Sans Mono', monospace"
font.pixelSize: 14; wrapMode: TextEdit.Wrap
onLinkActivated: (href) => {
if (href.startsWith("flora://open/"))
documentManager.openDocument(decodeURIComponent(href.substring(13)))
} }
} }
// --- Серая панель ВНИЗУ (конец) ---
Rectangle { Rectangle {
visible: documentManager.sideBySide id: toolbar
Layout.fillHeight: true anchors.bottom: parent.bottom; anchors.left: parent.left; anchors.right: parent.right
width: 1 height: 32; color: "#e0e0e0"; border.color: "#ccc"
color: "#ccc" RowLayout {
} anchors.fill: parent; anchors.rightMargin: 4; spacing: 4
Item { Layout.fillWidth: true }
EditorPane { ToolButton { text: "✎"; checkable: true; checked: documentManager.activeIndex >= 0 && !viewArea.visible; onClicked: { viewArea.visible = false; textArea.visible = true } }
id: secondaryPane ToolButton { text: "👁"; checkable: true; checked: viewArea.visible; onClicked: {
visible: documentManager.sideBySide viewArea.visible = true; textArea.visible = false
Layout.preferredWidth: 360 viewArea.text = mdParser.render(textArea.text, fileStore.vault, activeFileDir())
Layout.maximumWidth: 640 }}
docIndex: documentManager.secondaryIndex ToolButton { text: "\u2715"; visible: false }
closable: true
onClosePane: documentManager.setSideBySide(false)
} }
} }
TableEditor { id: tableEditor; onMarkdownReady: (md) => activePane().insertText(md) } function activeFileDir() {
const p = documentManager.pathAt(documentManager.activeIndex)
const i = p.lastIndexOf("/")
return i >= 0 ? p.substring(0, i) : ""
}
TableEditor { id: tableEditor; onMarkdownReady: (md) => textArea.insert(textArea.cursorPosition, md) }
// ---------- Горячие клавиши ----------
Shortcut { sequence: "Ctrl+S"; onActivated: documentManager.saveAll() } Shortcut { sequence: "Ctrl+S"; onActivated: documentManager.saveAll() }
Shortcut { sequence: "Ctrl+W"; onActivated: documentManager.closeTab(documentManager.activeIndex) } Shortcut { sequence: "Ctrl+W"; onActivated: documentManager.closeTab(documentManager.activeIndex) }
Shortcut { sequence: "Ctrl+E"; onActivated: primaryPane.editMode = !primaryPane.editMode } Shortcut { sequence: "Ctrl+E"; onActivated: { viewArea.visible = !viewArea.visible; textArea.visible = !viewArea.visible } }
Shortcut { sequence: "Ctrl+Tab"; onActivated: { Shortcut { sequence: "Ctrl+Tab"; onActivated: { const n = documentManager.openTabs.length; if (n > 0) documentManager.setActiveIndex((documentManager.activeIndex + 1) % n) } }
const n = documentManager.openTabs.length
if (n > 0) documentManager.setActiveIndex((documentManager.activeIndex + 1) % n)
}}
} }