Fix: корень EditorPanel — ColumnLayout вместо Item (исправляет layout в SplitView: вкладки сверху, редактор снизу); убрана обёртка Item; color:text на TextArea; автооткрытие первого .md
This commit is contained in:
+149
-161
@@ -3,8 +3,9 @@ import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
|
||||
// Центральная панель: панель вкладок + редактор.
|
||||
// Поддержка двух панелей рядом («открыть рядом»): правая = вторая вкладка.
|
||||
Item {
|
||||
// Корень — ColumnLayout (без обёртки Item), чтобы SplitView корректно
|
||||
// задавал размеры и вкладки были сверху, а редактор снизу.
|
||||
ColumnLayout {
|
||||
id: root
|
||||
|
||||
function baseName(p) {
|
||||
@@ -12,161 +13,17 @@ Item {
|
||||
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() {
|
||||
if (secondaryPane.visible && secondaryPane.hasFocus)
|
||||
return secondaryPane
|
||||
return primaryPane
|
||||
}
|
||||
|
||||
function toolbarShouldShow() {
|
||||
const p = primaryPane
|
||||
const s = secondaryPane
|
||||
return (p.hasFocus && p.editMode)
|
||||
|| (s.visible && s.hasFocus && s.editMode)
|
||||
return p.editMode
|
||||
|| (s.visible && s.editMode)
|
||||
}
|
||||
|
||||
Connections {
|
||||
@@ -180,32 +37,163 @@ Item {
|
||||
|
||||
TableEditor {
|
||||
id: tableEditor
|
||||
onMarkdownReady: (md) => {
|
||||
root.activePane().insertText(md)
|
||||
onMarkdownReady: (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 {
|
||||
sequence: "Ctrl+S"
|
||||
context: Qt.WindowShortcut
|
||||
onActivated: {
|
||||
documentManager.saveAll()
|
||||
}
|
||||
onActivated: documentManager.saveAll()
|
||||
}
|
||||
Shortcut {
|
||||
sequence: "Ctrl+W"
|
||||
context: Qt.WindowShortcut
|
||||
onActivated: {
|
||||
documentManager.closeTab(documentManager.activeIndex)
|
||||
}
|
||||
onActivated: documentManager.closeTab(documentManager.activeIndex)
|
||||
}
|
||||
Shortcut {
|
||||
sequence: "Ctrl+E"
|
||||
context: Qt.WindowShortcut
|
||||
onActivated: {
|
||||
primaryPane.editMode = !primaryPane.editMode
|
||||
}
|
||||
onActivated: primaryPane.editMode = !primaryPane.editMode
|
||||
}
|
||||
Shortcut {
|
||||
sequence: "Ctrl+Tab"
|
||||
|
||||
Reference in New Issue
Block a user