6import QGroundControl.Controls
10 pageComponent: pageComponent
11 pageDescription: qsTr("Provides a connection to the vehicle's system shell.")
14 property bool isLoaded: false
16 // Key input on mobile is handled differently, so use a separate command input text field.
17 // E.g. for android see https://bugreports.qt.io/browse/QTBUG-40803
18 readonly property bool _separateCommandInput: ScreenTools.isMobile
20 MAVLinkConsoleController { id: conController }
26 height: availableHeight
28 property int _consoleOutputLen: 0
30 function scrollToBottom() {
31 if (flickable.contentHeight > flickable.height) {
32 flickable.contentY = flickable.contentHeight - flickable.height
36 function getCommand() { return textConsole.getText(_consoleOutputLen, textConsole.length) }
38 function getCommandAndClear() {
39 const command = getCommand()
40 textConsole.remove(_consoleOutputLen, textConsole.length)
44 function pasteFromClipboard() {
45 // we need to handle a few cases here:
46 // in the general form we have: <command_pre><cursor><command_post>
47 // and the clipboard may contain newlines
48 const cursor = textConsole.cursorPosition - _consoleOutputLen
49 var command = getCommandAndClear()
51 var command_post = command
53 command_pre = command.substr(0, cursor)
54 command_post = command.substr(cursor)
56 var command_leftover = conController.handleClipboard(command_pre) + command_post
57 textConsole.insert(textConsole.length, command_leftover)
58 textConsole.cursorPosition = textConsole.length - command_post.length
63 function onDataChanged(topLeft, bottomRight, roles) {
65 // rate-limit updates to reduce CPU load
77 // only update if scroll bar is at the bottom
78 if (flickable.atYEnd) {
79 // backup & restore cursor & command
80 const command = getCommand()
81 const cursor = textConsole.cursorPosition - _consoleOutputLen
82 textConsole.text = conController.text
83 _consoleOutputLen = textConsole.length
84 textConsole.insert(textConsole.length, command)
85 textConsole.cursorPosition = textConsole.length
88 // We could restore the selection here too...
89 textConsole.cursorPosition = _consoleOutputLen + cursor
99 Layout.fillWidth: true
100 Layout.fillHeight: true
101 contentWidth: textConsole.width
102 contentHeight: textConsole.height
104 TextArea.flickable: TextArea {
106 width: availableWidth
107 wrapMode: Text.WordWrap
108 readOnly: _separateCommandInput
109 textFormat: TextEdit.RichText
110 inputMethodHints: Qt.ImhNoAutoUppercase | Qt.ImhMultiLine
114 selectedTextColor: qgcPal.windowShade
115 selectionColor: qgcPal.text
116 font.pointSize: ScreenTools.defaultFontPointSize
117 font.family: ScreenTools.fixedFontFamily
119 Component.onCompleted: {
121 _consoleOutputLen = textConsole.length
122 textConsole.cursorPosition = _consoleOutputLen
123 if (!_separateCommandInput) {
124 textConsole.forceActiveFocus()
128 background: Rectangle { color: qgcPal.windowShade }
130 Keys.onPressed: (event) => {
132 if (event.key == Qt.Key_Tab) {
133 event.accepted = true
137 if (event.matches(StandardKey.Cut)) {
138 event.accepted = true
141 if (!event.matches(StandardKey.Copy) &&
142 event.key != Qt.Key_Escape &&
143 event.key != Qt.Key_Insert &&
144 event.key != Qt.Key_Pause &&
145 event.key != Qt.Key_Print &&
146 event.key != Qt.Key_SysReq &&
147 event.key != Qt.Key_Clear &&
148 event.key != Qt.Key_Home &&
149 event.key != Qt.Key_End &&
150 event.key != Qt.Key_Left &&
151 event.key != Qt.Key_Up &&
152 event.key != Qt.Key_Right &&
153 event.key != Qt.Key_Down &&
154 event.key != Qt.Key_PageUp &&
155 event.key != Qt.Key_PageDown &&
156 event.key != Qt.Key_Shift &&
157 event.key != Qt.Key_Control &&
158 event.key != Qt.Key_Meta &&
159 event.key != Qt.Key_Alt &&
160 event.key != Qt.Key_AltGr &&
161 event.key != Qt.Key_CapsLock &&
162 event.key != Qt.Key_NumLock &&
163 event.key != Qt.Key_ScrollLock &&
164 event.key != Qt.Key_Super_L &&
165 event.key != Qt.Key_Super_R &&
166 event.key != Qt.Key_Menu &&
167 event.key != Qt.Key_Hyper_L &&
168 event.key != Qt.Key_Hyper_R &&
169 event.key != Qt.Key_Direction_L &&
170 event.key != Qt.Key_Direction_R) {
171 // Note: dead keys do not generate keyPressed event on linux, see
172 // https://bugreports.qt.io/browse/QTBUG-79216
176 // ensure cursor position is at an editable region
177 if (textConsole.selectionStart < _consoleOutputLen) {
178 textConsole.select(_consoleOutputLen, textConsole.selectionEnd)
181 if (textConsole.cursorPosition < _consoleOutputLen) {
182 textConsole.cursorPosition = textConsole.length
188 // don't move beyond current command
189 if (textConsole.cursorPosition == _consoleOutputLen) {
190 event.accepted = true
193 case Qt.Key_Backspace:
194 if (textConsole.cursorPosition <= _consoleOutputLen) {
195 event.accepted = true
200 conController.sendCommand(getCommandAndClear())
201 event.accepted = true
207 if (event.matches(StandardKey.Paste)) {
209 event.accepted = true
213 if (event.key == Qt.Key_Up) {
214 const command = conController.historyUp(getCommandAndClear())
215 textConsole.insert(textConsole.length, command)
216 textConsole.cursorPosition = textConsole.length
217 event.accepted = true
218 } else if (event.key == Qt.Key_Down) {
219 const command = conController.historyDown(getCommandAndClear())
220 textConsole.insert(textConsole.length, command)
221 textConsole.cursorPosition = textConsole.length
222 event.accepted = true
229 Layout.fillWidth: true
230 visible: _separateCommandInput
234 Layout.fillWidth: true
235 placeholderText: qsTr("Enter Commands here...")
236 inputMethodHints: Qt.ImhNoAutoUppercase
237 onAccepted: sendCommand()
239 function sendCommand() {
240 conController.sendCommand(text)
249 onClicked: commandInput.sendCommand()