Changeset - e3f742bbe8b8
[Not reviewed]
Merge default
0 6 0
Hasan Yavuz ÖZDERYA - 7 years ago 2019-04-07 09:41:25
hy@ozderya.net
Merged in aslan-mehmet/serialplot/feature/command-line-options

feature/command line options

Resolves #45
6 files changed with 166 insertions and 51 deletions:
0 comments (0 inline, 0 general)
CMakeLists.txt
Show inline comments
 
@@ -133,96 +133,97 @@ add_executable(${PROGRAM_NAME} WIN32
 
  src/samplepack.cpp
 
  src/source.cpp
 
  src/sink.cpp
 
  src/samplecounter.cpp
 
  src/ledwidget.cpp
 
  src/datatextview.cpp
 
  misc/windows_icon.rc
 
  ${UI_FILES}
 
  ${RES_FILES}
 
  )
 

	
 
# Use the Widgets module from Qt 5.
 
target_link_libraries(${PROGRAM_NAME}
 
  ${QWT_LIBRARY}
 
  )
 
qt5_use_modules(${PROGRAM_NAME} Widgets SerialPort Network)
 

	
 
if (BUILD_QWT)
 
  add_dependencies(${PROGRAM_NAME} QWT)
 
endif ()
 

	
 
# set compiler flags
 
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall")
 

	
 
# Enable C++11 support, fail if not supported
 
include(CheckCXXCompilerFlag)
 
CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_SUPPORTS_CXX11)
 
CHECK_CXX_COMPILER_FLAG("-std=c++0x" COMPILER_SUPPORTS_CXX0X)
 
if(COMPILER_SUPPORTS_CXX11)
 
  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
 
elseif(COMPILER_SUPPORTS_CXX0X)
 
  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x")
 
else()
 
  message(STATUS "The compiler ${CMAKE_CXX_COMPILER} has no C++11 support. Please use a different C++ compiler.")
 
endif()
 

	
 
# default version
 
set(VERSION_STRING "0.10.0")
 
set(VERSION_REVISION "0")
 

	
 
# get revision number from mercurial and parse version string
 
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}
 
)
 

	
 
# installing
 
install(TARGETS ${PROGRAM_NAME} DESTINATION bin)
 

	
 
# for windows put libraries to install directory
 
if (WIN32)
 
  file(GLOB WINDOWS_INSTALL_LIBRARIES
 
    "${CMAKE_BINARY_DIR}/windows_install_libraries/*.*")
 
  install(FILES ${WINDOWS_INSTALL_LIBRARIES} DESTINATION bin)
 
endif (WIN32)
 

	
 
# prepare menu item and icon
 
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/misc/program_name.desktop.in"
 
  "${CMAKE_BINARY_DIR}/${PROGRAM_NAME}.desktop")
 
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/misc/program_name.png"
 
  "${CMAKE_BINARY_DIR}/${PROGRAM_NAME}.png" COPYONLY)
 

	
 
set(DESKTOP_FILE ${CMAKE_BINARY_DIR}/${PROGRAM_NAME}.desktop)
 
set(ICON_FILE ${CMAKE_BINARY_DIR}/${PROGRAM_NAME}.png)
 

	
 
# install menu item and icon
 
if (UNIX)
 
  install(FILES ${DESKTOP_FILE} DESTINATION share/applications/)
 
  install(FILES ${ICON_FILE} DESTINATION share/icons/hicolor/256x256/apps/)
 
endif (UNIX)
 

	
 
# uninstalling
 
configure_file(
 
  "${CMAKE_CURRENT_SOURCE_DIR}/cmake/cmake_uninstall.cmake.in"
 
  "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake"
 
  @ONLY)
 

	
 
if (UNIX)
 
  add_custom_target(uninstall
 
    COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake)
 
endif (UNIX)
 

	
 
# testing
 
set(ENABLE_TESTS false CACHE BOOL "Build tests.")
 
if (ENABLE_TESTS)
 
  enable_testing()
src/main.cpp
Show inline comments
 
/*
 
  Copyright © 2017 Hasan Yavuz Özderya
 

	
 
  This file is part of serialplot.
 

	
 
  serialplot is free software: you can redistribute it and/or modify
 
  it under the terms of the GNU General Public License as published by
 
  the Free Software Foundation, either version 3 of the License, or
 
  (at your option) any later version.
 

	
 
  serialplot is distributed in the hope that it will be useful,
 
  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
  GNU General Public License for more details.
 

	
 
  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)
 
{
 
    // 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);
 

	
 
    // log application information
 
    qDebug() << "SerialPlot" << VERSION_STRING;
 
    qDebug() << "Revision" << VERSION_REVISION;
 

	
 
    w.show();
 

	
 
    return a.exec();
 
}
src/mainwindow.cpp
Show inline comments
 
/*
 
  Copyright © 2019 Hasan Yavuz Özderya
 

	
 
  This file is part of serialplot.
 

	
 
  serialplot is free software: you can redistribute it and/or modify
 
  it under the terms of the GNU General Public License as published by
 
  the Free Software Foundation, either version 3 of the License, or
 
  (at your option) any later version.
 

	
 
  serialplot is distributed in the hope that it will be useful,
 
  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
  GNU General Public License for more details.
 

	
 
  You should have received a copy of the GNU General Public License
 
  along with serialplot.  If not, see <http://www.gnu.org/licenses/>.
 
*/
 

	
 
#include "mainwindow.h"
 
#include "ui_mainwindow.h"
 
#include <QByteArray>
 
#include <QApplication>
 
#include <QFileDialog>
 
#include <QMessageBox>
 
#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 <iostream>
 
#include <cstdlib>
 

	
 
#include <plot.h>
 
#include <barplot.h>
 

	
 
#include "framebufferseries.h"
 
#include "utils.h"
 
#include "defines.h"
 
#include "version.h"
 
#include "setting_defines.h"
 

	
 
#if defined(Q_OS_WIN) && defined(QT_STATIC)
 
#include <QtPlugin>
 
Q_IMPORT_PLUGIN(QWindowsIntegrationPlugin)
 
#endif
 

	
 
// TODO: depends on tab insertion order, a better solution would be to use object names
 
const QMap<int, QString> panelSettingMap({
 
        {0, "Port"},
 
        {1, "DataFormat"},
 
        {2, "Plot"},
 
        {3, "Commands"},
 
        {4, "Record"},
 
        {5, "TextView"},
 
        {6, "Log"}
 
    });
 

	
 
MainWindow::MainWindow(QWidget *parent) :
 
    QMainWindow(parent),
 
    ui(new Ui::MainWindow),
 
    aboutDialog(this),
 
    portControl(&serialPort),
 
    secondaryPlot(NULL),
 
    snapshotMan(this, &stream),
 
    commandPanel(&serialPort),
 
    dataFormatPanel(&serialPort),
 
    recordPanel(&stream),
 
    textView(&stream),
 
    updateCheckDialog(this)
 
{
 
    ui->setupUi(this);
 

	
 
    plotMan = new PlotManager(ui->plotArea, &plotMenu, &stream);
 

	
 
    ui->tabWidget->insertTab(0, &portControl, "Port");
 
    ui->tabWidget->insertTab(1, &dataFormatPanel, "Data Format");
 
    ui->tabWidget->insertTab(2, &plotControlPanel, "Plot");
 
    ui->tabWidget->insertTab(3, &commandPanel, "Commands");
 
    ui->tabWidget->insertTab(4, &recordPanel, "Record");
 
@@ -206,146 +209,148 @@ MainWindow::MainWindow(QWidget *parent) 
 
    QObject::connect(&recordPanel, &RecordPanel::recordPausedChanged,
 
                     [this](bool enabled)
 
                     {
 
                         if (ui->actionPause->isChecked() && enabled)
 
                         {
 
                             dataFormatPanel.pause(false);
 
                         }
 
                     });
 

	
 
    connect(&serialPort, &QIODevice::aboutToClose,
 
            &recordPanel, &RecordPanel::onPortClose);
 

	
 
    // init plot
 
    numOfSamples = plotControlPanel.numOfSamples();
 
    stream.setNumSamples(numOfSamples);
 
    plotControlPanel.setChannelInfoModel(stream.infoModel());
 

	
 
    // init scales
 
    stream.setXAxis(plotControlPanel.xAxisAsIndex(),
 
                    plotControlPanel.xMin(), plotControlPanel.xMax());
 

	
 
    plotMan->setYAxis(plotControlPanel.autoScale(),
 
                      plotControlPanel.yMin(), plotControlPanel.yMax());
 
    plotMan->setXAxis(plotControlPanel.xAxisAsIndex(),
 
                      plotControlPanel.xMin(), plotControlPanel.xMax());
 
    plotMan->setNumOfSamples(numOfSamples);
 
    plotMan->setPlotWidth(plotControlPanel.plotWidth());
 

	
 
    // Init sps (sample per second) counter
 
    spsLabel.setText("0sps");
 
    spsLabel.setToolTip("samples per second (per channel)");
 
    ui->statusBar->addPermanentWidget(&spsLabel);
 
    connect(&sampleCounter, &SampleCounter::spsChanged,
 
            this, &MainWindow::onSpsChanged);
 

	
 
    // init demo
 
    QObject::connect(ui->actionDemoMode, &QAction::toggled,
 
                     this, &MainWindow::enableDemo);
 

	
 
    QObject::connect(ui->actionDemoMode, &QAction::toggled,
 
                     plotMan, &PlotManager::showDemoIndicator);
 

	
 
    // 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();
 
    }
 

	
 
    // Important: This should be after newCommandAction is triggered
 
    // (above) we don't want user to be greeted with command panel on
 
    // the very first run.
 
    connect(commandPanel.newCommandAction(), &QAction::triggered, [this]()
 
            {
 
                this->ui->tabWidget->setCurrentWidget(&commandPanel);
 
                this->ui->tabWidget->showTabs();
 
            });
 
}
 

	
 
