aboutsummaryrefslogtreecommitdiff
path: root/qml
diff options
context:
space:
mode:
Diffstat (limited to 'qml')
-rw-r--r--qml/EmbeddedTerminal.qml88
-rw-r--r--qml/ScrollBar.qml78
-rw-r--r--qml/TerminalItem.qml118
-rw-r--r--qml/main.qml168
-rw-r--r--qml/ui.qrc8
5 files changed, 460 insertions, 0 deletions
diff --git a/qml/EmbeddedTerminal.qml b/qml/EmbeddedTerminal.qml
new file mode 100644
index 0000000..f4f104e
--- /dev/null
+++ b/qml/EmbeddedTerminal.qml
@@ -0,0 +1,88 @@
+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 select() { highlighter.select() }
+ function deselect() { highlighter.deselect() }
+
+ Row {
+ id: container
+
+ Rectangle {
+ id: highlighter
+
+ width: 10
+ height: terminal.height
+
+ color: "#909636"
+
+ Behavior on opacity {
+ NumberAnimation {
+ duration: 300
+ easing.type: Easing.OutCubic
+ }
+ }
+
+ function select() { opacity = 1 }
+ function deselect() { opacity = 0 }
+ function focus() { color = "#352F6A" }
+ function unfocus() { color = "#909636" }
+ }
+
+ 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;
+ }
+ }
+
+ onTermGetFocus: highlighter.focus()
+ onTermLostFocus: highlighter.unfocus()
+
+ MouseArea {
+ anchors.fill: parent
+ acceptedButtons: Qt.NoButton
+ onWheel: { }
+ }
+
+ Component.onCompleted: {
+ terminal.forceActiveFocus();
+ session.startShellProgram();
+ }
+ }
+ }
+ }
+}
diff --git a/qml/ScrollBar.qml b/qml/ScrollBar.qml
new file mode 100644
index 0000000..18f149c
--- /dev/null
+++ b/qml/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/qml/TerminalItem.qml b/qml/TerminalItem.qml
new file mode 100644
index 0000000..6c19c45
--- /dev/null
+++ b/qml/TerminalItem.qml
@@ -0,0 +1,118 @@
+import QtQuick 2.0
+import QtQuick.Controls 1.2
+import QtQuick.Layouts 1.1
+
+Item {
+ id: terminalItem
+ signal executed
+
+ height: elementList.height
+
+ function select() {
+ if ( command.readOnly ) {
+ elementList.children[1].select();
+ } else {
+ highlighter.select();
+ }
+ }
+
+ function deselect() {
+ if ( command.readOnly ) {
+ elementList.children[1].deselect();
+ } else {
+ highlighter.deselect();
+ }
+ }
+
+ function forceActiveFocus() {
+ if ( command.readOnly ) {
+ scope.forceActiveFocus();
+ } else {
+ scope.forceActiveFocus();
+ highlighter.select();
+ highlighter.focus();
+ }
+ }
+
+ function unfocus() {
+ if ( !command.readOnly ) {
+ highlighter.unfocus();
+ }
+ }
+
+ FocusScope {
+ id: scope
+
+ Column {
+ id: elementList
+
+ function createTerminal(program) {
+ var terminal = Qt.createComponent("qrc:/EmbeddedTerminal.qml");
+ var instantiateTerminal = function() {
+ terminal.createObject(elementList, {
+ "columns": 90,
+ "lines": 20,
+ "program": program,
+ "workingDirectory": "$HOME",
+ "focus": true
+ });
+ }
+
+ if ( terminal.status === Component.Ready ) {
+ instantiateTerminal();
+ } else {
+ terminal.statusChanged.connect(instantiateTerminal);
+ }
+ }
+
+ RowLayout {
+ width: terminalItem.width
+
+ Rectangle {
+ id: highlighter
+
+ width: 10
+ height: command.height
+ opacity: 0
+
+ color: "#909636"
+
+ Behavior on opacity {
+ NumberAnimation {
+ duration: 300
+ easing.type: Easing.OutCubic
+ }
+ }
+
+ function select() { opacity = 1 }
+ function deselect() { opacity = 0 }
+ function focus() { color = "#352F6A" }
+ function unfocus() { color = "#909636" }
+ }
+
+ TextInput {
+ id: command
+
+ font.pointSize: 18
+ color: "white"
+ selectedTextColor: "#161616"
+ selectionColor: "white"
+ selectByMouse: true
+ focus: true
+
+ Layout.fillWidth: true
+
+ onAccepted: {
+ if ( !readOnly ) {
+ readOnly = true;
+ focus = false;
+ elementList.createTerminal(text);
+ terminalItem.executed();
+ highlighter.deselect();
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/qml/main.qml b/qml/main.qml
new file mode 100644
index 0000000..1e0db9d
--- /dev/null
+++ b/qml/main.qml
@@ -0,0 +1,168 @@
+import QtQuick 2.0
+import QtQuick.Window 2.0
+import QtQuick.Controls 1.2
+
+ApplicationWindow {
+ id: root
+
+ visible: true
+
+ color: "#161616"
+
+ Component.onCompleted: terminalList.focusCurrent()
+
+ Flickable {
+ id: terminalListFlickable
+ anchors.fill: parent
+
+ boundsBehavior: Flickable.StopAtBounds
+ contentHeight: terminalList.height
+ contentWidth: terminalList.width
+ pixelAligned: true
+
+ Column {
+ id: terminalList
+ spacing: 10
+
+ property int activeItem : 0
+
+ onHeightChanged: scrollTo(activeItem)
+
+ function createItem() {
+ var terminalItem = Qt.createComponent("qrc:/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 scrollTo(index) {
+ if ( terminalList.height >= terminalListFlickable.height ) {
+ var offset = children[index].y
+ + (children[index].height / 2)
+ - (terminalListFlickable.height / 2);
+
+ var bound = terminalList.height
+ - terminalListFlickable.height;
+
+ if ( offset < 0 ) {
+ terminalListFlickable.contentY = 0;
+ } else if ( offset >= bound ) {
+ terminalListFlickable.contentY = bound;
+ } else {
+ terminalListFlickable.contentY = offset;
+ }
+ }
+ }
+
+ function selectItem(index) {
+ children[activeItem].deselect();
+ children[index ].select();
+
+ activeItem = index;
+
+ scrollTo(index);
+ }
+
+ function selectNext() {
+ if ( activeItem < (children.length - 1) ) {
+ selectItem(activeItem + 1);
+ } else {
+ insertTerminalAction.trigger();
+ }
+ }
+
+ function selectPrev() {
+ if ( activeItem > 0 ) {
+ selectItem(activeItem - 1);
+ }
+ }
+
+ function focusCurrent() {
+ children[activeItem].forceActiveFocus();
+ }
+
+ function unfocusCurrent() {
+ children[activeItem].unfocus();
+ }
+
+ TerminalItem {
+ width: terminalListFlickable.width
+ onExecuted: terminalList.createItem()
+ }
+ }
+ }
+
+ Action {
+ id: insertTerminalAction
+ shortcut: "i"
+ enabled: false
+ onTriggered: {
+ escapeTerminalAction.enabled = true;
+ insertTerminalAction.enabled = false;
+ nextTerminalAction.enabled = false;
+ prevTerminalAction.enabled = false;
+ lastTerminalAction.enabled = false;
+ firstTerminalAction.enabled = false;
+
+ terminalList.focusCurrent();
+ }
+ }
+
+ Action {
+ id: escapeTerminalAction
+ shortcut: "Shift+ESC"
+ onTriggered: {
+ escapeTerminalAction.enabled = false;
+ insertTerminalAction.enabled = true;
+ nextTerminalAction.enabled = true;
+ prevTerminalAction.enabled = true;
+ lastTerminalAction.enabled = true;
+ firstTerminalAction.enabled = true;
+
+ terminalList.forceActiveFocus();
+ terminalList.unfocusCurrent();
+ }
+ }
+
+ Action {
+ id: nextTerminalAction
+ shortcut: "j"
+ enabled: false
+ onTriggered: terminalList.selectNext()
+ }
+
+ Action {
+ id: prevTerminalAction
+ shortcut: "k"
+ enabled: false
+ onTriggered: terminalList.selectPrev()
+ }
+
+ Action {
+ id: lastTerminalAction
+ shortcut: "Shift+G"
+ enabled: false
+ onTriggered: terminalList.selectItem(terminalList.children.length - 1)
+ }
+
+ Action {
+ id: firstTerminalAction
+ shortcut: "g"
+ enabled: false
+ onTriggered: terminalList.selectItem(0)
+ }
+
+ ScrollBar {
+ flickable: terminalListFlickable
+ handleSize: 10
+ }
+}
diff --git a/qml/ui.qrc b/qml/ui.qrc
new file mode 100644
index 0000000..8339fa2
--- /dev/null
+++ b/qml/ui.qrc
@@ -0,0 +1,8 @@
+<RCC>
+ <qresource prefix="/">
+ <file>main.qml</file>
+ <file>TerminalItem.qml</file>
+ <file>EmbeddedTerminal.qml</file>
+ <file>ScrollBar.qml</file>
+ </qresource>
+</RCC>