@@ -175,12 +175,13 @@ include(GetVersion)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DVERSION_STRING=\\\"${VERSION_STRING}\\\" ")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DVERSION_MAJOR=${VERSION_MAJOR} ")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DVERSION_MINOR=${VERSION_MINOR} ")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DVERSION_PATCH=${VERSION_PATCH} ")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DVERSION_REVISION=\\\"${VERSION_REVISION}\\\" ")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DPROGRAM_NAME=\\\"${PROGRAM_NAME}\\\" ")
# add make run target
add_custom_target(run
COMMAND ${PROGRAM_NAME}
DEPENDS ${PROGRAM_NAME}
WORKING_DIRECTORY ${CMAKE_PROJECT_DIR}
@@ -16,34 +16,70 @@
You should have received a copy of the GNU General Public License
along with serialplot. If not, see <http://www.gnu.org/licenses/>.
*/
#include <QApplication>
#include <QtGlobal>
#include <iostream>
#include "mainwindow.h"
#include "tooltipfilter.h"
#include "version.h"
MainWindow* pMainWindow;
MainWindow* pMainWindow = nullptr;
void messageHandler(QtMsgType type, const QMessageLogContext &context,
const QString &msg)
{
QString logString;
switch (type)
#if (QT_VERSION >= QT_VERSION_CHECK(5, 5, 0))
case QtInfoMsg:
logString = "[Info] " + msg;
break;
#endif
case QtDebugMsg:
logString = "[Debug] " + msg;
case QtWarningMsg:
logString = "[Warning] " + msg;
case QtCriticalMsg:
logString = "[Error] " + msg;
case QtFatalMsg:
logString = "[Fatal] " + msg;
}
std::cerr << logString.toStdString() << std::endl;
if (pMainWindow != nullptr)
// TODO: don't call MainWindow::messageHandler if window is destroyed
pMainWindow->messageHandler(type, context, msg);
pMainWindow->messageHandler(type, logString, msg);
if (type == QtFatalMsg)
__builtin_trap();
int main(int argc, char *argv[])
QApplication a(argc, argv);
QApplication::setApplicationName(PROGRAM_NAME);
QApplication::setApplicationVersion(VERSION_STRING);
qInstallMessageHandler(messageHandler);
MainWindow w;
pMainWindow = &w;
ToolTipFilter ttf;
a.installEventFilter(&ttf);
// log application information
qDebug() << "SerialPlot" << VERSION_STRING;
qDebug() << "Revision" << VERSION_REVISION;
@@ -26,16 +26,19 @@
#include <QFile>
#include <QTextStream>
#include <QMenu>
#include <QDesktopServices>
#include <QMap>
#include <QtDebug>
#include <QCommandLineParser>
#include <QFileInfo>
#include <qwt_plot.h>
#include <limits.h>
#include <cmath>
#include <cstdlib>
#include <plot.h>
#include <barplot.h>
#include "framebufferseries.h"
#include "utils.h"
@@ -248,15 +251,17 @@ MainWindow::MainWindow(QWidget *parent)
// init stream connections
connect(&dataFormatPanel, &DataFormatPanel::sourceChanged,
this, &MainWindow::onSourceChanged);
onSourceChanged(dataFormatPanel.activeSource());
// load default settings
QSettings settings("serialplot", "serialplot");
QSettings settings(PROGRAM_NAME, PROGRAM_NAME);
loadAllSettings(&settings);
handleCommandLineOptions(*QApplication::instance());
// ensure command panel has 1 command if none loaded
if (!commandPanel.numOfCommands())
commandPanel.newCommandAction()->trigger();
@@ -297,13 +302,13 @@ void MainWindow::closeEvent(QCloseEvent
event->ignore();
return;
// save settings
saveAllSettings(&settings);
settings.sync();
if (settings.status() != QSettings::NoError)
QString errorText;
@@ -471,50 +476,22 @@ void MainWindow::onExportCsv()
PlotViewSettings MainWindow::viewSettings() const
return plotMenu.viewSettings();
void MainWindow::messageHandler(QtMsgType type,
const QMessageLogContext &context,
const QString &logString,
if (ui != NULL) ui->ptLog->appendPlainText(logString);
if (ui != NULL)
ui->ptLog->appendPlainText(logString);
if (type != QtDebugMsg && ui != NULL)
ui->statusBar->showMessage(msg, 5000);
void MainWindow::saveAllSettings(QSettings* settings)
saveMWSettings(settings);
portControl.saveSettings(settings);
@@ -613,6 +590,59 @@ void MainWindow::onLoadSettings()
if (!fileName.isNull()) // user canceled
QSettings settings(fileName, QSettings::IniFormat);
void MainWindow::handleCommandLineOptions(const QCoreApplication &app)
QCommandLineParser parser;
parser.setSingleDashWordOptionMode(QCommandLineParser::ParseAsCompactedShortOptions);
parser.setApplicationDescription("Small and simple software for plotting data from serial port in realtime.");
parser.addHelpOption();
parser.addVersionOption();
QCommandLineOption configOpt({"c", "config"}, "Load configuration from file.", "filename");
QCommandLineOption portOpt({"p", "port"}, "Set port name.", "port name");
QCommandLineOption baudrateOpt({"b" ,"baudrate"}, "Set port baud rate.", "baud rate");
QCommandLineOption openPortOpt({"o", "open"}, "Open serial port.");
parser.addOption(configOpt);
parser.addOption(portOpt);
parser.addOption(baudrateOpt);
parser.addOption(openPortOpt);
parser.process(app);
if (parser.isSet(configOpt))
QString fileName = parser.value(configOpt);
QFileInfo fileInfo(fileName);
if (fileInfo.exists() && fileInfo.isFile())
else
qCritical() << "Configuration file not exist. Closing application.";
std::exit(1);
if (parser.isSet(portOpt))
portControl.selectPort(parser.value(portOpt));
if (parser.isSet(baudrateOpt))
portControl.selectBaudrate(parser.value(baudrateOpt));
if (parser.isSet(openPortOpt))
portControl.openPort();
@@ -59,14 +59,13 @@ class MainWindow : public QMainWindow
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
PlotViewSettings viewSettings() const;
const QString &msg);
void messageHandler(QtMsgType type, const QString &logString, const QString &msg);
private:
Ui::MainWindow *ui;
QDialog aboutDialog;
void setupAboutDialog();
@@ -90,12 +89,14 @@ private:
RecordPanel recordPanel;
PlotControlPanel plotControlPanel;
PlotMenu plotMenu;
DataTextView textView;
UpdateCheckDialog updateCheckDialog;
void handleCommandLineOptions(const QCoreApplication &app);
/// Returns true if demo is running
bool isDemoRunning();
/// Display a secondary plot in the splitter, removing and
/// deleting previous one if it exists
void showSecondary(QWidget* wid);
/// Hide secondary plot
@@ -76,25 +76,25 @@ PortControl::PortControl(QSerialPort* po
this, &PortControl::onCbPortListActivated);
QObject::connect(&tbPortList,
SELECT<int>::OVERLOAD_OF(&QComboBox::activated),
this, &PortControl::onTbPortListActivated);
QObject::connect(ui->cbPortList,
SELECT<const QString&>::OVERLOAD_OF(&QComboBox::activated),
this, &PortControl::selectPort);
this, &PortControl::selectListedPort);
// setup buttons
ui->pbOpenPort->setDefaultAction(&openAction);
ui->pbReloadPorts->setDefaultAction(&loadPortListAction);
// setup baud rate selection widget
QObject::connect(ui->cbBaudRate,
this, &PortControl::selectBaudRate);
this, &PortControl::_selectBaudRate);
// setup parity selection buttons
parityButtons.addButton(ui->rbNoParity, (int) QSerialPort::NoParity);
parityButtons.addButton(ui->rbEvenParity, (int) QSerialPort::EvenParity);
parityButtons.addButton(ui->rbOddParity, (int) QSerialPort::OddParity);
@@ -195,13 +195,13 @@ void PortControl::loadBaudRateList()
for (auto baudRate : QSerialPortInfo::standardBaudRates())
ui->cbBaudRate->addItem(QString::number(baudRate));
void PortControl::selectBaudRate(QString baudRate)
void PortControl::_selectBaudRate(QString baudRate)
if (serialPort->isOpen())
if (!serialPort->setBaudRate(baudRate.toInt()))
qCritical() << "Can't set baud rate!";
@@ -286,13 +286,13 @@ void PortControl::togglePort()
serialPort->setPortName(ui->cbPortList->currentData(PortNameRole).toString());
// open port
if (serialPort->open(QIODevice::ReadWrite))
// set port settings
selectBaudRate(ui->cbBaudRate->currentText());
_selectBaudRate(ui->cbBaudRate->currentText());
selectParity((QSerialPort::Parity) parityButtons.checkedId());
selectDataBits((QSerialPort::DataBits) dataBitsButtons.checkedId());
selectStopBits((QSerialPort::StopBits) stopBitsButtons.checkedId());
selectFlowControl((QSerialPort::FlowControl) flowControlButtons.checkedId());
// set output signals
@@ -307,16 +307,23 @@ void PortControl::togglePort()
emit portToggled(true);
openAction.setChecked(serialPort->isOpen());
void PortControl::selectPort(QString portName)
void PortControl::selectListedPort(QString portName)
// portName may be coming from combobox
portName = portName.split(" ")[0];
QSerialPortInfo portInfo(portName);
if (portInfo.isNull())
qWarning() << "Device doesn't exists:" << portName;
// has selection actually changed
if (portName != serialPort->portName())
// if another port is already open, close it by toggling
@@ -467,12 +474,49 @@ QString PortControl::currentFlowControlT
else // no parity
return "none";
int portIndex = portList.indexOfName(portName);
if (portIndex < 0) // not in list, add to model and update the selections
portList.appendRow(new PortListItem(portName));
portIndex = portList.rowCount()-1;
ui->cbPortList->setCurrentIndex(portIndex);
tbPortList.setCurrentIndex(portIndex);
selectListedPort(portName);
void PortControl::selectBaudrate(QString baudRate)
int baudRateIndex = ui->cbBaudRate->findText(baudRate);
if (baudRateIndex < 0)
ui->cbBaudRate->setCurrentText(baudRate);
ui->cbBaudRate->setCurrentIndex(baudRateIndex);
_selectBaudRate(baudRate);
void PortControl::openPort()
if (!serialPort->isOpen())
openAction.trigger();
void PortControl::saveSettings(QSettings* settings)
settings->beginGroup(SettingGroup_Port);
settings->setValue(SG_Port_SelectedPort, selectedPortName());
settings->setValue(SG_Port_BaudRate, ui->cbBaudRate->currentText());
settings->setValue(SG_Port_Parity, currentParityText());
@@ -508,13 +552,13 @@ void PortControl::loadSettings(QSettings
settings->value(SG_Port_Parity, currentParityText()).toString();
QSerialPort::Parity paritySetting = paritySettingMap.key(
parityText, (QSerialPort::Parity) parityButtons.checkedId());
parityButtons.button(paritySetting)->setChecked(true);
// load number of bits
int dataBits = settings->value(SG_Port_Parity, dataBitsButtons.checkedId()).toInt();
int dataBits = settings->value(SG_Port_DataBits, dataBitsButtons.checkedId()).toInt();
if (dataBits >=5 && dataBits <= 8)
dataBitsButtons.button((QSerialPort::DataBits) dataBits)->setChecked(true);
// load stop bits
@@ -44,12 +44,16 @@ public:
explicit PortControl(QSerialPort* port, QWidget* parent = 0);
~PortControl();
QSerialPort* serialPort;
QToolBar* toolBar();
void selectPort(QString portName);
void selectBaudrate(QString baudRate);
void openPort();
/// Stores port settings into a `QSettings`
void saveSettings(QSettings* settings);
/// Loads port settings from a `QSettings`. If open serial port is closed.
void loadSettings(QSettings* settings);
@@ -73,25 +77,24 @@ private:
QString selectedPortName();
/// Returns currently selected parity as text to be saved in settings
QString currentParityText();
/// Returns currently selected flow control as text to be saved in settings
QString currentFlowControlText();
public slots:
private slots:
void loadPortList();
void loadBaudRateList();
void togglePort();
void selectListedPort(QString portName);
void selectBaudRate(QString baudRate);
void _selectBaudRate(QString baudRate);
void selectParity(int parity); // parity must be one of QSerialPort::Parity
void selectDataBits(int dataBits); // bits must be one of QSerialPort::DataBits
void selectStopBits(int stopBits); // stopBits must be one of QSerialPort::StopBits
void selectFlowControl(int flowControl); // flowControl must be one of QSerialPort::FlowControl
void openActionTriggered(bool checked);
void onCbPortListActivated(int index);
void onTbPortListActivated(int index);
void onPortError(QSerialPort::SerialPortError error);
void updatePinLeds(void);
Status change: