diff --git a/README.md b/README.md
index 75ff1d6..3ce0f9e 100644
--- a/README.md
+++ b/README.md
@@ -1,9 +1,9 @@
QtSerialMonitor
-
-
-
+
+
+
@@ -12,10 +12,10 @@ Universal serial monitor with data plotting capabilities, based on [Qt](https://
**Features:**
-
- In/out serial data terminal with command history,
- UDP network protocol support,
-- Advanced data plotter with multiple graphs support and basic data filtering - uses [QCustomPlot](https://www.qcustomplot.com/),
+- Resizable UI widgets,
+- Data plotter with multiple graphs support and basic data filtering - uses [QCustomPlot](https://www.qcustomplot.com/),
- Printer support, ability to save graph as image,
- Read/write ".txt" data logs,
- many more...
@@ -26,14 +26,12 @@ Universal serial monitor with data plotting capabilities, based on [Qt](https://
**Work in progress:**
-
+ - Linux compatibility
- 3D Orientation Demo - for IMU testing (user will be able to toggle between chart view
and a simple 3D scene containing an object rotating accordingly to received roll,
pitch and yaw values, representing the sensor's orientation),
- - "What’s this ?" popups for less obvious widgets,
-
- Improvements, fixes etc.
----
diff --git a/src/QtSerialMonitor.pro b/src/QtSerialMonitor.pro
index dc97911..e197e52 100644
--- a/src/QtSerialMonitor.pro
+++ b/src/QtSerialMonitor.pro
@@ -30,7 +30,9 @@ DEFINES += QT_DEPRECATED_WARNINGS
CONFIG += c++11
SOURCES += \
+ codeeditor.cpp \
filereader.cpp \
+ highlighter.cpp \
infodialog.cpp \
logger.cpp \
main.cpp \
@@ -42,8 +44,10 @@ SOURCES += \
HEADERS += \
../../../../../../Downloads/QCustomPlot.tar/qcustomplot/qcustomplot.h \
+ codeeditor.h \
config.h \
filereader.h \
+ highlighter.h \
infodialog.h \
logger.h \
mainwindow.h \
@@ -64,7 +68,8 @@ else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target
DISTFILES += \
- QtSM.ico
+ QtSM.ico \
+ TODO
RESOURCES += \
3dres.qrc
diff --git a/src/TODO b/src/TODO
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/src/TODO
@@ -0,0 +1 @@
+
diff --git a/src/codeeditor.cpp b/src/codeeditor.cpp
new file mode 100644
index 0000000..eedf64f
--- /dev/null
+++ b/src/codeeditor.cpp
@@ -0,0 +1,147 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include
+#include "codeeditor.h"
+
+CodeEditor::CodeEditor(QWidget *parent) : QPlainTextEdit(parent)
+{
+ lineNumberArea = new LineNumberArea(this);
+
+ connect(this, &CodeEditor::blockCountChanged, this, &CodeEditor::updateLineNumberAreaWidth);
+ connect(this, &CodeEditor::updateRequest, this, &CodeEditor::updateLineNumberArea);
+ connect(this, &CodeEditor::cursorPositionChanged, this, &CodeEditor::highlightCurrentLine);
+
+ updateLineNumberAreaWidth(0);
+}
+
+int CodeEditor::lineNumberAreaWidth()
+{
+ int digits = 1;
+ int max = qMax(1, blockCount());
+
+ while (max >= 10)
+ {
+ max /= 10;
+ ++digits;
+ }
+
+ int space = 10 + fontMetrics().horizontalAdvance(" ") * digits;
+
+ return space;
+}
+
+void CodeEditor::updateLineNumberAreaWidth(int /* newBlockCount */)
+{
+ setViewportMargins(lineNumberAreaWidth(), 0, 0, 0);
+}
+
+void CodeEditor::updateLineNumberArea(const QRect &rect, int dy)
+{
+ if (dy)
+ lineNumberArea->scroll(0, dy);
+ else
+ lineNumberArea->update(0, rect.y(), lineNumberArea->width(), rect.height());
+
+ if (rect.contains(viewport()->rect()))
+ updateLineNumberAreaWidth(0);
+}
+
+void CodeEditor::resizeEvent(QResizeEvent *e)
+{
+ QPlainTextEdit::resizeEvent(e);
+
+ QRect cr = contentsRect();
+ lineNumberArea->setGeometry(QRect(cr.left(), cr.top(), lineNumberAreaWidth(), cr.height()));
+}
+
+void CodeEditor::highlightCurrentLine()
+{
+ QList extraSelections;
+ QTextEdit::ExtraSelection selection;
+ QColor lineColor = QColor(Qt::yellow).lighter(160);
+
+ selection.format.setBackground(lineColor);
+ selection.format.setProperty(QTextFormat::FullWidthSelection, true);
+ selection.cursor = textCursor();
+ selection.cursor.clearSelection();
+ extraSelections.append(selection);
+
+ setExtraSelections(extraSelections);
+
+ selection.cursor.clearSelection();
+
+}
+
+void CodeEditor::lineNumberAreaPaintEvent(QPaintEvent *event)
+{
+ QPainter painter(lineNumberArea);
+ painter.fillRect(event->rect(), Qt::lightGray);
+
+ QTextBlock block = firstVisibleBlock();
+ int blockNumber = block.blockNumber();
+ int top = (int)blockBoundingGeometry(block).translated(contentOffset()).top();
+ int bottom = top + (int)blockBoundingRect(block).height();
+
+ while (block.isValid() && top <= event->rect().bottom())
+ {
+ if (block.isVisible() && bottom >= event->rect().top())
+ {
+ QString number = QString::number(blockNumber + 1);
+ painter.setPen(Qt::black);
+ painter.drawText(0, top, lineNumberArea->width(), fontMetrics().height(), Qt::AlignLeft, number);
+ }
+
+ block = block.next();
+ top = bottom;
+ bottom = top + (int)blockBoundingRect(block).height();
+ ++blockNumber;
+ }
+}
diff --git a/src/codeeditor.h b/src/codeeditor.h
new file mode 100644
index 0000000..ee33a3a
--- /dev/null
+++ b/src/codeeditor.h
@@ -0,0 +1,60 @@
+#ifndef CODEEDITOR_H
+#define CODEEDITOR_H
+
+#include
+
+QT_BEGIN_NAMESPACE
+class QPaintEvent;
+class QResizeEvent;
+class QSize;
+class QWidget;
+QT_END_NAMESPACE
+
+class LineNumberArea;
+
+class CodeEditor : public QPlainTextEdit
+{
+ Q_OBJECT
+
+public:
+ CodeEditor(QWidget *parent = nullptr);
+
+ void lineNumberAreaPaintEvent(QPaintEvent *event);
+ int lineNumberAreaWidth();
+
+protected:
+ void resizeEvent(QResizeEvent *event) override;
+
+private slots:
+ void updateLineNumberAreaWidth(int newBlockCount);
+ void highlightCurrentLine();
+ void updateLineNumberArea(const QRect &, int);
+
+private:
+ QWidget *lineNumberArea;
+};
+
+class LineNumberArea : public QWidget
+{
+public:
+ LineNumberArea(CodeEditor *editor) : QWidget(editor)
+ {
+ codeEditor = editor;
+ }
+
+ QSize sizeHint() const override
+ {
+ return QSize(codeEditor->lineNumberAreaWidth(), 0);
+ }
+
+protected:
+ void paintEvent(QPaintEvent *event) override
+ {
+ codeEditor->lineNumberAreaPaintEvent(event);
+ }
+
+private:
+ CodeEditor *codeEditor;
+};
+
+#endif
diff --git a/src/config.h b/src/config.h
index dba2bed..96ef134 100644
--- a/src/config.h
+++ b/src/config.h
@@ -1,7 +1,7 @@
#ifndef CONFIG_H
#define CONFIG_H
-#define VERSION "1.2"
+#define VERSION "1.3"
#define CHANGELOG_TEXT "" //"Changelog - version " VERSION ": \n"
@@ -9,4 +9,8 @@
"Welcome to QtSerialMonitor, \n" \
"Press F1 to activate \"What's this\" mode. In this mode, clicked widget \r" \
"will display an explanation about its function. \n"
+
+#define RADIO_BUTTON_UPDATE_SERIAL_DEVICES_ON_INTERVAL 100
+#define SERIAL_DEVICE_CHECK_TIMER_INTERVAL 500
+
#endif // CONFIG_H
diff --git a/src/highlighter.cpp b/src/highlighter.cpp
new file mode 100644
index 0000000..7051eac
--- /dev/null
+++ b/src/highlighter.cpp
@@ -0,0 +1,141 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "highlighter.h"
+
+Highlighter::Highlighter(QTextDocument *parent) : QSyntaxHighlighter(parent)
+{
+ HighlightingRule rule;
+
+ keywordFormat.setForeground(Qt::darkBlue);
+ keywordFormat.setFontWeight(QFont::Bold);
+ // const QString keywordPatterns[] = {
+ // QStringLiteral("\\bchar\\b"), QStringLiteral("\\bclass\\b"), QStringLiteral("\\bconst\\b"),
+ // QStringLiteral("\\bdouble\\b"), QStringLiteral("\\benum\\b"), QStringLiteral("\\bexplicit\\b"),
+ // QStringLiteral("\\bfriend\\b"), QStringLiteral("\\binline\\b"), QStringLiteral("\\bint\\b"),
+ // QStringLiteral("\\blong\\b"), QStringLiteral("\\bnamespace\\b"), QStringLiteral("\\boperator\\b"),
+ // QStringLiteral("\\bprivate\\b"), QStringLiteral("\\bprotected\\b"), QStringLiteral("\\bpublic\\b"),
+ // QStringLiteral("\\bshort\\b"), QStringLiteral("\\bsignals\\b"), QStringLiteral("\\bsigned\\b"),
+ // QStringLiteral("\\bslots\\b"), QStringLiteral("\\bstatic\\b"), QStringLiteral("\\bstruct\\b"),
+ // QStringLiteral("\\btemplate\\b"), QStringLiteral("\\btypedef\\b"), QStringLiteral("\\btypename\\b"),
+ // QStringLiteral("\\bunion\\b"), QStringLiteral("\\bunsigned\\b"), QStringLiteral("\\bvirtual\\b"),
+ // QStringLiteral("\\bvoid\\b"), QStringLiteral("\\bvolatile\\b"), QStringLiteral("\\bbool\\b")
+ // };
+ // for (const QString &pattern : keywordPatterns) {
+ // rule.pattern = QRegularExpression(pattern);
+ // rule.format = keywordFormat;
+ // highlightingRules.append(rule);
+ // }
+
+ classFormat.setFontWeight(QFont::Bold);
+ classFormat.setForeground(Qt::darkMagenta);
+ rule.pattern = QRegularExpression(QStringLiteral("\\bQ[A-Za-z]+\\b"));
+ rule.format = classFormat;
+ highlightingRules.append(rule);
+
+ singleLineCommentFormat.setForeground(Qt::red);
+ rule.pattern = QRegularExpression(QStringLiteral("//[^\n]*"));
+ rule.format = singleLineCommentFormat;
+ highlightingRules.append(rule);
+
+ multiLineCommentFormat.setForeground(Qt::red);
+
+ quotationFormat.setForeground(Qt::darkGreen);
+ rule.pattern = QRegularExpression(QStringLiteral("\".*\""));
+ rule.format = quotationFormat;
+ highlightingRules.append(rule);
+
+ functionFormat.setFontItalic(true);
+ functionFormat.setForeground(Qt::blue);
+ rule.pattern = QRegularExpression(QStringLiteral("\\b[A-Za-z0-9_]+(?=\\()"));
+ rule.format = functionFormat;
+ highlightingRules.append(rule);
+
+ commentStartExpression = QRegularExpression(QStringLiteral("/\\*"));
+ commentEndExpression = QRegularExpression(QStringLiteral("\\*/"));
+}
+
+void Highlighter::highlightBlock(const QString &text)
+{
+ for (const HighlightingRule &rule : qAsConst(highlightingRules))
+ {
+ QRegularExpressionMatchIterator matchIterator = rule.pattern.globalMatch(text, 0,
+ QRegularExpression::MatchType::PartialPreferCompleteMatch,
+ QRegularExpression::MatchOption::NoMatchOption);
+ if (matchIterator.hasNext())
+ {
+ QRegularExpressionMatch match = matchIterator.next();
+ setFormat(match.capturedStart(), match.capturedLength(), rule.format);
+ }
+ }
+ setCurrentBlockState(0);
+
+ int startIndex = 0;
+ if (previousBlockState() != 1)
+ startIndex = text.indexOf(commentStartExpression);
+
+ while (startIndex >= 0)
+ {
+ QRegularExpressionMatch match = commentEndExpression.match(text, startIndex);
+ int endIndex = match.capturedStart();
+ int commentLength = 0;
+ if (endIndex == -1)
+ {
+ setCurrentBlockState(1);
+ commentLength = text.length() - startIndex;
+ }
+ else
+ {
+ commentLength = endIndex - startIndex + match.capturedLength();
+ }
+ setFormat(startIndex, commentLength, multiLineCommentFormat);
+ startIndex = text.indexOf(commentStartExpression, startIndex + commentLength);
+ }
+}
diff --git a/src/highlighter.h b/src/highlighter.h
new file mode 100644
index 0000000..ef3ee17
--- /dev/null
+++ b/src/highlighter.h
@@ -0,0 +1,93 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef HIGHLIGHTER_H
+#define HIGHLIGHTER_H
+
+#include
+#include
+#include
+
+QT_BEGIN_NAMESPACE
+class QTextDocument;
+QT_END_NAMESPACE
+
+//! [0]
+class Highlighter : public QSyntaxHighlighter
+{
+ Q_OBJECT
+
+public:
+ Highlighter(QTextDocument *parent = nullptr);
+
+protected:
+ void highlightBlock(const QString &text) override;
+
+private:
+ struct HighlightingRule
+ {
+ QRegularExpression pattern;
+ QTextCharFormat format;
+ };
+ QVector highlightingRules;
+
+ QRegularExpression commentStartExpression;
+ QRegularExpression commentEndExpression;
+
+ QTextCharFormat keywordFormat;
+ QTextCharFormat classFormat;
+ QTextCharFormat singleLineCommentFormat;
+ QTextCharFormat multiLineCommentFormat;
+ QTextCharFormat quotationFormat;
+ QTextCharFormat functionFormat;
+};
+//! [0]
+
+#endif // HIGHLIGHTER_H
diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp
index 3990a57..8b0ad0c 100644
--- a/src/mainwindow.cpp
+++ b/src/mainwindow.cpp
@@ -21,6 +21,21 @@ MainWindow::~MainWindow()
delete ui;
}
+void MainWindow::closeEvent(QCloseEvent *event)
+{
+ // if (ui->pushButtonSerialConnect->isChecked() || ui->pushButtonUDPConnect->isChecked())
+
+ if (serial.isOpen() || networkUDP.isOpen())
+ {
+ QMessageBox::StandardButton resBtn = QMessageBox::question(this, "About to exit...", tr("Connection open. Are you sure ? \n"),
+ QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
+ if (resBtn == QMessageBox::No)
+ event->ignore();
+ else
+ event->accept();
+ }
+}
+
void MainWindow::on_aboutToQuitSlot()
{
settingsSaveAll();
@@ -43,14 +58,27 @@ void MainWindow::setupGUI()
this->setWindowTitle(this->windowTitle() + " " + VERSION);
- ui->textBrowserLogs->document()->setMaximumBlockCount(ui->spinBoxMaxLines->value());
+ // ui->textBrowserLogs
+ {
+ ui->textBrowserLogs->document()->setMaximumBlockCount(ui->spinBoxMaxLines->value());
+
+ if (ui->checkBoxWrapText->isChecked() == true)
+ ui->textBrowserLogs->setLineWrapMode(QPlainTextEdit::LineWrapMode::WidgetWidth);
+ else
+ ui->textBrowserLogs->setLineWrapMode(QPlainTextEdit::LineWrapMode::NoWrap);
- foreach (auto item, QSerialPortInfo::standardBaudRates())
- ui->comboBoxBaudRates->addItem(QString::number(item));
+ // highlighter = new Highlighter(ui->textBrowserLogs->document());
+ }
- connect(ui->comboBoxSend->lineEdit(), SIGNAL(returnPressed()), this, SLOT(on_comboBoxSendReturnPressedSlot()));
+ // ui->comboBoxBaudRates
+ {
+ foreach (auto item, QSerialPortInfo::standardBaudRates())
+ ui->comboBoxBaudRates->addItem(QString::number(item));
- ui->comboBoxBaudRates->setCurrentIndex(ui->comboBoxBaudRates->count() - 3); // TODO SETTINGS !
+ ui->comboBoxBaudRates->setCurrentIndex(ui->comboBoxBaudRates->count() - 3); // TODO SETTINGS !
+ }
+
+ connect(ui->comboBoxSend->lineEdit(), SIGNAL(returnPressed()), this, SLOT(on_comboBoxSendReturnPressedSlot()));
ui->comboBoxTracerStyle->addItem("Crosshair");
ui->comboBoxTracerStyle->addItem("Circle");
@@ -105,7 +133,7 @@ void MainWindow::setupGUI()
if (ui->checkBoxAutoRefresh->isChecked())
{
- serialDeviceCheckTimer->start(500);
+ serialDeviceCheckTimer->start(SERIAL_DEVICE_CHECK_TIMER_INTERVAL);
ui->pushButtonRefresh->setEnabled(false);
}
else
@@ -484,8 +512,8 @@ void MainWindow::processTable(QStringList labels, QList values)
void MainWindow::on_printIntroChangelog() // TODO
{
ui->pushButtonTextLogToggle->setChecked(false);
- ui->textBrowserLogs->append(INTRO_TEXT);
- ui->textBrowserLogs->append("\n" CHANGELOG_TEXT);
+ ui->textBrowserLogs->appendPlainText(INTRO_TEXT);
+ ui->textBrowserLogs->appendPlainText("\n" CHANGELOG_TEXT);
// ui->textBrowserLogs->horizontalScrollBar()->setValue(0);
}
@@ -792,14 +820,12 @@ void MainWindow::on_chartMouseMoveHandler(QMouseEvent *event)
void MainWindow::on_updateSerialDeviceList()
{
- QList devices = QSerialPortInfo::availablePorts();
+ QList devices = serial.getAvailiblePorts();
QList portNames;
static QList portNamesOld;
foreach (auto item, devices)
- {
portNames.append(item.portName());
- }
if ((devices.count() >= 1) && (!(portNames.toSet().intersects(portNamesOld.toSet())) || (portNames.count() != portNamesOld.count())))
{
@@ -813,13 +839,13 @@ void MainWindow::on_updateSerialDeviceList()
else if ((devices.count() < 1) && !ui->comboBoxDevices->itemText(0).startsWith("No COM devices"))
{
ui->comboBoxDevices->clear();
- ui->comboBoxDevices->addItem("No COM devices detected :(");
+ ui->comboBoxDevices->addItem("No serial devices detected :(");
ui->comboBoxDevices->setCurrentIndex(ui->comboBoxDevices->count() - 1);
}
portNamesOld = portNames;
- this->radioButtonTimer->start(100);
+ this->radioButtonTimer->start(RADIO_BUTTON_UPDATE_SERIAL_DEVICES_ON_INTERVAL);
ui->radioButtonDeviceUpdate->setChecked(true);
}
@@ -839,7 +865,7 @@ void MainWindow::addLog(QString text)
if (ui->checkBoxShowTime->isChecked())
text = currentDateTime + text;
- ui->textBrowserLogs->append(text);
+ ui->textBrowserLogs->appendPlainText(text);
// ui->textBrowserLogs->insertPlainText(text);
// ui->textBrowserLogs->moveCursor(QTextCursor::MoveOperation::End, QTextCursor::MoveMode::MoveAnchor);
@@ -847,7 +873,7 @@ void MainWindow::addLog(QString text)
}
}
-void MainWindow::addLogBytes(QString prefix, QByteArray bytes, bool hexToBinary)
+void MainWindow::addLogBytes(QByteArray bytes, bool hexToBinary)
{
if (ui->pushButtonTextLogToggle->isChecked() == false)
{
@@ -856,10 +882,9 @@ void MainWindow::addLogBytes(QString prefix, QByteArray bytes, bool hexToBinary)
QString bytesText;
if (hexToBinary == false)
- bytesText = prefix + bytes.toHex(' ');
+ bytesText = bytes.toHex(' ');
else
{
- bytesText.append(prefix);
for (auto i = 0; i < bytes.size(); ++i)
{
bytesText.append(QString::number(bytes[i], 2) + ' ');
@@ -869,7 +894,7 @@ void MainWindow::addLogBytes(QString prefix, QByteArray bytes, bool hexToBinary)
if (ui->checkBoxShowTime->isChecked())
bytesText = currentDateTime + bytesText;
- ui->textBrowserLogs->append(bytesText);
+ ui->textBrowserLogs->appendPlainText(bytesText);
}
}
@@ -897,15 +922,15 @@ void MainWindow::on_processSerial()
if (ui->comboBoxFormat->currentIndex() == 0 && serialInput.isEmpty() == false)
{
- addLog("Serial <<\t" + serialInput);
+ addLog(serialInput);
}
else if (ui->comboBoxFormat->currentIndex() == 1 && serialInput.length() > 0)
{
- addLogBytes("Serial (HEX) <<\t", serialInput.toUtf8());
+ addLogBytes(serialInput.toUtf8());
}
else if (ui->comboBoxFormat->currentIndex() == 2 && serialInput.length() > 0)
{
- addLogBytes("Serial (BIN) <<\t", serialInput.toUtf8(), true);
+ addLogBytes(serialInput.toUtf8(), true);
}
if (serialInput.isEmpty() == false)
@@ -946,15 +971,15 @@ void MainWindow::on_processUDP()
if (ui->comboBoxFormat->currentIndex() == 0 && udpInput.isEmpty() == false)
{
- addLog("UDP <<\t" + udpInput);
+ addLog(udpInput);
}
else if (ui->comboBoxFormat->currentIndex() == 1 && udpInput.length() > 0)
{
- addLogBytes("UDP (HEX) <<\t", udpInput.toUtf8());
+ addLogBytes(udpInput.toUtf8());
}
else if (ui->comboBoxFormat->currentIndex() == 2 && udpInput.length() > 0)
{
- addLogBytes("UDP (BIN) <<\t", udpInput.toUtf8(), true);
+ addLogBytes(udpInput.toUtf8(), true);
}
if (udpInput.isEmpty() == false)
@@ -992,7 +1017,7 @@ void MainWindow::sendUDPDatagram(QString message)
networkUDP.write(message, QHostAddress(ui->lineEditUDPTargetIP->text()), ui->spinBoxUDPTargetPort->value());
}
- addLog("UDP >>\t" + message);
+ // addLog("UDP >>\t" + message);
}
void MainWindow::processChart(QStringList labelList, QList numericDataList, QList timeStampsList)
@@ -1171,9 +1196,7 @@ void MainWindow::keyPressEvent(QKeyEvent *event)
void MainWindow::sendSerial(QString message)
{
- if (serial.send(message))
- this->addLog("Serial >>\t" + message);
- else
+ if (!serial.send(message))
this->addLog("App >>\t Unable to send! Serial port closed !");
}
@@ -1268,7 +1291,7 @@ void MainWindow::on_checkBoxAutoRefresh_toggled(bool checked)
if (checked == true)
{
ui->pushButtonRefresh->setEnabled(false);
- serialDeviceCheckTimer->start(500);
+ serialDeviceCheckTimer->start(SERIAL_DEVICE_CHECK_TIMER_INTERVAL);
}
else
{
@@ -1330,9 +1353,9 @@ void MainWindow::on_highlighLog(QString searchString)
void MainWindow::on_checkBoxWrapText_toggled(bool checked)
{
if (checked)
- ui->textBrowserLogs->setLineWrapMode(QTextBrowser::LineWrapMode::WidgetWidth);
+ ui->textBrowserLogs->setLineWrapMode(QPlainTextEdit::LineWrapMode::WidgetWidth);
else
- ui->textBrowserLogs->setLineWrapMode(QTextBrowser::LineWrapMode::NoWrap);
+ ui->textBrowserLogs->setLineWrapMode(QPlainTextEdit::LineWrapMode::NoWrap);
}
void MainWindow::on_checkBoxEnableTracer_toggled(bool checked)
@@ -1528,9 +1551,7 @@ void MainWindow::on_pushButtonSerialConnect_toggled(bool checked)
return;
}
- // clearGraphData(true);
-
- QString parsedPortName = ui->comboBoxDevices->currentText().mid(ui->comboBoxDevices->currentText().indexOf("COM"), ui->comboBoxDevices->currentText().indexOf(")") - 1);
+ QString parsedPortName = QSerialPortInfo::availablePorts().at(ui->comboBoxDevices->currentIndex()).portName();
qint32 parsedBaudRate = ui->comboBoxBaudRates->currentText().toInt();
QString dataBits = ui->comboBoxDataBits->currentText();
QString stopBits = ui->comboBoxStopBits->currentText();
@@ -2158,17 +2179,10 @@ void MainWindow::on_comboBoxClockSource_currentIndexChanged(int index)
}
}
-void MainWindow::closeEvent(QCloseEvent *event)
+void MainWindow::on_comboBoxFormat_currentIndexChanged(int index)
{
- // if (ui->pushButtonSerialConnect->isChecked() || ui->pushButtonUDPConnect->isChecked())
-
- if (serial.isOpen() || networkUDP.isOpen())
- {
- QMessageBox::StandardButton resBtn = QMessageBox::question(this, "About to exit...", tr("Connection open. Are you sure ? \n"),
- QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
- if (resBtn == QMessageBox::No)
- event->ignore();
- else
- event->accept();
- }
+ if (index == 0)
+ ui->comboBoxTextProcessing->setEnabled(true);
+ else
+ ui->comboBoxTextProcessing->setEnabled(false);
}
diff --git a/src/mainwindow.h b/src/mainwindow.h
index a2f2bdb..f3b665c 100644
--- a/src/mainwindow.h
+++ b/src/mainwindow.h
@@ -9,6 +9,7 @@
#include "qcustomplot.h"
#include "serial.h"
#include "infodialog.h"
+#include "highlighter.h"
#include
#include
@@ -85,6 +86,7 @@ private slots:
void on_checkBoxWrapText_toggled(bool checked);
void on_clearGraphSelection();
void on_comboBoxClockSource_currentIndexChanged(int index);
+ void on_comboBoxFormat_currentIndexChanged(int index);
void on_comboBoxGraphDisplayMode_currentIndexChanged(const QString &arg1);
void on_comboBoxLoggingMode_currentIndexChanged(int index);
void on_comboBoxSendReturnPressedSlot();
@@ -154,8 +156,8 @@ private slots:
QTimer *udpStringProcessingTimer;
Serial serial;
Ui::MainWindow *ui;
+ Highlighter *highlighter;
void addLog(QString text);
- void addLogBytes(QString prefix, QByteArray bytes, bool hexToBinary = false);
void chartPrintPreview();
void clearGraphData(bool replot);
void clearGraphs(bool replot);
@@ -176,6 +178,7 @@ private slots:
void setupGUI();
void setupTable();
void writeLogToFile(QString rawLine, QStringList labelList, QList dataList, QList timeList);
+ void addLogBytes(QByteArray bytes, bool hexToBinary = false);
protected:
void keyPressEvent(QKeyEvent *event);
};
diff --git a/src/mainwindow.ui b/src/mainwindow.ui
index a2c10f1..b8636a4 100644
--- a/src/mainwindow.ui
+++ b/src/mainwindow.ui
@@ -1519,25 +1519,16 @@
0
-
-
+
0
0
-
-
- Consolas
- 9
-
-
<html><head/><body><p>This is the main text browser. Received messages and notification will be displayed here.</p></body></html>
-
- QTextEdit::NoWrap
-
true
@@ -1547,52 +1538,46 @@
-
-
-
-
+
-
+
-
+
0
0
-
- Disable
+
+ <html><head/><body><p>Highlights the words in the main text window that matches the contents of this textbox</p></body></html>
-
+
+ Text to highlight...
+
+
true
- -
-
+
-
+
-
+
0
0
- <html><head/><body><p>Choose message display format:</p><p>- text</p><p>- hex (base 16)</p><p>- binary (base 2)</p></body></html>
+ <html><head/><body><p>If checked, pressed key will be immidietly sent to the device via Serial or UDP, depending on the active control section tab as long as the <span style=" font-weight:600;">text window remains focused</span>.</p><p>This is very useful for creating a rapidly accesible control interface via serial i.e, you could quickly regulate motor's PWM output by holding "+" or "-" keys, instead of typing "set value ... " every time you need to make a change.</p></body></html>
+
+
+ Send Key
+
+
+ true
-
-
-
- TXT
-
-
- -
-
- HEX
-
-
- -
-
- BIN
-
-
- -
-
+
-
+
0
@@ -1600,12 +1585,25 @@
- <html><head/><body><p>Highlights the words in the main text window that matches the contents of this textbox</p></body></html>
+ <html><head/><body><p>If checked, received message will be displayed with system clock time in which it was received.</p></body></html>
-
- Text to highlight...
+
+ Timestamp
-
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ Disable
+
+
true
@@ -1685,42 +1683,35 @@
- -
-
-
-
- 0
- 0
-
-
-
- <html><head/><body><p>If checked, pressed key will be immidietly sent to the device via Serial or UDP, depending on the active control section tab as long as the <span style=" font-weight:600;">text window remains focused</span>.</p><p>This is very useful for creating a rapidly accesible control interface via serial i.e, you could quickly regulate motor's PWM output by holding "+" or "-" keys, instead of typing "set value ... " every time you need to make a change.</p></body></html>
-
-
- Send Key
-
-
- true
-
-
-
- -
-
+
-
+
-
+
0
0
- <html><head/><body><p>If checked, received message will be displayed with system clock time in which it was received.</p></body></html>
-
-
- Timestamp
+ <html><head/><body><p>Choose message display format:</p><p><span style=" font-weight:600;">- text</span></p><p><span style=" font-weight:600;">- hex (base 16)</span></p><p><span style=" font-weight:600;">- binary (base 2)</span></p></body></html>
+
-
+
+ TXT
+
+
+ -
+
+ HEX
+
+
+ -
+
+ BIN
+
+
- -
+
-
@@ -1728,6 +1719,9 @@
0
+
+ <html><head/><body><p>Choose text post-processing:</p><p><span style=" font-weight:600;">- None</span></p><p><span style=" font-weight:600;">- Trim - remove whitespace form the start and the end of each line.</span></p><p><span style=" font-weight:600;">- Simplify - removes whitespace form the start and the end, and that has each sequence of internal whitespace replaced with a single space.</span></p></body></html>
+
-
None
@@ -2284,7 +2278,7 @@ p, li { white-space: pre-wrap; }
- <html><head/><body><p>Sets the missing samples threshold value. If process string doesnt contain related data n times in a row it is then automatically deleted.</p></body></html>
+ <html><head/><body><p>Sets the missing samples threshold value. If processed string doesnt contain one new data for the already present graph n times in a row it is then this graph will be automatically deleted. This is useful when switching between diffrent steaming data sets.</p></body></html>
Qt::AlignCenter
@@ -2673,6 +2667,11 @@ p, li { white-space: pre-wrap; }
1
+
+ CodeEditor
+ QTextBrowser
+
+
tabWidgetControlSection
diff --git a/src/serial.cpp b/src/serial.cpp
index 5359e99..54dbf1f 100644
--- a/src/serial.cpp
+++ b/src/serial.cpp
@@ -179,6 +179,11 @@ bool Serial::isOpen()
return serialDevice->isOpen();
}
+QList Serial::getAvailiblePorts()
+{
+ return QSerialPortInfo::availablePorts();
+}
+
int Serial::getAvailiblePortsCount()
{
return QSerialPortInfo::availablePorts().count();
diff --git a/src/serial.h b/src/serial.h
index 9a5a904..5fc983b 100644
--- a/src/serial.h
+++ b/src/serial.h
@@ -27,6 +27,7 @@ class Serial : public QObject
bool send(QString message);
bool setReadMode(int mode);
int getAvailiblePortsCount();
+ QList getAvailiblePorts();
QString getSerialInfo();
QString getString(bool clearBuffer = true);
void clearAll(bool clearHardwareBuffers = false);