diff --git a/CMakeLists.txt b/CMakeLists.txt --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -178,6 +178,7 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} 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 diff --git a/src/main.cpp b/src/main.cpp --- a/src/main.cpp +++ b/src/main.cpp @@ -19,28 +19,64 @@ #include #include +#include #include "mainwindow.h" #include "tooltipfilter.h" #include "version.h" -MainWindow* pMainWindow; +MainWindow* pMainWindow = nullptr; void messageHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg) { - // TODO: don't call MainWindow::messageHandler if window is destroyed - pMainWindow->messageHandler(type, context, 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; + break; + case QtWarningMsg: + logString = "[Warning] " + msg; + break; + case QtCriticalMsg: + logString = "[Error] " + msg; + break; + case QtFatalMsg: + logString = "[Fatal] " + msg; + break; + } + + std::cerr << logString.toStdString() << std::endl; + + if (pMainWindow != nullptr) + { + // TODO: don't call MainWindow::messageHandler if window is destroyed + 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; - qInstallMessageHandler(messageHandler); - ToolTipFilter ttf; a.installEventFilter(&ttf); diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -29,10 +29,13 @@ #include #include #include +#include +#include #include #include #include #include +#include #include #include @@ -251,9 +254,11 @@ MainWindow::MainWindow(QWidget *parent) 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()) { @@ -300,7 +305,7 @@ void MainWindow::closeEvent(QCloseEvent } // save settings - QSettings settings("serialplot", "serialplot"); + QSettings settings(PROGRAM_NAME, PROGRAM_NAME); saveAllSettings(&settings); settings.sync(); @@ -474,44 +479,16 @@ PlotViewSettings MainWindow::viewSetting } void MainWindow::messageHandler(QtMsgType type, - const QMessageLogContext &context, + const QString &logString, 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; - break; - case QtWarningMsg: - logString = "[Warning] " + msg; - break; - case QtCriticalMsg: - logString = "[Error] " + msg; - break; - case QtFatalMsg: - logString = "[Fatal] " + msg; - break; - } - - if (ui != NULL) ui->ptLog->appendPlainText(logString); - std::cerr << logString.toStdString() << std::endl; + if (ui != NULL) + ui->ptLog->appendPlainText(logString); if (type != QtDebugMsg && ui != NULL) { ui->statusBar->showMessage(msg, 5000); } - - if (type == QtFatalMsg) - { - __builtin_trap(); - } } void MainWindow::saveAllSettings(QSettings* settings) @@ -616,3 +593,56 @@ void MainWindow::onLoadSettings() loadAllSettings(&settings); } } + +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()) + { + QSettings settings(fileName, QSettings::IniFormat); + loadAllSettings(&settings); + } + 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(); + } +} diff --git a/src/mainwindow.h b/src/mainwindow.h --- a/src/mainwindow.h +++ b/src/mainwindow.h @@ -62,8 +62,7 @@ public: PlotViewSettings viewSettings() const; - void messageHandler(QtMsgType type, const QMessageLogContext &context, - const QString &msg); + void messageHandler(QtMsgType type, const QString &logString, const QString &msg); private: Ui::MainWindow *ui; @@ -93,6 +92,8 @@ private: 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 diff --git a/src/portcontrol.cpp b/src/portcontrol.cpp --- a/src/portcontrol.cpp +++ b/src/portcontrol.cpp @@ -79,10 +79,10 @@ PortControl::PortControl(QSerialPort* po this, &PortControl::onTbPortListActivated); QObject::connect(ui->cbPortList, SELECT::OVERLOAD_OF(&QComboBox::activated), - this, &PortControl::selectPort); + this, &PortControl::selectListedPort); QObject::connect(&tbPortList, SELECT::OVERLOAD_OF(&QComboBox::activated), - this, &PortControl::selectPort); + this, &PortControl::selectListedPort); // setup buttons ui->pbOpenPort->setDefaultAction(&openAction); @@ -91,7 +91,7 @@ PortControl::PortControl(QSerialPort* po // setup baud rate selection widget QObject::connect(ui->cbBaudRate, SELECT::OVERLOAD_OF(&QComboBox::activated), - this, &PortControl::selectBaudRate); + this, &PortControl::_selectBaudRate); // setup parity selection buttons parityButtons.addButton(ui->rbNoParity, (int) QSerialPort::NoParity); @@ -198,7 +198,7 @@ void PortControl::loadBaudRateList() } } -void PortControl::selectBaudRate(QString baudRate) +void PortControl::_selectBaudRate(QString baudRate) { if (serialPort->isOpen()) { @@ -289,7 +289,7 @@ void PortControl::togglePort() 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()); @@ -310,10 +310,17 @@ void PortControl::togglePort() 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()) { @@ -470,6 +477,43 @@ QString PortControl::currentFlowControlT } } +void PortControl::selectPort(QString portName) +{ + 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); + } + else + { + ui->cbBaudRate->setCurrentIndex(baudRateIndex); + } + _selectBaudRate(baudRate); +} + +void PortControl::openPort() +{ + if (!serialPort->isOpen()) + { + openAction.trigger(); + } +} + void PortControl::saveSettings(QSettings* settings) { settings->beginGroup(SettingGroup_Port); @@ -511,7 +555,7 @@ void PortControl::loadSettings(QSettings 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); diff --git a/src/portcontrol.h b/src/portcontrol.h --- a/src/portcontrol.h +++ b/src/portcontrol.h @@ -47,6 +47,10 @@ public: 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. @@ -76,19 +80,18 @@ private: /// 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 selectPort(QString portName); + 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 -private slots: void openActionTriggered(bool checked); void onCbPortListActivated(int index); void onTbPortListActivated(int index);