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 objectName: "mavlinkConsole_page"
27 height: availableHeight
29 property int _consoleOutputLen: 0
31 function scrollToBottom() {
32 if (flickable.contentHeight > flickable.height) {
33 flickable.contentY = flickable.contentHeight - flickable.height
37 function getCommand() { return textConsole.getText(_consoleOutputLen, textConsole.length) }
39 function getCommandAndClear() {
40 const command = getCommand()
41 textConsole.remove(_consoleOutputLen, textConsole.length)
45 function pasteFromClipboard() {
46 // we need to handle a few cases here:
47 // in the general form we have: <command_pre><cursor><command_post>
48 // and the clipboard may contain newlines
49 const cursor = textConsole.cursorPosition - _consoleOutputLen
50 var command = getCommandAndClear()
52 var command_post = command
54 command_pre = command.substr(0, cursor)
55 command_post = command.substr(cursor)
57 var command_leftover = conController.handleClipboard(command_pre) + command_post
58 textConsole.insert(textConsole.length, command_leftover)
59 textConsole.cursorPosition = textConsole.length - command_post.length
64 function onDataChanged(topLeft, bottomRight, roles) {
66 // rate-limit updates to reduce CPU load
78 // only update if scroll bar is at the bottom
79 if (flickable.atYEnd) {
80 // backup & restore cursor & command
81 const command = getCommand()
82 const cursor = textConsole.cursorPosition - _consoleOutputLen
83 textConsole.text = conController.text
84 _consoleOutputLen = textConsole.length
85 textConsole.insert(textConsole.length, command)
86 textConsole.cursorPosition = textConsole.length
89 // We could restore the selection here too...
90 textConsole.cursorPosition = _consoleOutputLen + cursor
100 Layout.fillWidth: true
101 Layout.fillHeight: true
102 contentWidth: textConsole.width
103 contentHeight: textConsole.height
105 TextArea.flickable: TextArea {
107 objectName: "mavlinkConsole_textArea"
108 width: availableWidth
109 wrapMode: Text.WordWrap
110 readOnly: _separateCommandInput
111 textFormat: TextEdit.RichText
112 inputMethodHints: Qt.ImhNoAutoUppercase | Qt.ImhMultiLine
116 selectedTextColor: qgcPal.windowShade
117 selectionColor: qgcPal.text
118 font.pointSize: ScreenTools.defaultFontPointSize
119 font.family: ScreenTools.fixedFontFamily
121 Component.onCompleted: {
123 _consoleOutputLen = textConsole.length
124 textConsole.cursorPosition = _consoleOutputLen
125 if (!_separateCommandInput) {
126 textConsole.forceActiveFocus()
130 background: Rectangle { color: qgcPal.windowShade }
132 Keys.onPressed: (event) => {
134 if (event.key == Qt.Key_Tab) {
135 event.accepted = true
139 if (event.matches(StandardKey.Cut)) {
140 event.accepted = true
143 if (!event.matches(StandardKey.Copy) &&
144 event.key != Qt.Key_Escape &&
145 event.key != Qt.Key_Insert &&
146 event.key != Qt.Key_Pause &&
147 event.key != Qt.Key_Print &&
148 event.key != Qt.Key_SysReq &&
149 event.key != Qt.Key_Clear &&
150 event.key != Qt.Key_Home &&
151 event.key != Qt.Key_End &&
152 event.key != Qt.Key_Left &&
153 event.key != Qt.Key_Up &&
154 event.key != Qt.Key_Right &&
155 event.key != Qt.Key_Down &&
156 event.key != Qt.Key_PageUp &&
157 event.key != Qt.Key_PageDown &&
158 event.key != Qt.Key_Shift &&
159 event.key != Qt.Key_Control &&
160 event.key != Qt.Key_Meta &&
161 event.key != Qt.Key_Alt &&
162 event.key != Qt.Key_AltGr &&
163 event.key != Qt.Key_CapsLock &&
164 event.key != Qt.Key_NumLock &&
165 event.key != Qt.Key_ScrollLock &&
166 event.key != Qt.Key_Super_L &&
167 event.key != Qt.Key_Super_R &&
168 event.key != Qt.Key_Menu &&
169 event.key != Qt.Key_Hyper_L &&
170 event.key != Qt.Key_Hyper_R &&
171 event.key != Qt.Key_Direction_L &&
172 event.key != Qt.Key_Direction_R) {
173 // Note: dead keys do not generate keyPressed event on linux, see
174 // https://bugreports.qt.io/browse/QTBUG-79216
178 // ensure cursor position is at an editable region
179 if (textConsole.selectionStart < _consoleOutputLen) {
180 textConsole.select(_consoleOutputLen, textConsole.selectionEnd)
183 if (textConsole.cursorPosition < _consoleOutputLen) {
184 textConsole.cursorPosition = textConsole.length
190 // don't move beyond current command
191 if (textConsole.cursorPosition == _consoleOutputLen) {
192 event.accepted = true
195 case Qt.Key_Backspace:
196 if (textConsole.cursorPosition <= _consoleOutputLen) {
197 event.accepted = true
202 conController.sendCommand(getCommandAndClear())
203 event.accepted = true
209 if (event.matches(StandardKey.Paste)) {
211 event.accepted = true
215 if (event.key == Qt.Key_Up) {
216 const command = conController.historyUp(getCommandAndClear())
217 textConsole.insert(textConsole.length, command)
218 textConsole.cursorPosition = textConsole.length
219 event.accepted = true
220 } else if (event.key == Qt.Key_Down) {
221 const command = conController.historyDown(getCommandAndClear())
222 textConsole.insert(textConsole.length, command)
223 textConsole.cursorPosition = textConsole.length
224 event.accepted = true
231 Layout.fillWidth: true
232 visible: _separateCommandInput
236 Layout.fillWidth: true
237 placeholderText: qsTr("Enter Commands here...")
238 inputMethodHints: Qt.ImhNoAutoUppercase
239 onAccepted: sendCommand()
241 function sendCommand() {
242 conController.sendCommand(text)
251 onClicked: commandInput.sendCommand()