MainWindow::~MainWindow()
 
{
 
    if (serialPort.isOpen())
 
    {
 
        serialPort.close();
 
    }
 

	
 
    delete plotMan;
 

	
 
    delete ui;
 
    ui = NULL; // we check if ui is deleted in messageHandler
 
}
 

	
 
void MainWindow::closeEvent(QCloseEvent * event)
 
{
 
    // save snapshots
 
    if (!snapshotMan.isAllSaved())
 
    {
 
        auto clickedButton = QMessageBox::warning(
 
            this, "Closing SerialPlot",
 
            "There are un-saved snapshots. If you close you will loose the data.",
 
            QMessageBox::Discard, QMessageBox::Cancel);
 
        if (clickedButton == QMessageBox::Cancel)
 
        {
 
            event->ignore();
 
            return;
 
        }
 
    }
 

	
 
    // save settings
 
    QSettings settings("serialplot", "serialplot");
 
    QSettings settings(PROGRAM_NAME, PROGRAM_NAME);
 
    saveAllSettings(&settings);
 
    settings.sync();
 

	
 
    if (settings.status() != QSettings::NoError)
 
    {
 
        QString errorText;
 

	
 
        if (settings.status() == QSettings::AccessError)
 
        {
 
            QString file = settings.fileName();
 
            errorText = QString("Serialplot cannot save settings due to access error. \
 
This happens if you have run serialplot as root (with sudo for ex.) previously. \
 
Try fixing the permissions of file: %1, or just delete it.").arg(file);
 
        }
 
        else
 
        {
 
            errorText = QString("Serialplot cannot save settings due to unknown error: %1").\
 
                arg(settings.status());
 
        }
 

	
 
        auto button = QMessageBox::critical(
 
            NULL,
 
            "Failed to save settings!", errorText,
 
            QMessageBox::Cancel | QMessageBox::Ok);
 

	
 
        if (button == QMessageBox::Cancel)
 
        {
 
            event->ignore();
 
            return;
 
        }
 
    }
 

	
 
    QMainWindow::closeEvent(event);
 
}
 

	
 
void MainWindow::setupAboutDialog()
 
{
 
    Ui_AboutDialog uiAboutDialog;
 
    uiAboutDialog.setupUi(&aboutDialog);
 

	
 
    QObject::connect(uiAboutDialog.pbAboutQt, &QPushButton::clicked,
 
                     [](){ QApplication::aboutQt();});
 

	
 
    QString aboutText = uiAboutDialog.lbAbout->text();
 
    aboutText.replace("$VERSION_STRING$", VERSION_STRING);
 
    aboutText.replace("$VERSION_REVISION$", VERSION_REVISION);
 
    uiAboutDialog.lbAbout->setText(aboutText);
 
}
 
@@ -429,134 +434,106 @@ void MainWindow::hideSecondary()
 

	
 
    secondaryPlot->deleteLater();
 
    secondaryPlot = NULL;
 
}
 

	
 
void MainWindow::showBarPlot(bool show)
 
{
 
    if (show)
 
    {
 
        auto plot = new BarPlot(&stream, &plotMenu);
 
        plot->setYAxis(plotControlPanel.autoScale(),
 
                       plotControlPanel.yMin(),
 
                       plotControlPanel.yMax());
 
        connect(&plotControlPanel, &PlotControlPanel::yScaleChanged,
 
                plot, &BarPlot::setYAxis);
 
        showSecondary(plot);
 
    }
 
    else
 
    {
 
        hideSecondary();
 
    }
 
}
 

	
 
void MainWindow::onExportCsv()
 
{
 
    bool wasPaused = ui->actionPause->isChecked();
 
    ui->actionPause->setChecked(true); // pause plotting
 

	
 
    QString fileName = QFileDialog::getSaveFileName(this, tr("Export CSV File"));
 

	
 
    if (fileName.isNull())  // user canceled export
 
    {
 
        ui->actionPause->setChecked(wasPaused);
 
    }
 
    else
 
    {
 
        Snapshot* snapshot = snapshotMan.makeSnapshot();
 
        snapshot->save(fileName);
 
        delete snapshot;
 
    }
 
}
 

	
 
PlotViewSettings MainWindow::viewSettings() const
 
{
 
    return plotMenu.viewSettings();
 
}
 

	
 
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)
 
{
 
    saveMWSettings(settings);
 
    portControl.saveSettings(settings);
 
    dataFormatPanel.saveSettings(settings);
 
    stream.saveSettings(settings);
 
    plotControlPanel.saveSettings(settings);
 
    plotMenu.saveSettings(settings);
 
    commandPanel.saveSettings(settings);
 
    recordPanel.saveSettings(settings);
 
    textView.saveSettings(settings);
 
    updateCheckDialog.saveSettings(settings);
 
}
 

	
 
void MainWindow::loadAllSettings(QSettings* settings)
 
{
 
    loadMWSettings(settings);
 
    portControl.loadSettings(settings);
 
    dataFormatPanel.loadSettings(settings);
 
    stream.loadSettings(settings);
 
    plotControlPanel.loadSettings(settings);
 
    plotMenu.loadSettings(settings);
 
    commandPanel.loadSettings(settings);
 
    recordPanel.loadSettings(settings);
 
    textView.loadSettings(settings);
 
    updateCheckDialog.loadSettings(settings);
 
}
 

	
 
void MainWindow::saveMWSettings(QSettings* settings)
 
{
 
    // save window geometry
 
    settings->beginGroup(SettingGroup_MainWindow);
 
    settings->setValue(SG_MainWindow_Size, size());
 
    settings->setValue(SG_MainWindow_Pos, pos());
 
    // save active panel
 
    settings->setValue(SG_MainWindow_ActivePanel,
 
                       panelSettingMap.value(ui->tabWidget->currentIndex()));
 
    // save panel minimization
 
    settings->setValue(SG_MainWindow_HidePanels,
 
                       ui->tabWidget->hideAction.isChecked());
 
    // save window maximized state
 
    settings->setValue(SG_MainWindow_Maximized,
 
                       bool(windowState() & Qt::WindowMaximized));
 
    // save toolbar/dockwidgets state
 
    settings->setValue(SG_MainWindow_State, saveState());
 
    settings->endGroup();
 
@@ -571,48 +548,101 @@ void MainWindow::loadMWSettings(QSetting
 

	
 
    // set active panel
 
    QString tabSetting =
 
        settings->value(SG_MainWindow_ActivePanel, QString()).toString();
 
    ui->tabWidget->setCurrentIndex(
 
        panelSettingMap.key(tabSetting, ui->tabWidget->currentIndex()));
 

	
 
    // hide panels
 
    ui->tabWidget->hideAction.setChecked(
 
        settings->value(SG_MainWindow_HidePanels,
 
                        ui->tabWidget->hideAction.isChecked()).toBool());
 

	
 
    // maximize window
 
    if (settings->value(SG_MainWindow_Maximized).toBool())
 
    {
 
        showMaximized();
 
    }
 

	
 
    // load toolbar/dockwidgets state
 
    restoreState(settings->value(SG_MainWindow_State).toByteArray());
 
    settings->setValue(SG_MainWindow_State, saveState());
 

	
 
    settings->endGroup();
 
}
 

	
 
void MainWindow::onSaveSettings()
 
{
 
    QString fileName = QFileDialog::getSaveFileName(
 
        this, tr("Save Settings"), QString(), "INI (*.ini)");
 

	
 
    if (!fileName.isNull()) // user canceled
 
    {
 
        QSettings settings(fileName, QSettings::IniFormat);
 
        saveAllSettings(&settings);
 
    }
 
}
 

	
 
void MainWindow::onLoadSettings()
 
{
 
    QString fileName = QFileDialog::getOpenFileName(
 
        this, tr("Load Settings"), QString(), "INI (*.ini)");
 

	
 
    if (!fileName.isNull()) // user canceled
 
    {
 
        QSettings settings(fileName, QSettings::IniFormat);
 
        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();
 
    }
 
}
src/mainwindow.h
Show inline comments
 
@@ -17,114 +17,115 @@
 
  along with serialplot.  If not, see <http://www.gnu.org/licenses/>.
 
*/
 

	
 
#ifndef MAINWINDOW_H
 
#define MAINWINDOW_H
 

	
 
#include <QMainWindow>
 
#include <QButtonGroup>
 
#include <QLabel>
 
#include <QString>
 
#include <QVector>
 
#include <QList>
 
#include <QSerialPort>
 
#include <QSignalMapper>
 
#include <QTimer>
 
#include <QColor>
 
#include <QtGlobal>
 
#include <QSettings>
 
#include <qwt_plot_curve.h>
 

	
 
#include "portcontrol.h"
 
#include "commandpanel.h"
 
#include "dataformatpanel.h"
 
#include "plotcontrolpanel.h"
 
#include "recordpanel.h"
 
#include "ui_about_dialog.h"
 
#include "stream.h"
 
#include "snapshotmanager.h"
 
#include "plotmanager.h"
 
#include "plotmenu.h"
 
#include "updatecheckdialog.h"
 
#include "samplecounter.h"
 
#include "datatextview.h"
 

	
 
namespace Ui {
 
class MainWindow;
 
}
 

	
 
class MainWindow : public QMainWindow
 
{
 
    Q_OBJECT
 

	
 
public:
 
    explicit MainWindow(QWidget *parent = 0);
 
    ~MainWindow();
 

	
 
    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;
 

	
 
    QDialog aboutDialog;
 
    void setupAboutDialog();
 

	
 
    QSerialPort serialPort;
 
    PortControl portControl;
 

	
 
    unsigned int numOfSamples;
 

	
 
    QList<QwtPlotCurve*> curves;
 
    // ChannelManager channelMan;
 
    Stream stream;
 
    PlotManager* plotMan;
 
    QWidget* secondaryPlot;
 
    SnapshotManager snapshotMan;
 
    SampleCounter sampleCounter;
 

	
 
    QLabel spsLabel;
 
    CommandPanel commandPanel;
 
    DataFormatPanel dataFormatPanel;
 
    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
 
    void hideSecondary();
 
    /// Stores settings for all modules
 
    void saveAllSettings(QSettings* settings);
 
    /// Load settings for all modules
 
    void loadAllSettings(QSettings* settings);
 
    /// Stores main window settings into a `QSettings`
 
    void saveMWSettings(QSettings* settings);
 
    /// Loads main window settings from a `QSettings`
 
    void loadMWSettings(QSettings* settings);
 

	
 
    /// `QWidget::closeEvent` handler
 
    void closeEvent(QCloseEvent * event);
 

	
 
private slots:
 
    void onPortToggled(bool open);
 
    void onSourceChanged(Source* source);
 
    void onNumOfSamplesChanged(int value);
 

	
 
    void clearPlot();
 
    void onSpsChanged(float sps);
 
    void enableDemo(bool enabled);
 
    void showBarPlot(bool show);
 

	
 
    void onExportCsv();
 
    void onSaveSettings();
 
    void onLoadSettings();
 
};
 

	
 
#endif // MAINWINDOW_H
src/portcontrol.cpp
Show inline comments
 
@@ -34,109 +34,109 @@
 
// setting mappings
 
const QMap<QSerialPort::Parity, QString> paritySettingMap({
 
        {QSerialPort::NoParity, "none"},
 
        {QSerialPort::OddParity, "odd"},
 
        {QSerialPort::EvenParity, "even"},
 
    });
 

	
 
PortControl::PortControl(QSerialPort* port, QWidget* parent) :
 
    QWidget(parent),
 
    ui(new Ui::PortControl),
 
    portToolBar("Port Toolbar"),
 
    openAction("Open", this),
 
    loadPortListAction("↺", this)
 
{
 
    ui->setupUi(this);
 

	
 
    serialPort = port;
 
    connect(serialPort, SIGNAL(error(QSerialPort::SerialPortError)),
 
            this, SLOT(onPortError(QSerialPort::SerialPortError)));
 

	
 
    // setup actions
 
    openAction.setCheckable(true);
 
    openAction.setShortcut(QKeySequence("F12"));
 
    openAction.setToolTip("Open Port");
 
    QObject::connect(&openAction, &QAction::triggered,
 
                     this, &PortControl::openActionTriggered);
 

	
 
    loadPortListAction.setToolTip("Reload port list");
 
    QObject::connect(&loadPortListAction, &QAction::triggered,
 
                     [this](bool checked){loadPortList();});
 

	
 
    // setup toolbar
 
    portToolBar.addWidget(&tbPortList);
 
    portToolBar.addAction(&loadPortListAction);
 
    portToolBar.addAction(&openAction);
 

	
 
    // setup port selection widgets
 
    tbPortList.setMinimumWidth(TBPORTLIST_MINWIDTH);
 
    tbPortList.setModel(&portList);
 
    ui->cbPortList->setModel(&portList);
 
    QObject::connect(ui->cbPortList,
 
                     SELECT<int>::OVERLOAD_OF(&QComboBox::activated),
 
                     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);
 
    QObject::connect(&tbPortList,
 
                     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,
 
                     SELECT<const QString&>::OVERLOAD_OF(&QComboBox::activated),
 
                     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);
 

	
 
    QObject::connect(&parityButtons,
 
                     SELECT<int>::OVERLOAD_OF(&QButtonGroup::buttonClicked),
 
                     this, &PortControl::selectParity);
 

	
 
    // setup data bits selection buttons
 
    dataBitsButtons.addButton(ui->rb8Bits, (int) QSerialPort::Data8);
 
    dataBitsButtons.addButton(ui->rb7Bits, (int) QSerialPort::Data7);
 
    dataBitsButtons.addButton(ui->rb6Bits, (int) QSerialPort::Data6);
 
    dataBitsButtons.addButton(ui->rb5Bits, (int) QSerialPort::Data5);
 

	
 
    QObject::connect(&dataBitsButtons,
 
                     SELECT<int>::OVERLOAD_OF(&QButtonGroup::buttonClicked),
 
                     this, &PortControl::selectDataBits);
 

	
 
    // setup stop bits selection buttons
 
    stopBitsButtons.addButton(ui->rb1StopBit, (int) QSerialPort::OneStop);
 
    stopBitsButtons.addButton(ui->rb2StopBit, (int) QSerialPort::TwoStop);
 

	
 
    QObject::connect(&stopBitsButtons,
 
                     SELECT<int>::OVERLOAD_OF(&QButtonGroup::buttonClicked),
 
                     this, &PortControl::selectStopBits);
 

	
 
    // setup flow control selection buttons
 
    flowControlButtons.addButton(ui->rbNoFlowControl,
 
                                 (int) QSerialPort::NoFlowControl);
 
    flowControlButtons.addButton(ui->rbHardwareControl,
 
                                 (int) QSerialPort::HardwareControl);
 
    flowControlButtons.addButton(ui->rbSoftwareControl,
 
                                 (int) QSerialPort::SoftwareControl);
 

	
 
    QObject::connect(&flowControlButtons,
 
                     SELECT<int>::OVERLOAD_OF(&QButtonGroup::buttonClicked),
 
                     this, &PortControl::selectFlowControl);
 

	
 
    // initialize signal leds
 
    ui->ledDTR->setOn(true);
 
    ui->ledRTS->setOn(true);
 

	
 
    // connect output signals
 
    connect(ui->pbDTR, &QPushButton::clicked, [this]()
 
            {
 
                // toggle DTR
 
@@ -153,212 +153,219 @@ PortControl::PortControl(QSerialPort* po
 
                ui->ledRTS->toggle();
 
                if (serialPort->isOpen())
 
                {
 
                    serialPort->setRequestToSend(ui->ledRTS->isOn());
 
                }
 
            });
 

	
 
    // setup pin update leds
 
    ui->ledDCD->setColor(Qt::yellow);
 
    ui->ledDSR->setColor(Qt::yellow);
 
    ui->ledRI->setColor(Qt::yellow);
 
    ui->ledCTS->setColor(Qt::yellow);
 

	
 
    pinUpdateTimer.setInterval(1000); // ms
 
    connect(&pinUpdateTimer, &QTimer::timeout, this, &PortControl::updatePinLeds);
 

	
 
    loadPortList();
 
    loadBaudRateList();
 
    ui->cbBaudRate->setCurrentIndex(ui->cbBaudRate->findText("9600"));
 
}
 

	
 
PortControl::~PortControl()
 
{
 
    delete ui;
 
}
 

	
 
void PortControl::loadPortList()
 
{
 
    QString currentSelection = ui->cbPortList->currentData(PortNameRole).toString();
 
    portList.loadPortList();
 
    int index = portList.indexOf(currentSelection);
 
    if (index >= 0)
 
    {
 
        ui->cbPortList->setCurrentIndex(index);
 
        tbPortList.setCurrentIndex(index);
 
    }
 
}
 

	
 
void PortControl::loadBaudRateList()
 
{
 
    ui->cbBaudRate->clear();
 

	
 
    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!";
 
        }
 
    }
 
}
 

	
 
void PortControl::selectParity(int parity)
 
{
 
    if (serialPort->isOpen())
 
    {
 
        if(!serialPort->setParity((QSerialPort::Parity) parity))
 
        {
 
            qCritical() << "Can't set parity option!";
 
        }
 
    }
 
}
 

	
 
void PortControl::selectDataBits(int dataBits)
 
{
 
    if (serialPort->isOpen())
 
    {
 
        if(!serialPort->setDataBits((QSerialPort::DataBits) dataBits))
 
        {
 
            qCritical() << "Can't set numer of data bits!";
 
        }
 
    }
 
}
 

	
 
void PortControl::selectStopBits(int stopBits)
 
{
 
    if (serialPort->isOpen())
 
    {
 
        if(!serialPort->setStopBits((QSerialPort::StopBits) stopBits))
 
        {
 
            qCritical() << "Can't set number of stop bits!";
 
        }
 
    }
 
}
 

	
 
void PortControl::selectFlowControl(int flowControl)
 
{
 
    if (serialPort->isOpen())
 
    {
 
        if(!serialPort->setFlowControl((QSerialPort::FlowControl) flowControl))
 
        {
 
            qCritical() << "Can't set flow control option!";
 
        }
 
    }
 
}
 

	
 
void PortControl::togglePort()
 
