From 97e3cfada0d599fe6121d92d52e4782fc02aed08 Mon Sep 17 00:00:00 2001 From: Adrian Kummerlaender Date: Sun, 21 Jun 2015 20:21:50 +0200 Subject: Initial commit of _MetaTerm_ UI prototype MetaTerm is a meta terminal in the sense that it allows launching multiple terminal shells and applications in a unified interface that is in itself reminiscent of a terminal shell. --- EmbeddedTerminal.qml | 86 ++++++++++++++++++++++++++++++++++++++++++++++++++++ MetaTerm.qml | 76 ++++++++++++++++++++++++++++++++++++++++++++++ ScrollBar.qml | 78 +++++++++++++++++++++++++++++++++++++++++++++++ TerminalItem.qml | 70 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 310 insertions(+) create mode 100644 EmbeddedTerminal.qml create mode 100644 MetaTerm.qml create mode 100644 ScrollBar.qml create mode 100644 TerminalItem.qml diff --git a/EmbeddedTerminal.qml b/EmbeddedTerminal.qml new file mode 100644 index 0000000..e02ba61 --- /dev/null +++ b/EmbeddedTerminal.qml @@ -0,0 +1,86 @@ +import QtQuick 2.0 +import QMLTermWidget 1.0 +import QtQuick.Controls 1.2 + +Item { + id: embeddedTerminal + property string program + property string workingDirectory + property int columns + property int lines + + width: container.width + height: container.height + + function focus() { terminal.forceActiveFocus() } + + Row { + id: container + + Rectangle { + id: highlighter + + width: 10 + height: terminal.height + + color: "#aadb0f" + + Behavior on opacity { + NumberAnimation { + duration: 300 + easing.type: Easing.OutCubic + } + } + + function focus() { opacity = 1 } + function unfocus() { opacity = 0 } + } + + Rectangle { + width: terminal.width + height: terminal.height + + color: "#ffffff" + + QMLTermWidget { + id: terminal + + font.family: "Monospace" + font.pointSize: 8 + + width: fontMetrics.width * embeddedTerminal.columns + height: fontMetrics.height * embeddedTerminal.lines + + session: QMLTermSession { + initialWorkingDirectory: embeddedTerminal.workingDirectory + + shellProgram: { + return (embeddedTerminal.program).split(" ")[0]; + } + + shellProgramArgs: { + var elements = (embeddedTerminal.program).split(" "); + elements.shift(); + + return elements; + } + } + + MouseArea { + anchors.fill: parent + acceptedButtons: Qt.LeftButton + onClicked: parent.forceActiveFocus(); + onWheel: { } + } + + onTermGetFocus: highlighter.focus() + onTermLostFocus: highlighter.unfocus() + + Component.onCompleted: { + terminal.forceActiveFocus(); + session.startShellProgram(); + } + } + } + } +} diff --git a/MetaTerm.qml b/MetaTerm.qml new file mode 100644 index 0000000..f95baa7 --- /dev/null +++ b/MetaTerm.qml @@ -0,0 +1,76 @@ +import QtQuick 2.0 +import QMLTermWidget 1.0 +import QtQuick.Controls 1.2 + +Rectangle { + anchors.fill: parent + + color: "#161616" + + Flickable { + id: terminalListFlickable + boundsBehavior: Flickable.StopAtBounds + width: 600 + anchors.fill: parent + + Column { + id: terminalList + spacing: 10 + + property int activeItem : 0 + + function createItem() { + var terminalItem = Qt.createComponent("TerminalItem.qml"); + var instantiateTerminal = function() { + var instance = terminalItem.createObject(terminalList, { + "width": terminalListFlickable.width + }); + instance.onExecuted.connect(createItem); + } + + if ( terminalItem.status == Component.Ready ) { + instantiateTerminal(); + } else { + terminalItem.statusChanged.connect(instantiateTerminal); + } + } + + function nextItem() { + if ( activeItem < (children.length - 1) ) { + children[++activeItem].focus(); + } + } + + function prevItem() { + if ( activeItem > 0 ) { + children[--activeItem].focus(); + } + } + + TerminalItem { + width: terminalListFlickable.width + onExecuted: terminalList.createItem() + } + } + + contentHeight: terminalList.height + contentWidth: terminalList.width + } + + Action { + id: nextTerminalAction + shortcut: "j" + onTriggered: terminalList.nextItem() + } + + Action { + id: prevTerminalAction + shortcut: "k" + onTriggered: terminalList.prevItem() + } + + ScrollBar { + flickable: terminalListFlickable + handleSize: 10 + } +} diff --git a/ScrollBar.qml b/ScrollBar.qml new file mode 100644 index 0000000..18f149c --- /dev/null +++ b/ScrollBar.qml @@ -0,0 +1,78 @@ +import QtQuick 2.0; + +Item { + id: scrollbar + width: (handleSize + 2) + visible: (flickable.visibleArea.heightRatio < 1.0) + + anchors { + top: flickable.top + right: flickable.right + bottom: flickable.bottom + } + + property Flickable flickable + property int handleSize + + Item { + id: bar + + anchors.fill: parent + + Rectangle { + anchors.fill: parent + color: "black" + opacity: 0.5 + } + + MouseArea { + id: control + anchors.fill: parent + + drag { + target: handle + minimumY: 0 + maximumY: (bar.height - handle.height) + axis: Drag.YAxis + } + + onClicked: { + flickable.contentY = (mouse.y / bar.height * (flickable.contentHeight - flickable.height)); + } + } + + Item { + id: handle; + height: Math.max(20, (flickable.visibleArea.heightRatio * bar.height)) + + anchors { + left: parent.left + right: parent.right + } + + Rectangle { + id: backHandle + anchors { + fill: parent + margins: 1 + } + + color: (control.pressed ? "gray" : "white") + } + } + } + + Binding { + target: handle + property: "y" + value: (flickable.contentY * control.drag.maximumY / (flickable.contentHeight - flickable.height)) + when: (!control.drag.active) + } + + Binding { + target: flickable + property: "contentY" + value: (handle.y * (flickable.contentHeight - flickable.height) / control.drag.maximumY) + when: (control.drag.active || control.pressed) + } +} diff --git a/TerminalItem.qml b/TerminalItem.qml new file mode 100644 index 0000000..9fce337 --- /dev/null +++ b/TerminalItem.qml @@ -0,0 +1,70 @@ +import QtQuick 2.0 +import QtQuick.Controls 1.2 +import QtQuick.Layouts 1.1 + +Item { + id: terminalItem + signal executed + + height: elementList.height + + function focus() { + if ( command.readOnly ) { + elementList.children[1].focus(); + } else { + command.forceActiveFocus(); + } + } + + Column { + id: elementList + + function createTerminal(program) { + var terminal = Qt.createComponent("EmbeddedTerminal.qml"); + var instantiateTerminal = function() { + terminal.createObject(elementList, { + "columns": 90, + "lines": 20, + "program": program, + "workingDirectory": "$HOME" + }); + } + + if ( terminal.status == Component.Ready ) { + instantiateTerminal(); + } else { + terminal.statusChanged.connect(instantiateTerminal); + } + } + + RowLayout { + width: terminalItem.width + + Text { + text: "> " + font.pointSize: 18 + color: "white" + } + + TextInput { + id: command + + font.pointSize: 18 + color: "white" + selectedTextColor: "#161616" + selectionColor: "white" + selectByMouse: true + + Layout.fillWidth: true + + onAccepted: { + if ( !readOnly ) { + readOnly = true; + elementList.createTerminal(text); + terminalItem.executed(); + } + } + } + } + } +} -- cgit v1.2.3