3#include <QtGui/QClipboard>
4#include <QtGui/QGuiApplication>
17 : QStringListModel(parent)
20 qCDebug(MAVLinkConsoleControllerLog) <<
this;
23 &MAVLinkConsoleController::_setActiveVehicle);
32 _sendSerialData(msg,
true);
35 qCDebug(MAVLinkConsoleControllerLog) <<
this;
40 QString output = command;
43 const QStringList lines = output.split(
'\n');
44 for (
const QString& line : lines) {
45 if (!line.isEmpty()) {
46 _history.append(line);
50 (void) output.append(
"\n");
51 _sendSerialData(qPrintable(output));
57 QString clipboardData = command_pre + QGuiApplication::clipboard()->text();
59 const int lastLinePos = clipboardData.lastIndexOf(
'\n');
60 if (lastLinePos != -1) {
61 const QString commands = clipboardData.mid(0, lastLinePos);
63 clipboardData = clipboardData.mid(lastLinePos + 1);
69void MAVLinkConsoleController::_setActiveVehicle(
Vehicle* vehicle)
71 for (QMetaObject::Connection& con : _connections) {
72 (void) disconnect(con);
78 _incomingBuffer.clear();
80 setStringList(QStringList());
85 &MAVLinkConsoleController::_receiveData);
89void MAVLinkConsoleController::_receiveData(uint8_t device, uint8_t flags, uint16_t timeout, uint32_t baudrate,
90 const QByteArray& data)
96 if (device != SERIAL_CONTROL_DEV_SHELL) {
101 (void) _incomingBuffer.append(data);
103 while (!_incomingBuffer.isEmpty()) {
104 bool newline =
false;
106 int idx = _incomingBuffer.indexOf(
'\n');
109 idx = _incomingBuffer.size();
114 QByteArray fragment = _incomingBuffer.mid(0, idx);
115 if (!_processANSItext(fragment)) {
120 _writeLine(_cursorY, fragment);
125 const int rc = rowCount();
126 if (_cursorY >= rc) {
127 (void) insertRows(rc, 1 + _cursorY - rc);
131 (void) _incomingBuffer.remove(0, idx + (newline ? 1 : 0));
135void MAVLinkConsoleController::_sendSerialData(
const QByteArray& data,
bool close)
138 qCWarning(MAVLinkConsoleControllerLog) <<
"_sendSerialData called with no active vehicle";
148 QByteArray output(data);
149 while (output.size()) {
150 QByteArray chunk(output.left(MAVLINK_MSG_SERIAL_CONTROL_FIELD_DATA_LEN));
151 const int dataSize = chunk.size();
155 (void) chunk.append(MAVLINK_MSG_SERIAL_CONTROL_FIELD_DATA_LEN - chunk.size(),
'\0');
157 const uint8_t flags =
158 close ? 0 : SERIAL_CONTROL_FLAG_EXCLUSIVE | SERIAL_CONTROL_FLAG_RESPOND | SERIAL_CONTROL_FLAG_MULTI;
161 (void) mavlink_msg_serial_control_pack_chan(
163 &msg, SERIAL_CONTROL_DEV_SHELL, flags, 0, 0, dataSize,
reinterpret_cast<uint8_t*
>(chunk.data()),
167 (void) output.remove(0, chunk.size());
171bool MAVLinkConsoleController::_processANSItext(QByteArray& line)
174 for (
int i = 0; i <
line.size(); i++) {
175 if (line[i] !=
'\x1B') {
180 if ((i >= (
line.size() - 2)) || (line[i + 1] !=
'[')) {
186 switch (line[i + 2]) {
188 if (_cursorHomePos == -1) {
190 _cursorHomePos = _cursorY;
193 _cursorY = _cursorHomePos;
199 if (_cursorY < rowCount()) {
200 const QModelIndex idx = index(_cursorY);
201 QString updated = data(idx, Qt::DisplayRole).toString();
202 const int eraseIdx = _cursorX + i;
203 if (eraseIdx < updated.length()) {
204 (void) setData(idx, updated.remove(eraseIdx, updated.length()));
210 if (i >= (
line.size() - 3)) {
214 if ((line[i + 3] ==
'J') && (_cursorHomePos != -1)) {
216 const bool blocked = blockSignals(
true);
217 for (
int j = _cursorHomePos; j < rowCount(); j++) {
218 (void) setData(index(j),
"");
220 (void) blockSignals(blocked);
222 const QVector<int> roles({Qt::DisplayRole, Qt::EditRole});
223 emit dataChanged(index(_cursorY), index(rowCount()), roles);
227 (void)
line.remove(i + 3, 1);
234 (void)
line.remove(i, 3);
241QString MAVLinkConsoleController::_transformLineForRichText(
const QString& line)
const
243 QString ret =
line.toHtmlEscaped().replace(
" ",
" ").replace(
"\t",
" ");
245 if (ret.startsWith(
"WARN", Qt::CaseSensitive)) {
246 (void) ret.replace(0, 4,
"<font color=\"" + _palette->colorOrange().name() +
"\">WARN</font>");
247 }
else if (ret.startsWith(
"ERROR", Qt::CaseSensitive)) {
248 (void) ret.replace(0, 5,
"<font color=\"" + _palette->colorRed().name() +
"\">ERROR</font>");
254QString MAVLinkConsoleController::_getText()
const
257 if (rowCount() > 0) {
258 ret = _transformLineForRichText(data(index(0), Qt::DisplayRole).toString());
261 for (
int i = 1; i < rowCount(); ++i) {
262 ret += (
"<br>" + _transformLineForRichText(data(index(i), Qt::DisplayRole).toString()));
268void MAVLinkConsoleController::_writeLine(
int line,
const QByteArray& text)
270 const int rc = rowCount();
272 (void) insertRows(rc, 1 + line - rc);
275 if (rowCount() > kMaxNumLines) {
276 const int count = rowCount() - kMaxNumLines;
277 (void) removeRows(0, count);
280 _cursorHomePos -= count;
281 if (_cursorHomePos < 0) {
286 const QModelIndex idx = index(line);
287 QString updated = data(idx, Qt::DisplayRole).toString();
288 (void) updated.replace(_cursorX, text.size(), text);
289 (void) setData(idx, updated);
290 _cursorX += text.size();
293void MAVLinkConsoleController::CommandHistory::append(
const QString& command)
297 if ((_history.isEmpty()) || (_history.last() != command)) {
298 if (_history.length() >= CommandHistory::kMaxHistoryLength) {
299 _history.removeFirst();
301 _history.append(command);
305 _index = _history.length();
308QString MAVLinkConsoleController::CommandHistory::up(
const QString& current)
315 if (_index < _history.length()) {
316 return _history[_index];
319 return QStringLiteral(
"");
322QString MAVLinkConsoleController::CommandHistory::down(
const QString& current)
324 if (_index >= _history.length()) {
329 if (_index < _history.length()) {
330 return _history[_index];
333 return QStringLiteral(
"");
std::shared_ptr< LinkInterface > SharedLinkInterfacePtr
struct __mavlink_message mavlink_message_t
#define QGC_LOGGING_CATEGORY(name, categoryStr)
Q_INVOKABLE void sendCommand(const QString &command)
~MAVLinkConsoleController()
Q_INVOKABLE QString handleClipboard(const QString &command_pre)
static int getComponentId()
static MAVLinkProtocol * instance()
static MultiVehicleManager * instance()
void activeVehicleChanged(Vehicle *activeVehicle)
QGCPalette is used in QML ui to expose color properties for the QGC palette.
WeakLinkInterfacePtr primaryLink() const
VehicleLinkManager * vehicleLinkManager()
bool sendMessageOnLinkThreadSafe(LinkInterface *link, mavlink_message_t message)
int defaultComponentId() const
void mavlinkSerialControl(uint8_t device, uint8_t flags, uint16_t timeout, uint32_t baudrate, QByteArray data)
QByteArray line(std::string_view command)
command as one CR/LF-terminated line.
GPSCommandSequence::Command command(QByteArrayView body, GPSTextMatcher reply, std::chrono::milliseconds timeout)
body labelled by its text, framed as a sentence, and completed by reply within timeout.