{
 
    if (serialPort->isOpen())
 
    {
 
        pinUpdateTimer.stop();
 
        serialPort->close();
 
        qDebug() << "Closed port:" << serialPort->portName();
 
        emit portToggled(false);
 
    }
 
    else
 
    {
 
        // we get the port name from the edit text, which may not be
 
        // in the portList if user hasn't pressed Enter
 
        // Also note that, portText may not be the `portName`
 
        QString portText = ui->cbPortList->currentText();
 
        QString portName;
 
        int portIndex = portList.indexOf(portText);
 
        if (portIndex < 0) // not in list, add to model and update the selections
 
        {
 
            portList.appendRow(new PortListItem(portText));
 
            ui->cbPortList->setCurrentIndex(portList.rowCount()-1);
 
            tbPortList.setCurrentIndex(portList.rowCount()-1);
 
            portName = portText;
 
        }
 
        else
 
        {
 
            // get the port name from the data field
 
            portName = static_cast<PortListItem*>(portList.item(portIndex))->portName();
 
        }
 

	
 
        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
 
            serialPort->setDataTerminalReady(ui->ledDTR->isOn());
 
            serialPort->setRequestToSend(ui->ledRTS->isOn());
 

	
 
            // update pin signals
 
            updatePinLeds();
 
            pinUpdateTimer.start();
 

	
 
            qDebug() << "Opened port:" << serialPort->portName();
 
            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
 
        if (serialPort->isOpen())
 
        {
 
            togglePort();
 

	
 
            // open new selection by toggling
 
            togglePort();
 
        }
 
    }
 
}
 

	
 
