Add ClideEditorView.
This commit is contained in:
1
build.rs
1
build.rs
@@ -7,6 +7,7 @@ fn main() {
|
|||||||
"qml/ClideTreeView.qml",
|
"qml/ClideTreeView.qml",
|
||||||
"qml/ClideProjectView.qml",
|
"qml/ClideProjectView.qml",
|
||||||
"qml/ClideEditor.qml",
|
"qml/ClideEditor.qml",
|
||||||
|
"qml/ClideEditorView.qml",
|
||||||
"qml/ClideMenuBar.qml",
|
"qml/ClideMenuBar.qml",
|
||||||
"qml/ClideLogger.qml",
|
"qml/ClideLogger.qml",
|
||||||
"qml/Components/ClideScrollBar.qml",
|
"qml/Components/ClideScrollBar.qml",
|
||||||
|
|||||||
@@ -9,160 +9,128 @@ import QtQuick.Layouts
|
|||||||
import clide.module 1.0
|
import clide.module 1.0
|
||||||
import Logger 1.0
|
import Logger 1.0
|
||||||
|
|
||||||
SplitView {
|
RowLayout {
|
||||||
id: root
|
// We use a flickable to synchronize the position of the editor and
|
||||||
|
// the line numbers. This is necessary because the line numbers can
|
||||||
|
// extend the available height.
|
||||||
|
Flickable {
|
||||||
|
id: lineNumbers
|
||||||
|
|
||||||
// The path to the file to show in the text editor.
|
Layout.fillHeight: true
|
||||||
// This is updated by a signal caught within ClideProjectView.
|
Layout.fillWidth: false
|
||||||
// Initialized by the Default trait for the Rust QML singleton FileSystem.
|
// Calculating the width correctly is important as the number grows.
|
||||||
required property string filePath
|
// We need to ensure space required to show N line number digits.
|
||||||
|
// We use log10 to find how many digits are needed in a line number.
|
||||||
|
// log10(9) ~= .95; log10(10) = 1.0; log10(100) = 2.0 ...etc
|
||||||
|
// We +1 to ensure space for at least 1 digit, as floor(1.95) = 1.
|
||||||
|
// The +10 is additional spacing and can be adjusted.
|
||||||
|
Layout.preferredWidth: fontMetrics.averageCharacterWidth * (Math.floor(Math.log10(textArea.lineCount)) + 1) + 10
|
||||||
|
contentY: editorFlickable.contentY
|
||||||
|
interactive: false
|
||||||
|
|
||||||
Layout.fillHeight: true
|
Column {
|
||||||
Layout.fillWidth: true
|
anchors.fill: parent
|
||||||
orientation: Qt.Vertical
|
topPadding: textArea.topPadding
|
||||||
|
|
||||||
// Customized handle to drag between the Editor and the Console.
|
Repeater {
|
||||||
handle: ClideHandle {
|
id: repeatedLineNumbers
|
||||||
pressed: SplitHandle.pressed
|
|
||||||
hovered: SplitHandle.hovered
|
|
||||||
}
|
|
||||||
|
|
||||||
Component.onCompleted: {
|
// TODO: Bug where text wrapping shows as new line number.
|
||||||
// Show logging is working.
|
model: textArea.lineCount
|
||||||
Logger.info("Info logs");
|
|
||||||
Logger.warn("Warning logs");
|
|
||||||
Logger.debug("Debug logs");
|
|
||||||
Logger.error("Error logs");
|
|
||||||
Logger.trace("Trace logs");
|
|
||||||
}
|
|
||||||
|
|
||||||
RowLayout {
|
// This Item is used for each line number in the gutter.
|
||||||
// We use a flickable to synchronize the position of the editor and
|
delegate: Item {
|
||||||
// the line numbers. This is necessary because the line numbers can
|
required property int index
|
||||||
// extend the available height.
|
|
||||||
Flickable {
|
|
||||||
id: lineNumbers
|
|
||||||
|
|
||||||
Layout.fillHeight: true
|
// Calculates the height of each line in the text area.
|
||||||
Layout.fillWidth: false
|
height: textArea.contentHeight / textArea.lineCount
|
||||||
// Calculating the width correctly is important as the number grows.
|
width: parent.width
|
||||||
// We need to ensure space required to show N line number digits.
|
|
||||||
// We use log10 to find how many digits are needed in a line number.
|
|
||||||
// log10(9) ~= .95; log10(10) = 1.0; log10(100) = 2.0 ...etc
|
|
||||||
// We +1 to ensure space for at least 1 digit, as floor(1.95) = 1.
|
|
||||||
// The +10 is additional spacing and can be adjusted.
|
|
||||||
Layout.preferredWidth: fontMetrics.averageCharacterWidth * (Math.floor(Math.log10(textArea.lineCount)) + 1) + 10
|
|
||||||
contentY: editorFlickable.contentY
|
|
||||||
interactive: false
|
|
||||||
|
|
||||||
Column {
|
// Show the line number.
|
||||||
anchors.fill: parent
|
Label {
|
||||||
topPadding: textArea.topPadding
|
id: numbers
|
||||||
|
|
||||||
Repeater {
|
color: RustColors.linenumber
|
||||||
id: repeatedLineNumbers
|
font: textArea.font
|
||||||
|
height: parent.height
|
||||||
|
horizontalAlignment: Text.AlignLeft
|
||||||
|
text: parent.index + 1
|
||||||
|
verticalAlignment: Text.AlignVCenter
|
||||||
|
width: parent.width - indicator.width
|
||||||
|
|
||||||
// TODO: Bug where text wrapping shows as new line number.
|
background: Rectangle {
|
||||||
model: textArea.lineCount
|
color: RustColors.terminal_background
|
||||||
|
|
||||||
// This Item is used for each line number in the gutter.
|
|
||||||
delegate: Item {
|
|
||||||
required property int index
|
|
||||||
|
|
||||||
// Calculates the height of each line in the text area.
|
|
||||||
height: textArea.contentHeight / textArea.lineCount
|
|
||||||
width: parent.width
|
|
||||||
|
|
||||||
// Show the line number.
|
|
||||||
Label {
|
|
||||||
id: numbers
|
|
||||||
|
|
||||||
color: RustColors.linenumber
|
|
||||||
font: textArea.font
|
|
||||||
height: parent.height
|
|
||||||
horizontalAlignment: Text.AlignLeft
|
|
||||||
text: parent.index + 1
|
|
||||||
verticalAlignment: Text.AlignVCenter
|
|
||||||
width: parent.width - indicator.width
|
|
||||||
|
|
||||||
background: Rectangle {
|
|
||||||
color: RustColors.terminal_background
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// Draw edge along the right side of the line number.
|
}
|
||||||
Rectangle {
|
// Draw edge along the right side of the line number.
|
||||||
id: indicator
|
Rectangle {
|
||||||
|
id: indicator
|
||||||
|
|
||||||
anchors.left: numbers.right
|
anchors.left: numbers.right
|
||||||
color: RustColors.linenumber
|
color: RustColors.linenumber
|
||||||
height: parent.height
|
height: parent.height
|
||||||
width: 1
|
width: 1
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Flickable {
|
}
|
||||||
id: editorFlickable
|
Flickable {
|
||||||
|
id: editorFlickable
|
||||||
|
|
||||||
Layout.fillHeight: true
|
Layout.fillHeight: true
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
boundsBehavior: Flickable.StopAtBounds
|
boundsBehavior: Flickable.StopAtBounds
|
||||||
height: 650
|
height: 650
|
||||||
|
|
||||||
ScrollBar.horizontal: ClideScrollBar {
|
ScrollBar.horizontal: ClideScrollBar {
|
||||||
}
|
}
|
||||||
ScrollBar.vertical: ClideScrollBar {
|
ScrollBar.vertical: ClideScrollBar {
|
||||||
}
|
}
|
||||||
TextArea.flickable: TextArea {
|
TextArea.flickable: TextArea {
|
||||||
id: textArea
|
id: textArea
|
||||||
|
|
||||||
antialiasing: true
|
antialiasing: true
|
||||||
focus: true
|
focus: true
|
||||||
persistentSelection: true
|
persistentSelection: true
|
||||||
selectByMouse: true
|
selectByMouse: true
|
||||||
selectedTextColor: RustColors.editor_highlighted_text
|
selectedTextColor: RustColors.editor_highlighted_text
|
||||||
selectionColor: RustColors.editor_highlight
|
selectionColor: RustColors.editor_highlight
|
||||||
text: FileSystem.readFile(root.filePath)
|
text: FileSystem.readFile(root.filePath)
|
||||||
textFormat: Qt.AutoText
|
textFormat: Qt.AutoText
|
||||||
wrapMode: TextArea.Wrap
|
wrapMode: TextArea.Wrap
|
||||||
|
|
||||||
onLinkActivated: function (link) {
|
onLinkActivated: function (link) {
|
||||||
Qt.openUrlExternally(link);
|
Qt.openUrlExternally(link);
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Handle saving
|
|
||||||
// Component.onCompleted: {
|
|
||||||
// if (Qt.application.arguments.length === 2)
|
|
||||||
// textDocument.source = "file:" + Qt.application.arguments[1]
|
|
||||||
// else
|
|
||||||
// textDocument.source = "qrc:/texteditor.html"
|
|
||||||
// }
|
|
||||||
// textDocument.onStatusChanged: {
|
|
||||||
// // a message lookup table using computed properties:
|
|
||||||
// // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Object_initializer
|
|
||||||
// const statusMessages = {
|
|
||||||
// [ TextDocument.ReadError ]: qsTr("Failed to load “%1”"),
|
|
||||||
// [ TextDocument.WriteError ]: qsTr("Failed to save “%1”"),
|
|
||||||
// [ TextDocument.NonLocalFileError ]: qsTr("Not a local file: “%1”"),
|
|
||||||
// }
|
|
||||||
// const err = statusMessages[textDocument.status]
|
|
||||||
// if (err) {
|
|
||||||
// errorDialog.text = err.arg(textDocument.source)
|
|
||||||
// errorDialog.open()
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
FontMetrics {
|
// TODO: Handle saving
|
||||||
id: fontMetrics
|
// Component.onCompleted: {
|
||||||
|
// if (Qt.application.arguments.length === 2)
|
||||||
|
// textDocument.source = "file:" + Qt.application.arguments[1]
|
||||||
|
// else
|
||||||
|
// textDocument.source = "qrc:/texteditor.html"
|
||||||
|
// }
|
||||||
|
// textDocument.onStatusChanged: {
|
||||||
|
// // a message lookup table using computed properties:
|
||||||
|
// // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Object_initializer
|
||||||
|
// const statusMessages = {
|
||||||
|
// [ TextDocument.ReadError ]: qsTr("Failed to load “%1”"),
|
||||||
|
// [ TextDocument.WriteError ]: qsTr("Failed to save “%1”"),
|
||||||
|
// [ TextDocument.NonLocalFileError ]: qsTr("Not a local file: “%1”"),
|
||||||
|
// }
|
||||||
|
// const err = statusMessages[textDocument.status]
|
||||||
|
// if (err) {
|
||||||
|
// errorDialog.text = err.arg(textDocument.source)
|
||||||
|
// errorDialog.open()
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
font: textArea.font
|
FontMetrics {
|
||||||
}
|
id: fontMetrics
|
||||||
|
|
||||||
|
font: textArea.font
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ClideLogger {
|
|
||||||
id: areaConsole
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
46
qml/ClideEditorView.qml
Normal file
46
qml/ClideEditorView.qml
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
// SPDX-FileCopyrightText: 2026, Shaun Reed <shaunrd0@gmail.com>
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: GNU General Public License v3.0 or later
|
||||||
|
|
||||||
|
import QtQuick
|
||||||
|
import QtQuick.Controls
|
||||||
|
import QtQuick.Layouts
|
||||||
|
|
||||||
|
import clide.module 1.0
|
||||||
|
import Logger 1.0
|
||||||
|
|
||||||
|
SplitView {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
// The path to the file to show in the text editor.
|
||||||
|
// This is updated by a signal caught within ClideProjectView.
|
||||||
|
// Initialized by the Default trait for the Rust QML singleton FileSystem.
|
||||||
|
required property string filePath
|
||||||
|
|
||||||
|
Layout.fillHeight: true
|
||||||
|
Layout.fillWidth: true
|
||||||
|
orientation: Qt.Vertical
|
||||||
|
|
||||||
|
// Customized handle to drag between the Editor and the Console.
|
||||||
|
handle: ClideHandle {
|
||||||
|
pressed: SplitHandle.pressed
|
||||||
|
hovered: SplitHandle.hovered
|
||||||
|
}
|
||||||
|
|
||||||
|
Component.onCompleted: {
|
||||||
|
// Show logging is working.
|
||||||
|
Logger.info("Info logs");
|
||||||
|
Logger.warn("Warning logs");
|
||||||
|
Logger.debug("Debug logs");
|
||||||
|
Logger.error("Error logs");
|
||||||
|
Logger.trace("Trace logs");
|
||||||
|
}
|
||||||
|
|
||||||
|
ClideEditor{
|
||||||
|
id: clideEditor
|
||||||
|
}
|
||||||
|
ClideLogger {
|
||||||
|
id: areaConsole
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -100,7 +100,7 @@ SplitView {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ClideEditor {
|
ClideEditorView {
|
||||||
id: clideEditor
|
id: clideEditor
|
||||||
|
|
||||||
SplitView.fillWidth: true
|
SplitView.fillWidth: true
|
||||||
|
|||||||
Reference in New Issue
Block a user