183 lines
6.6 KiB
QML
183 lines
6.6 KiB
QML
import QtQuick
|
|
import QtQuick.Controls
|
|
import QtQuick.Layouts
|
|
|
|
// Центральная панель: вкладки сверху, тулбар, редактор заполняет остаток.
|
|
// Используем anchors вместо ColumnLayout — SplitView корректно работает с anchors.
|
|
Item {
|
|
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
|
|
}
|
|
|
|
// ---------- Вкладки (сверху) ----------
|
|
Rectangle {
|
|
id: tabBar
|
|
anchors.top: parent.top
|
|
anchors.left: parent.left
|
|
anchors.right: parent.right
|
|
height: 32
|
|
color: "#ececec"
|
|
|
|
RowLayout {
|
|
anchors.fill: parent
|
|
anchors.leftMargin: 4
|
|
anchors.rightMargin: 4
|
|
spacing: 2
|
|
|
|
Repeater {
|
|
model: documentManager.openTabs
|
|
delegate: 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 {
|
|
text: "\u25A1\u25A1"
|
|
checkable: true
|
|
checked: documentManager.sideBySide
|
|
enabled: documentManager.openTabs.length > 0
|
|
ToolTip.text: qsTr("Открыть рядом")
|
|
onClicked: {
|
|
if (checked) {
|
|
documentManager.setSecondaryIndex(documentManager.activeIndex)
|
|
documentManager.setSideBySide(true)
|
|
} else {
|
|
documentManager.setSideBySide(false)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// ---------- Формат-тулбар (под вкладками) ----------
|
|
FormatToolbar {
|
|
id: formatToolbar
|
|
anchors.top: tabBar.bottom
|
|
anchors.left: parent.left
|
|
anchors.right: parent.right
|
|
height: 34
|
|
visible: documentManager.activeIndex >= 0
|
|
targetPane: activePane()
|
|
onTableRequested: { tableEditor.resetDialog(); tableEditor.open() }
|
|
}
|
|
|
|
// ---------- Редактор (заполняет остаток) ----------
|
|
RowLayout {
|
|
id: editorArea
|
|
anchors.top: formatToolbar.bottom
|
|
anchors.left: parent.left
|
|
anchors.right: parent.right
|
|
anchors.bottom: parent.bottom
|
|
spacing: 0
|
|
|
|
EditorPane {
|
|
id: primaryPane
|
|
Layout.fillWidth: true
|
|
docIndex: documentManager.activeIndex
|
|
canOpenBeside: true
|
|
onOpenBeside: {
|
|
documentManager.setSecondaryIndex(documentManager.activeIndex)
|
|
documentManager.setSideBySide(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)
|
|
}
|
|
}
|
|
|
|
TableEditor { id: tableEditor; onMarkdownReady: (md) => activePane().insertText(md) }
|
|
|
|
// ---------- Горячие клавиши ----------
|
|
Shortcut { sequence: "Ctrl+S"; onActivated: documentManager.saveAll() }
|
|
Shortcut { sequence: "Ctrl+W"; onActivated: documentManager.closeTab(documentManager.activeIndex) }
|
|
Shortcut { sequence: "Ctrl+E"; onActivated: primaryPane.editMode = !primaryPane.editMode }
|
|
Shortcut { sequence: "Ctrl+Tab"; onActivated: {
|
|
const n = documentManager.openTabs.length
|
|
if (n > 0) documentManager.setActiveIndex((documentManager.activeIndex + 1) % n)
|
|
}}
|
|
|
|
// ОТЛАДКА: видимый текст прямо в EditorPanel (z:1000)
|
|
Text {
|
|
z: 1000
|
|
anchors.top: editorArea.top
|
|
anchors.left: editorArea.left
|
|
anchors.right: editorArea.right
|
|
height: 200
|
|
text: documentManager.activeIndex >= 0
|
|
? "DEBUG CONTENT: " + documentManager.contentAt(documentManager.activeIndex).substring(0, 500)
|
|
: "NO FILE OPENED (activeIndex=" + documentManager.activeIndex + ")"
|
|
font.pixelSize: 16
|
|
color: "blue"
|
|
wrapMode: Text.Wrap
|
|
clip: true
|
|
Rectangle { anchors.fill: parent; color: "yellow"; z: -1 }
|
|
}
|
|
} |