Fix: корень EditorPanel — ColumnLayout вместо Item (исправляет layout в SplitView: вкладки сверху, редактор снизу); убрана обёртка Item; color:text на TextArea; автооткрытие первого .md

This commit is contained in:
Flora (opencode)
2026-08-17 18:15:22 +03:00
parent 18962473ae
commit 8048b2be2f
+149 -161
View File
@@ -3,8 +3,9 @@ import QtQuick.Controls
import QtQuick.Layouts import QtQuick.Layouts
// Центральная панель: панель вкладок + редактор. // Центральная панель: панель вкладок + редактор.
// Поддержка двух панелей рядом («открыть рядом»): правая = вторая вкладка. // Корень — ColumnLayout (без обёртки Item), чтобы SplitView корректно
Item { // задавал размеры и вкладки были сверху, а редактор снизу.
ColumnLayout {
id: root id: root
function baseName(p) { function baseName(p) {
@@ -12,161 +13,17 @@ Item {
return idx >= 0 ? p.substring(idx + 1) : p return idx >= 0 ? p.substring(idx + 1) : p
} }
ColumnLayout {
anchors.fill: parent
spacing: 0
// ----- Панель вкладок -----
Rectangle {
Layout.fillWidth: true
implicitHeight: 32
color: "#ececec"
RowLayout {
anchors.fill: parent
anchors.leftMargin: 4
anchors.rightMargin: 4
spacing: 2
Repeater {
model: documentManager.openTabs
Rectangle {
id: tab
required property string modelData
required property int index
readonly property bool active: index === documentManager.activeIndex
width: Math.max(96, Math.min(200, tabLabel.implicitWidth + 44))
height: 26
radius: 4
color: active ? "white" : "#e0e0e0"
RowLayout {
anchors.fill: parent
anchors.leftMargin: 8
anchors.rightMargin: 2
spacing: 4
MouseArea {
Layout.fillWidth: true
Layout.fillHeight: true
onClicked: documentManager.setActiveIndex(index)
onDoubleClicked: documentManager.closeTab(index)
Label {
id: tabLabel
anchors.verticalCenter: parent.verticalCenter
text: root.baseName(tab.modelData)
+ (documentManager.isDirty(tab.index) ? " •" : "")
font.pixelSize: 12
color: tab.active ? "#111" : "#555"
}
}
ToolButton {
text: "\u2715"
implicitWidth: 20
implicitHeight: 20
font.pixelSize: 9
opacity: tab.active || hovered ? 1 : 0
onClicked: documentManager.closeTab(tab.index)
}
}
}
}
Item { Layout.fillWidth: true }
Label {
visible: documentManager.openTabs.length === 0
text: qsTr("Откройте файл из дерева")
color: "#999"
font.pixelSize: 12
}
ToolButton {
id: splitBtn
text: "\u25A1\u25A1"
checkable: true
checked: documentManager.sideBySide
enabled: documentManager.openTabs.length > 0
ToolTip.visible: hovered
ToolTip.text: qsTr("Открыть рядом (две панели)")
onToggled: {
if (checked) {
documentManager.setSecondaryIndex(documentManager.activeIndex)
documentManager.setSideBySide(true)
} else {
documentManager.setSideBySide(false)
}
}
}
}
}
// ----- Панель форматирования (Фаза 5) -----
FormatToolbar {
id: formatToolbar
Layout.fillWidth: true
visible: documentManager.activeIndex >= 0 && toolbarShouldShow()
targetPane: activePane()
onTableRequested: {
tableEditor.resetDialog()
tableEditor.open()
}
}
// ----- Область редактора (одна или две панели) -----
RowLayout {
Layout.fillWidth: true
Layout.fillHeight: true
spacing: 0
EditorPane {
id: primaryPane
Layout.fillWidth: true
docIndex: documentManager.activeIndex
canOpenBeside: true
onOpenBeside: {
documentManager.setSecondaryIndex(documentManager.activeIndex)
documentManager.setSideBySide(true)
splitBtn.checked = true
}
}
Rectangle {
visible: documentManager.sideBySide
Layout.fillHeight: true
width: 1
color: "#ccc"
}
EditorPane {
id: secondaryPane
visible: documentManager.sideBySide
Layout.preferredWidth: 360
Layout.maximumWidth: 640
docIndex: documentManager.secondaryIndex
closable: true
onClosePane: {
documentManager.setSideBySide(false)
splitBtn.checked = false
}
}
}
}
// ----- Функции активной панели и таблица -----
function activePane() { function activePane() {
if (secondaryPane.visible && secondaryPane.hasFocus) if (secondaryPane.visible && secondaryPane.hasFocus)
return secondaryPane return secondaryPane
return primaryPane return primaryPane
} }
function toolbarShouldShow() { function toolbarShouldShow() {
const p = primaryPane const p = primaryPane
const s = secondaryPane const s = secondaryPane
return (p.hasFocus && p.editMode) return p.editMode
|| (s.visible && s.hasFocus && s.editMode) || (s.visible && s.editMode)
} }
Connections { Connections {
@@ -180,32 +37,163 @@ Item {
TableEditor { TableEditor {
id: tableEditor id: tableEditor
onMarkdownReady: (md) => { onMarkdownReady: (md) => root.activePane().insertText(md)
root.activePane().insertText(md) }
// ---------- Панель вкладок ----------
Rectangle {
Layout.fillWidth: true
implicitHeight: 32
color: "#ececec"
RowLayout {
anchors.fill: parent
anchors.leftMargin: 4
anchors.rightMargin: 4
spacing: 2
Repeater {
model: documentManager.openTabs
Rectangle {
id: tab
required property string modelData
required property int index
readonly property bool active: index === documentManager.activeIndex
width: Math.max(96, Math.min(200, tabLabel.implicitWidth + 44))
height: 26
radius: 4
color: active ? "white" : "#e0e0e0"
RowLayout {
anchors.fill: parent
anchors.leftMargin: 8
anchors.rightMargin: 2
spacing: 4
MouseArea {
Layout.fillWidth: true
Layout.fillHeight: true
onClicked: documentManager.setActiveIndex(index)
onDoubleClicked: documentManager.closeTab(index)
Label {
id: tabLabel
anchors.verticalCenter: parent.verticalCenter
text: root.baseName(tab.modelData)
+ (documentManager.isDirty(tab.index) ? " •" : "")
font.pixelSize: 12
color: tab.active ? "#111" : "#555"
}
}
ToolButton {
text: "\u2715"
implicitWidth: 20
implicitHeight: 20
font.pixelSize: 9
opacity: tab.active || hovered ? 1 : 0
onClicked: documentManager.closeTab(tab.index)
}
}
}
}
Item { Layout.fillWidth: true }
Label {
visible: documentManager.openTabs.length === 0
text: qsTr("Откройте файл из дерева")
color: "#999"
font.pixelSize: 12
}
ToolButton {
id: splitBtn
text: "\u25A1\u25A1"
checkable: true
checked: documentManager.sideBySide
enabled: documentManager.openTabs.length > 0
ToolTip.visible: hovered
ToolTip.text: qsTr("Открыть рядом (две панели)")
onToggled: {
if (checked) {
documentManager.setSecondaryIndex(documentManager.activeIndex)
documentManager.setSideBySide(true)
} else {
documentManager.setSideBySide(false)
}
}
}
} }
} }
// ----- Горячие клавиши ----- // ---------- Панель форматирования ----------
FormatToolbar {
id: formatToolbar
Layout.fillWidth: true
visible: documentManager.activeIndex >= 0 && toolbarShouldShow()
targetPane: activePane()
onTableRequested: {
tableEditor.resetDialog()
tableEditor.open()
}
}
// ---------- Область редактора (одна или две панели) ----------
RowLayout {
Layout.fillWidth: true
Layout.fillHeight: true
spacing: 0
EditorPane {
id: primaryPane
Layout.fillWidth: true
docIndex: documentManager.activeIndex
canOpenBeside: true
onOpenBeside: {
documentManager.setSecondaryIndex(documentManager.activeIndex)
documentManager.setSideBySide(true)
splitBtn.checked = true
}
}
Rectangle {
visible: documentManager.sideBySide
Layout.fillHeight: true
width: 1
color: "#ccc"
}
EditorPane {
id: secondaryPane
visible: documentManager.sideBySide
Layout.preferredWidth: 360
Layout.maximumWidth: 640
docIndex: documentManager.secondaryIndex
closable: true
onClosePane: {
documentManager.setSideBySide(false)
splitBtn.checked = false
}
}
}
// ---------- Горячие клавиши ----------
Shortcut { Shortcut {
sequence: "Ctrl+S" sequence: "Ctrl+S"
context: Qt.WindowShortcut context: Qt.WindowShortcut
onActivated: { onActivated: documentManager.saveAll()
documentManager.saveAll()
}
} }
Shortcut { Shortcut {
sequence: "Ctrl+W" sequence: "Ctrl+W"
context: Qt.WindowShortcut context: Qt.WindowShortcut
onActivated: { onActivated: documentManager.closeTab(documentManager.activeIndex)
documentManager.closeTab(documentManager.activeIndex)
}
} }
Shortcut { Shortcut {
sequence: "Ctrl+E" sequence: "Ctrl+E"
context: Qt.WindowShortcut context: Qt.WindowShortcut
onActivated: { onActivated: primaryPane.editMode = !primaryPane.editMode
primaryPane.editMode = !primaryPane.editMode
}
} }
Shortcut { Shortcut {
sequence: "Ctrl+Tab" sequence: "Ctrl+Tab"