diff --git a/README.md b/README.md index 33e29a4..b44d95e 100644 --- a/README.md +++ b/README.md @@ -63,6 +63,33 @@ Source and .pro file of the Qt Project are available. A standalone .exe is inclu All notable changes to this project will be documented below this line. This project adheres to [Semantic Versioning](http://semver.org/). + +## [1.3.2] - 2019-11-20 + +### Info + +- Load settings at startup +- Save settings at close event : port, baud, data, parity, stop, spinPoints, spinYStep, spinAxesMin, spinAxesMax + +### Bugfix + +- Solve issue #10 : Save and load settings + +## [1.3.1] - 2019-11-20 + +### Info + +- Built with QT 5.7. +- Change #includes (Qwidget is a separate module) +- Remove QApplication::UnicodeUTF8 in QApplication::translate method (read [Qt forum](https://forum.qt.io/topic/28054/unicodeutf8-not-member-qapplication-generated-with-qt5-designer/2)) +- add QDir::homePath() + in file name string in mainwindow.cpp in order to be able to save csv and png in home directory +- add coordonateX(0) and spinPoints->value() in PNG name in order to be able to save multiple PNG from the same dataset with different zoom or drag +- remove PNG export disable in order to allow export PNG after stop or pause + +### Bugfix + +- Solve issue #9 : Now export work on linux (maybe on mac too) + ## [1.3.0] - 2018-08-01 ### Info diff --git a/SerialPortPlotter.pro b/SerialPortPlotter.pro index 9763c48..7d79c7b 100644 --- a/SerialPortPlotter.pro +++ b/SerialPortPlotter.pro @@ -8,9 +8,11 @@ QT += core gui QT += serialport CONFIG += c++11 -greaterThan(QT_MAJOR_VERSION, 4): QT += widgets printsupport +#greaterThan(QT_MAJOR_VERSION, 5): QT += widgets printsupport -TARGET = serial_port_plotter +QT += widgets printsupport + +TARGET = serialportplotter TEMPLATE = app SOURCES += main.cpp\ @@ -28,7 +30,7 @@ FORMS += mainwindow.ui \ RESOURCES += \ res/serial_port_plotter.qrc \ - res/qdark_stylesheet/qdarkstyle/style.qrc + #res/qdark_stylesheet/qdarkstyle/style.qrc # don't exist # The following line compiles on Release but not on Debug, so this workaroung is used: RC_FILE = res/serial_port_plotter.rc @@ -38,3 +40,26 @@ RC_FILE = res/serial_port_plotter.rc #win32:QMAKE_EXTRA_TARGETS += mkver_rc #win32:PRE_TARGETDEPS += serial_port_plotter_res.o #win32:LIBS += serial_port_plotter_res.o + +unix:configfiles.extra = chmod +x scripts/*; make clean; +binfile.files += serial_port_plotter +binfile.path = /usr/bin/ +#configfiles.files += data/config/* +configfiles.path = /usr/share/ +docfiles.files += data/doc/* +docfiles.path = /usr/share/doc/ +manfiles.files += data/man/* +manfiles.path = /usr/share/man/man1/ +shortcutfiles.files += data/serialportplotter.desktop +shortcutfiles.path = /usr/share/applications/ +INSTALLS += configfiles +INSTALLS += docfiles +INSTALLS += manfiles +INSTALLS += shortcutfiles +INSTALLS += binfile + + + + + + diff --git a/helpwindow.hpp b/helpwindow.hpp index 1fde9ec..12da68c 100644 --- a/helpwindow.hpp +++ b/helpwindow.hpp @@ -27,7 +27,7 @@ #ifndef HELPWINDOW_HPP #define HELPWINDOW_HPP -#include +#include namespace Ui { class HelpWindow; diff --git a/main.cpp b/main.cpp index 9f4bca0..84a3956 100644 --- a/main.cpp +++ b/main.cpp @@ -25,12 +25,16 @@ ****************************************************************************/ #include "mainwindow.hpp" -#include +#include int main(int argc, char *argv[]) { QApplication a(argc, argv); + a.setOrganizationName("SerialPortPlotter"); // give the folder name to store settings in local home + a.setApplicationName("SerialPortPlotter"); // give file config name (.conf) + + /* Apply style sheet */ QFile file(":/serial_port_plotter/styles/style.qss"); if(file.open(QIODevice::ReadOnly | QIODevice::Text)) diff --git a/mainwindow.cpp b/mainwindow.cpp index b804904..95abca4 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -124,7 +124,6 @@ void MainWindow::createUI() { enable_com_controls (false); ui->statusBar->showMessage ("No ports detected."); - ui->savePNGButton->setEnabled (false); return; } @@ -152,7 +151,7 @@ void MainWindow::createUI() ui->comboBaud->addItem ("921600"); /* Select 115200 bits by default */ - ui->comboBaud->setCurrentIndex (7); + //ui->comboBaud->setCurrentIndex (7); // done by loadSettings now /* Populate data bits combo box */ ui->comboData->addItem ("8 bits"); @@ -169,7 +168,22 @@ void MainWindow::createUI() /* Initialize the listwidget */ ui->listWidget_Channels->clear(); -} + + // try to load settings, or populate with default value + loadSettings(); + ui->comboPort->setCurrentIndex(m_prefs.port); + ui->comboBaud->setCurrentIndex(m_prefs.baud); + ui->comboData->setCurrentIndex(m_prefs.data); + ui->comboParity->setCurrentIndex(m_prefs.parity); + ui->comboStop->setCurrentIndex(m_prefs.stop); + ui->spinPoints->setValue(m_prefs.spinPoints); + ui->spinYStep->setValue(m_prefs.spinYStep); + ui->spinAxesMin->setValue(m_prefs.spinAxesMin); + ui->spinAxesMax->setValue(m_prefs.spinAxesMax); + + // disable PNG export before starting record + ui->actionRecord_PNG->setEnabled(false); + } /** ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ /** @@ -546,11 +560,13 @@ void MainWindow::on_spinYStep_valueChanged(int arg1) /** ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ /** - * @brief Save a PNG image of the plot to current EXE directory + * @brief Save a PNG image of the plot to current HOME directory */ -void MainWindow::on_savePNGButton_clicked() +void MainWindow::on_actionRecord_PNG_triggered() { - ui->plot->savePng (QString::number(dataPointNumber) + ".png", 1920, 1080, 2, 50); + ui->plot->savePng (QDir::homePath() + '/' + QString::number(dataPointNumber) + '_' + QString::number(ui->plot->xAxis->coordToPixel(0)) + '_' + QString::number(ui->spinPoints->value()) + ".png", 1920, 1080, 2, 50); + //ui->plot->savePng (QDir::homePath() + '/' + QString::number(dataPointNumber) + ".png", 1920, 1080, 2, 50); // add home path before picture's name + //ui->plot->savePng (QString::number(dataPointNumber) + ".png", 1920, 1080, 2, 50); } /** ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ @@ -727,6 +743,9 @@ void MainWindow::on_actionConnect_triggered() /* Open serial port and connect its signals */ openPort (portInfo, baudRate, dataBits, parity, stopBits); + + /* Enable PNG export */ + ui->actionRecord_PNG->setEnabled(true); } } /** ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ @@ -786,7 +805,6 @@ void MainWindow::on_actionDisconnect_triggered() ui->actionRecord_stream->setEnabled(true); receivedData.clear(); // Clear received string - ui->savePNGButton->setEnabled (false); enable_com_controls (true); } } @@ -799,12 +817,23 @@ void MainWindow::on_actionDisconnect_triggered() */ void MainWindow::on_actionClear_triggered() { - ui->plot->clearPlottables(); - ui->listWidget_Channels->clear(); + + // from https://www.qcustomplot.com/index.php/support/forum/1304 + // delete dataset but not the graph + for( int g=0; gplot->graphCount(); g++ ) + { + ui->plot->graph(g)->data().data()->clear(); + } + ui->plot->replot(); +// ui->plot->clearPlottables(); +// ui->listWidget_Channels->clear(); channels = 0; dataPointNumber = 0; emit setupPlot(); ui->plot->replot(); + + /* Disable PNG export */ + ui->actionRecord_PNG->setEnabled(false); } /** ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ @@ -814,7 +843,8 @@ void MainWindow::on_actionClear_triggered() */ void MainWindow::openCsvFile(void) { - m_csvFile = new QFile(QDateTime::currentDateTime().toString("yyyy-MM-d-HH-mm-ss-")+"data-out.csv"); + m_csvFile = new QFile(QDir::homePath() + '/' + QDateTime::currentDateTime().toString("yyyy-MM-d-HH-mm-ss-")+"data-out.csv"); // add home path before picture's name + //m_csvFile = new QFile(QDateTime::currentDateTime().toString("yyyy-MM-d-HH-mm-ss-")+"data-out.csv"); if(!m_csvFile) return; if (!m_csvFile->open(QIODevice::ReadWrite | QIODevice::Text)) @@ -926,3 +956,56 @@ void MainWindow::on_pushButton_clicked() ui->comboPort->addItem (port.portName()); } } + +/** ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +/** + * @brief Load settings from config file and populate preferences + * + */ +void MainWindow::loadSettings() +{ + QSettings settings; + m_prefs.port = settings.value("port", 0).toInt(); + m_prefs.baud = settings.value("baud", 7).toInt(); + m_prefs.data = settings.value("data", 0).toInt(); + m_prefs.parity = settings.value("parity", 0).toInt(); + m_prefs.stop = settings.value("stop", 0).toInt(); + m_prefs.spinPoints = settings.value("spinPoints", 1000).toInt(); + m_prefs.spinYStep = settings.value("spinYStep", 10).toInt(); + m_prefs.spinAxesMin = settings.value("spinAxesMin", -100).toInt(); + m_prefs.spinAxesMax = settings.value("spinAxesMax", 100).toInt(); +} + +/** ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +/** + * @brief Load settings from config file and populate preferences + * + */ +void MainWindow::saveSettings() +{ + QSettings settings; + settings.setValue("port", ui->comboPort->currentIndex()); + settings.setValue("baud", ui->comboBaud->currentIndex()); + settings.setValue("data", ui->comboData->currentIndex()); + settings.setValue("parity", ui->comboParity->currentIndex()); + settings.setValue("stop", ui->comboStop->currentIndex()); + settings.setValue("spinPoints", ui->spinPoints->value()); + settings.setValue("spinYStep", ui->spinYStep->value()); + settings.setValue("spinAxesMin", ui->spinAxesMin->value()); + settings.setValue("spinAxesMax", ui->spinAxesMax->value()); +} +/** ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +/** + * @brief t the close event, save settings + * + */ +void MainWindow::closeEvent(QCloseEvent *event) +{ + saveSettings(); + event->accept(); +} + + diff --git a/mainwindow.hpp b/mainwindow.hpp index 12d74ff..a914372 100644 --- a/mainwindow.hpp +++ b/mainwindow.hpp @@ -27,7 +27,7 @@ #ifndef MAINWINDOW_HPP #define MAINWINDOW_HPP -#include +#include #include #include #include "helpwindow.hpp" @@ -54,6 +54,7 @@ class MainWindow : public QMainWindow public: explicit MainWindow(QWidget *parent = nullptr); ~MainWindow(); + void closeEvent(QCloseEvent *event); // close event to save settings private slots: void on_comboPort_currentIndexChanged(const QString &arg1); // Slot displays message on status bar @@ -68,7 +69,7 @@ private slots: void readData(); // Slot for inside serial port //void on_comboAxes_currentIndexChanged(int index); // Display number of axes and colors in status bar void on_spinYStep_valueChanged(int arg1); // Spin box for changing Y axis tick step - void on_savePNGButton_clicked(); // Button for saving JPG + //void on_savePNGButton_clicked(); // Button for saving JPG void onMouseMoveInPlot (QMouseEvent *event); // Displays coordinates of mouse pointer when clicked in plot in status bar void on_spinPoints_valueChanged (int arg1); // Spin box controls how many data points are collected and displayed void on_mouse_wheel_in_plot (QWheelEvent *event); // Makes wheel mouse works while plotting @@ -83,6 +84,7 @@ private slots: void on_actionPause_Plot_triggered(); void on_actionClear_triggered(); void on_actionRecord_stream_triggered(); + void on_actionRecord_PNG_triggered(); void on_pushButton_TextEditHide_clicked(); @@ -96,6 +98,7 @@ private slots: void on_pushButton_clicked(); + signals: void portOpenFail(); // Emitted when cannot open port void portOpenOK(); // Emitted when port is open @@ -113,6 +116,8 @@ private slots: bool connected; // Status connection variable bool plotting; // Status plotting variable int dataPointNumber; // Keep track of data points + + char buffer[10]; // buffer to convert number in string for png export /* Channels of data (number of graphs) */ int channels; @@ -131,6 +136,21 @@ private slots: void openCsvFile(void); void closeCsvFile(void); + /* Preferences */ + struct SPreferences + { + int port; // last port used + int baud; // last baudrate item used + int data; // last data length used + int parity; // last parity used + int stop; // last stop bit number + int spinPoints; + int spinYStep; // last value used + int spinAxesMin; // last value used + int spinAxesMax; // last value used + }; + SPreferences m_prefs; // preferences stucture + QTimer updateTimer; // Timer used for replotting the plot QTime timeOfFirstData; // Record the time of the first data point double timeBetweenSamples; // Store time between samples @@ -145,6 +165,9 @@ private slots: void setupPlot(); // Setup the QCustomPlot // Open the inside serial port with these parameters void openPort(QSerialPortInfo portInfo, int baudRate, QSerialPort::DataBits dataBits, QSerialPort::Parity parity, QSerialPort::StopBits stopBits); + + void loadSettings(); // load settings to populate preferences fro; config file + void saveSettings(); // sqve preferences in config file }; diff --git a/mainwindow.ui b/mainwindow.ui index 0025c0a..b5e9cf9 100644 --- a/mainwindow.ui +++ b/mainwindow.ui @@ -528,13 +528,6 @@ - - - - Save PNG - - - @@ -555,12 +548,6 @@ - - - 0 - 80 - - TEXT CONTROLS @@ -703,6 +690,7 @@ + @@ -834,6 +822,18 @@ true + + + + :/serial_port_plotter/ExPNG_nor.png:/serial_port_plotter/ExPNG_nor.png + + + Record_PNG + + + Record the currently plot view in PNG image. + + diff --git a/res/serial_port_plotter.qrc b/res/serial_port_plotter.qrc index 01d0e5c..0da7d1a 100644 --- a/res/serial_port_plotter.qrc +++ b/res/serial_port_plotter.qrc @@ -17,6 +17,9 @@ icons/lynny-2x_white/Stop.png icons/lynny-2x_white/No Entry.png icons/lynny-2x_white/Help.png + icons/lynny-2x/File Type PNG.png + icons/lynny-2x_text/File Type PNG.png + icons/lynny-2x_white/File Type PNG.png icons/line_icon_set/document.png