import QtQuick import QtQuick.Controls import QtQuick.Layouts // Центральная панель: панель вкладок + редактор. // Корень — ColumnLayout (без обёртки Item), чтобы SplitView корректно // задавал размеры и вкладки были сверху, а редактор снизу. ColumnLayout { id: root function baseName(p) { const idx = p.lastIndexOf("/") return idx >= 0 ? p.substring(idx + 1) : p } function activePane() { if (secondaryPane.visible && secondaryPane.hasFocus) return secondaryPane return primaryPane } function toolbarShouldShow() { const p = primaryPane const s = secondaryPane return p.editMode || (s.visible && s.editMode) } Connections { target: primaryPane function onActiveFocusChanged() { formatToolbar.targetPane = root.activePane() } } Connections { target: secondaryPane function onActiveFocusChanged() { formatToolbar.targetPane = root.activePane() } } TableEditor { id: tableEditor 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() } Shortcut { sequence: "Ctrl+W" context: Qt.WindowShortcut onActivated: documentManager.closeTab(documentManager.activeIndex) } Shortcut { sequence: "Ctrl+E" context: Qt.WindowShortcut onActivated: primaryPane.editMode = !primaryPane.editMode } Shortcut { sequence: "Ctrl+Tab" context: Qt.WindowShortcut onActivated: { const n = documentManager.openTabs.length if (n > 0) documentManager.setActiveIndex((documentManager.activeIndex + 1) % n) } } }