QString PortControl::selectedPortName()
 
{
 
    QString portText = ui->cbPortList->currentText();
 
    int portIndex = portList.indexOf(portText);
 
    if (portIndex < 0) // not in the list yet
 
    {
 
        // return the displayed name as port name
 
        return portText;
 
    }
 
    else
 
    {
 
        // get the port name from the 'port list'
 
        return static_cast<PortListItem*>(portList.item(portIndex))->portName();
 
    }
 
}
 

	
 
QToolBar* PortControl::toolBar()
 
{
 
    return &portToolBar;
 
}
 

	
 
void PortControl::openActionTriggered(bool checked)
 
{
 
    togglePort();
 
}
 

	
 
void PortControl::onCbPortListActivated(int index)
 
{
 
    tbPortList.setCurrentIndex(index);
 
}
 

	
 
void PortControl::onTbPortListActivated(int index)
 
{
 
    ui->cbPortList->setCurrentIndex(index);
 
@@ -425,124 +432,161 @@ required privileges or device is already
 
        case QSerialPort::TimeoutError:
 
            qCritical() << "A timeout error occurred.";
 
            break;
 
        case QSerialPort::UnknownError:
 
#ifdef Q_OS_UNIX
 
            // Qt 5.2 gives "Invalid argument" with 'UnknownError'
 
            if (isPtsInvalidArgErr())
 
                break;
 
#endif
 
            qCritical() << "Unknown error! Error: " << serialPort->errorString();
 
            break;
 
        default:
 
            qCritical() << "Unhandled port error: " << error;
 
            break;
 
    }
 
}
 

	
 
void PortControl::updatePinLeds(void)
 
{
 
    auto pins = serialPort->pinoutSignals();
 
    ui->ledDCD->setOn(pins & QSerialPort::DataCarrierDetectSignal);
 
    ui->ledDSR->setOn(pins & QSerialPort::DataSetReadySignal);
 
    ui->ledRI->setOn(pins & QSerialPort::RingIndicatorSignal);
 
    ui->ledCTS->setOn(pins & QSerialPort::ClearToSendSignal);
 
}
 

	
 
QString PortControl::currentParityText()
 
{
 
    return paritySettingMap.value(
 
        (QSerialPort::Parity) parityButtons.checkedId());
 
}
 

	
 
QString PortControl::currentFlowControlText()
 
{
 
    if (flowControlButtons.checkedId() == QSerialPort::HardwareControl)
 
    {
 
        return "hardware";
 
    }
 
    else if (flowControlButtons.checkedId() == QSerialPort::SoftwareControl)
 
    {
 
        return "software";
 
    }
 
    else // no parity
 
    {
 
        return "none";
 
    }
 
}
 

	
 
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);
 
    settings->setValue(SG_Port_SelectedPort, selectedPortName());
 
    settings->setValue(SG_Port_BaudRate, ui->cbBaudRate->currentText());
 
    settings->setValue(SG_Port_Parity, currentParityText());
 
    settings->setValue(SG_Port_DataBits, dataBitsButtons.checkedId());
 
    settings->setValue(SG_Port_StopBits, stopBitsButtons.checkedId());
 
    settings->setValue(SG_Port_FlowControl, currentFlowControlText());
 
    settings->endGroup();
 
}
 

	
 
void PortControl::loadSettings(QSettings* settings)
 
{
 
    // make sure the port is closed
 
    if (serialPort->isOpen()) togglePort();
 

	
 
    settings->beginGroup(SettingGroup_Port);
 

	
 
    // set port name if it exists in the current list otherwise ignore
 
    QString portName = settings->value(SG_Port_SelectedPort, QString()).toString();
 
    if (!portName.isEmpty())
 
    {
 
        int index = portList.indexOfName(portName);
 
        if (index > -1) ui->cbPortList->setCurrentIndex(index);
 
    }
 

	
 
    // load baud rate setting if it exists in baud rate list
 
    QString baudSetting = settings->value(
 
        SG_Port_BaudRate, ui->cbBaudRate->currentText()).toString();
 
    int baudIndex = ui->cbBaudRate->findText(baudSetting);
 
    if (baudIndex > -1) ui->cbBaudRate->setCurrentIndex(baudIndex);
 

	
 
    // load parity setting
 
    QString parityText =
 
        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
 
    int stopBits = settings->value(SG_Port_StopBits, stopBitsButtons.checkedId()).toInt();
 
    if (stopBits == QSerialPort::OneStop)
 
    {
 
        ui->rb1StopBit->setChecked(true);
 
    }
 
    else if (stopBits == QSerialPort::TwoStop)
 
    {
 
        ui->rb2StopBit->setChecked(true);
 
    }
 

	
 
    // load flow control
 
    QString flowControlSetting =
 
        settings->value(SG_Port_FlowControl, currentFlowControlText()).toString();
 
    if (flowControlSetting == "hardware")
 
    {
 
        ui->rbHardwareControl->setChecked(true);
 
    }
 
    else if (flowControlSetting == "software")
 
    {
 
        ui->rbSoftwareControl->setChecked(true);
 
    }
 
    else
 
    {
 
        ui->rbNoFlowControl->setChecked(true);
 
    }
 

	
 
    settings->endGroup();
 
}
src/portcontrol.h
Show inline comments
 
@@ -2,101 +2,104 @@
 
  Copyright © 2017 Hasan Yavuz Özderya
 

	
 
  This file is part of serialplot.
 

	
 
  serialplot is free software: you can redistribute it and/or modify
 
  it under the terms of the GNU General Public License as published by
 
  the Free Software Foundation, either version 3 of the License, or
 
  (at your option) any later version.
 

	
 
  serialplot is distributed in the hope that it will be useful,
 
  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
  GNU General Public License for more details.
 

	
 
  You should have received a copy of the GNU General Public License
 
  along with serialplot.  If not, see <http://www.gnu.org/licenses/>.
 
*/
 

	
 
#ifndef PORTCONTROL_H
 
#define PORTCONTROL_H
 

	
 
#include <QWidget>
 
#include <QButtonGroup>
 
#include <QSerialPort>
 
#include <QStringList>
 
#include <QToolBar>
 
#include <QAction>
 
#include <QComboBox>
 
#include <QSettings>
 
#include <QTimer>
 

	
 
#include "portlist.h"
 

	
 
namespace Ui {
 
class PortControl;
 
}
 

	
 
class PortControl : public QWidget
 
{
 
    Q_OBJECT
 

	
 
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);
 

	
 
private:
 
    Ui::PortControl *ui;
 

	
 
    QButtonGroup parityButtons;
 
    QButtonGroup dataBitsButtons;
 
    QButtonGroup stopBitsButtons;
 
    QButtonGroup flowControlButtons;
 

	
 
    QToolBar portToolBar;
 
    QAction openAction;
 
    QAction loadPortListAction;
 
    QComboBox tbPortList;
 
    PortList portList;
 

	
 
    /// Used to refresh pinout signal leds periodically
 
    QTimer pinUpdateTimer;
 

	
 
    /// Returns the currently selected (entered) "portName" in the UI
 
    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 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);
 
    void onPortError(QSerialPort::SerialPortError error);
 
    void updatePinLeds(void);
 

	
 
signals:
 
    void portToggled(bool open);
 
};
 

	
 
#endif // PORTCONTROL_H
0 comments (0 inline, 0 general)