Changeset - 5faf2cdfb6a5
[Not reviewed]
stream
0 5 2
Hasan Yavuz ÖZDERYA - 8 years ago 2018-05-26 17:26:08
hy@ozderya.net
added new sample per second counter
7 files changed with 104 insertions and 15 deletions:
0 comments (0 inline, 0 general)
CMakeLists.txt
Show inline comments
 
@@ -55,192 +55,193 @@ endif ()
 
set(BUILD_LEDWIDGET true CACHE BOOL "Download and build LedWidget automatically.")
 
if (BUILD_LEDWIDGET)
 
  include(BuildLedWidget)
 
else (BUILD_LEDWIDGET)
 
  include(FindLedWidget)
 
endif (BUILD_LEDWIDGET)
 

	
 
# includes
 
include_directories("./src"
 
  ${QWT_INCLUDE_DIR}
 
  ${QTCOLORWIDGETS_INCLUDE_DIRS}
 
  ${LEDWIDGET_INCLUDE_DIR}
 
  )
 

	
 
# flags
 
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${QTCOLORWIDGETS_FLAGS}")
 

	
 
# wrap UI and resource files
 
qt5_wrap_ui(UI_FILES
 
  src/mainwindow.ui
 
  src/portcontrol.ui
 
  src/about_dialog.ui
 
  src/snapshotview.ui
 
  src/commandpanel.ui
 
  src/commandwidget.ui
 
  src/dataformatpanel.ui
 
  src/plotcontrolpanel.ui
 
  src/recordpanel.ui
 
  src/numberformatbox.ui
 
  src/endiannessbox.ui
 
  src/binarystreamreadersettings.ui
 
  src/asciireadersettings.ui
 
  src/framedreadersettings.ui
 
  src/updatecheckdialog.ui
 
  )
 

	
 
if (WIN32)
 
  qt5_add_resources(RES_FILES misc/icons.qrc misc/winicons.qrc)
 
else (WIN32)
 
  qt5_add_resources(RES_FILES misc/icons.qrc)
 
endif (WIN32)
 

	
 
add_executable(${PROGRAM_NAME} WIN32
 
  src/main.cpp
 
  src/mainwindow.cpp
 
  src/portcontrol.cpp
 
  src/plot.cpp
 
  src/zoomer.cpp
 
  src/scrollzoomer.cpp
 
  src/scrollbar.cpp
 
  src/hidabletabwidget.cpp
 
  src/scalepicker.cpp
 
  src/scalezoomer.cpp
 
  src/portlist.cpp
 
  src/snapshot.cpp
 
  src/snapshotview.cpp
 
  src/snapshotmanager.cpp
 
  src/plotsnapshotoverlay.cpp
 
  src/commandpanel.cpp
 
  src/commandwidget.cpp
 
  src/commandedit.cpp
 
  src/dataformatpanel.cpp
 
  src/plotcontrolpanel.cpp
 
  src/recordpanel.cpp
 
  src/datarecorder.cpp
 
  src/tooltipfilter.cpp
 
  src/sneakylineedit.cpp
 
  src/stream.cpp
 
  src/streamchannel.cpp
 
  src/channelinfomodel.cpp
 
  src/ringbuffer.cpp
 
  src/ringbuffer.cpp
 
  src/indexbuffer.cpp
 
  src/framebufferseries.cpp
 
  src/numberformatbox.cpp
 
  src/endiannessbox.cpp
 
  src/abstractreader.cpp
 
  src/binarystreamreader.cpp
 
  src/binarystreamreadersettings.cpp
 
  src/asciireader.cpp
 
  src/asciireadersettings.cpp
 
  src/demoreader.cpp
 
  src/framedreader.cpp
 
  src/framedreadersettings.cpp
 
  src/plotmanager.cpp
 
  src/plotmenu.cpp
 
  src/barplot.cpp
 
  src/barchart.cpp
 
  src/barscaledraw.cpp
 
  src/numberformat.cpp
 
  src/updatechecker.cpp
 
  src/versionnumber.cpp
 
  src/updatecheckdialog.cpp
 
  src/samplepack.cpp
 
  src/source.cpp
 
  src/sink.cpp
 
  src/samplecounter.cpp
 
  misc/windows_icon.rc
 
  ${UI_FILES}
 
  ${RES_FILES}
 
  )
 

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

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

	
 
if (BUILD_QTCOLORWIDGETS)
 
  add_dependencies(${PROGRAM_NAME} QCW)
 
endif ()
 

	
 
if (BUILD_LEDWIDGET)
 
  add_dependencies(${PROGRAM_NAME} LEDW)
 
endif (BUILD_LEDWIDGET)
 

	
 

	
 
# 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}\\\" ")
 

	
 
# 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)
src/dataformatpanel.h
Show inline comments
 
/*
 
  Copyright © 2018 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 DATAFORMATPANEL_H
 
#define DATAFORMATPANEL_H
 

	
 
#include <QWidget>
 
#include <QButtonGroup>
 
#include <QTimer>
 
#include <QSerialPort>
 
#include <QList>
 
#include <QSettings>
 
#include <QtGlobal>
 

	
 
#include "binarystreamreader.h"
 
#include "asciireader.h"
 
#include "demoreader.h"
 
#include "framedreader.h"
 
#include "datarecorder.h"
 

	
 
namespace Ui {
 
class DataFormatPanel;
 
}
 

	
 
class DataFormatPanel : public QWidget
 
{
 
    Q_OBJECT
 

	
 
public:
 
    explicit DataFormatPanel(QSerialPort* port, QWidget* parent = 0);
 
    ~DataFormatPanel();
 

	
 
    /// Returns currently selected number of channels
 
    unsigned numChannels() const;
 
    /// Returns active source (reader)
 
    Source* activeSource();
 
    /// Stores data format panel settings into a `QSettings`
 
    void saveSettings(QSettings* settings);
 
    /// Loads data format panel settings from a `QSettings`.
 
    void loadSettings(QSettings* settings);
 

	
 
public slots:
 
    void pause(bool);
 
    void enableDemo(bool); // demo shouldn't be enabled when port is open
 

	
 
signals:
 
    /// Active (selected) reader has changed.
 
    void sourceChanged(Source* source);
 
    void numOfChannelsChanged(unsigned);
 
    void samplesPerSecondChanged(unsigned);
 

	
 
private:
 
    Ui::DataFormatPanel *ui;
 

	
 
    QSerialPort* serialPort;
 

	
 
    BinaryStreamReader bsReader;
 
    AsciiReader asciiReader;
 
    FramedReader framedReader;
 
    /// Currently selected reader
 
    AbstractReader* currentReader;
 
    /// Disable current reader and enable a another one
 
    void selectReader(AbstractReader* reader);
 

	
 
    bool paused;
 

	
 
    bool demoEnabled;
 
    DemoReader demoReader;
 
};
 

	
 
#endif // DATAFORMATPANEL_H
src/demoreader.h
Show inline comments
 
/*
 
  Copyright © 2018 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 DEMOREADER_H
 
#define DEMOREADER_H
 

	
 
#include <QTimer>
 

	
 
#include "abstractreader.h"
 

	
 
/**
 
 * This is a special case of reader implementation and should be used
 
 * with care.
 
 *
 
 * There is no settings widget. Number of channels should be set from
 
 * currently selected actual readers settings widget.
 
 *
 
 * This reader should not be enabled when port is open!
 
 */
 
class DemoReader : public AbstractReader
 
{
 
    Q_OBJECT
 

	
 
public:
 
    explicit DemoReader(QIODevice* device, QObject* parent = 0);
 

	
 
    /// Demo reader is an exception so this function returns NULL
 
    QWidget* settingsWidget();
 

	
 
    unsigned numChannels() const;
 

	
 
    void enable(bool enabled = true);
 

	
 
public slots:
 
    void pause(bool);
 

	
 
    /// Sets the number of channels, this doesn't trigger a `numOfChannelsChanged` signal.
 
    void setNumOfChannels(unsigned value);
 

	
 
signals:
 
    // TODO: added for build only, remove later
 
    void samplesPerSecondChanged(unsigned);
 

	
 
private:
 
    bool paused;
 
    unsigned _numChannels;
 
    QTimer timer;
 
    int count;
 

	
 
private slots:
 
    void demoTimerTimeout();
 
};
 

	
 
#endif // DEMOREADER_H
src/mainwindow.cpp
Show inline comments
 
@@ -130,337 +130,337 @@ MainWindow::MainWindow(QWidget *parent) 
 
    QObject::connect(ui->actionHelpAbout, &QAction::triggered,
 
              &aboutDialog, &QWidget::show);
 

	
 
    QObject::connect(ui->actionCheckUpdate, &QAction::triggered,
 
              &updateCheckDialog, &QWidget::show);
 

	
 
    QObject::connect(ui->actionReportBug, &QAction::triggered,
 
                     [](){QDesktopServices::openUrl(QUrl(BUG_REPORT_URL));});
 

	
 
    // File menu signals
 
    QObject::connect(ui->actionExportCsv, &QAction::triggered,
 
                     this, &MainWindow::onExportCsv);
 

	
 
    QObject::connect(ui->actionSaveSettings, &QAction::triggered,
 
                     this, &MainWindow::onSaveSettings);
 

	
 
    QObject::connect(ui->actionLoadSettings, &QAction::triggered,
 
                     this, &MainWindow::onLoadSettings);
 

	
 
    ui->actionQuit->setShortcutContext(Qt::ApplicationShortcut);
 

	
 
    QObject::connect(ui->actionQuit, &QAction::triggered,
 
                     this, &MainWindow::close);
 

	
 
    // port control signals
 
    QObject::connect(&portControl, &PortControl::portToggled,
 
                     this, &MainWindow::onPortToggled);
 

	
 
    // plot control signals
 
    connect(&plotControlPanel, &PlotControlPanel::numOfSamplesChanged,
 
            this, &MainWindow::onNumOfSamplesChanged);
 

	
 
    connect(&plotControlPanel, &PlotControlPanel::numOfSamplesChanged,
 
            plotMan, &PlotManager::setNumOfSamples);
 

	
 
    connect(&plotControlPanel, &PlotControlPanel::yScaleChanged,
 
            plotMan, &PlotManager::setYAxis);
 

	
 
    connect(&plotControlPanel, &PlotControlPanel::xScaleChanged,
 
            plotMan, &PlotManager::setXAxis);
 

	
 
    connect(&plotControlPanel, &PlotControlPanel::plotWidthChanged,
 
            plotMan, &PlotManager::setPlotWidth);
 

	
 
    // plot toolbar signals
 
    QObject::connect(ui->actionClear, SIGNAL(triggered(bool)),
 
                     this, SLOT(clearPlot()));
 

	
 
    QObject::connect(snapshotMan.takeSnapshotAction(), &QAction::triggered,
 
                     plotMan, &PlotManager::flashSnapshotOverlay);
 

	
 
    QObject::connect(ui->actionPause, &QAction::triggered,
 
                     &stream, &Stream::pause);
 

	
 
    QObject::connect(ui->actionPause, &QAction::triggered,
 
                     [this](bool enabled)
 
                     {
 
                         if (enabled && !recordPanel.recordPaused())
 
                         {
 
                             dataFormatPanel.pause(true);
 
                         }
 
                         else
 
                         {
 
                             dataFormatPanel.pause(false);
 
                         }
 
                     });
 

	
 
    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
 
    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);
 
    QObject::connect(&dataFormatPanel,
 
                     &DataFormatPanel::samplesPerSecondChanged,
 
    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::setStreamSource);
 
    setStreamSource(dataFormatPanel.activeSource());
 
            this, &MainWindow::onSourceChanged);
 
    onSourceChanged(dataFormatPanel.activeSource());
 

	
 
    // load default settings
 
    QSettings settings("serialplot", "serialplot");
 
    loadAllSettings(&settings);
 

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

	
 
void MainWindow::onPortToggled(bool open)
 
{
 
    // make sure demo mode is disabled
 
    if (open && isDemoRunning()) enableDemo(false);
 
    ui->actionDemoMode->setEnabled(!open);
 
}
 

	
 
void MainWindow::setStreamSource(Source* source)
 
void MainWindow::onSourceChanged(Source* source)
 
{
 
    // connect to new source
 
    source->connectSink(&stream);
 
    source->connectSink(&sampleCounter);
 
}
 

	
 
void MainWindow::clearPlot()
 
{
 
    stream.clear();
 
    plotMan->replot();
 
}
 

	
 
void MainWindow::onNumOfSamplesChanged(int value)
 
{
 
    numOfSamples = value;
 
    stream.setNumSamples(value);
 
    plotMan->replot();
 
}
 

	
 
void MainWindow::onSpsChanged(unsigned sps)
 
void MainWindow::onSpsChanged(float sps)
 
{
 
    spsLabel.setText(QString::number(sps) + "sps");
 
    int precision = sps < 1. ? 3 : 0;
 
    spsLabel.setText(QString::number(sps, 'f', precision) + "sps");
 
}
 

	
 
bool MainWindow::isDemoRunning()
 
{
 
    return ui->actionDemoMode->isChecked();
 
}
 

	
 
void MainWindow::enableDemo(bool enabled)
 
{
 
    if (enabled)
 
    {
 
        if (!serialPort.isOpen())
 
        {
 
            dataFormatPanel.enableDemo(true);
 
        }
 
        else
 
        {
 
            ui->actionDemoMode->setChecked(false);
 
        }
 
    }
 
    else
 
    {
 
        dataFormatPanel.enableDemo(false);
 
        ui->actionDemoMode->setChecked(false);
 
    }
 
}
 

	
 
void MainWindow::showSecondary(QWidget* wid)
 
{
 
    if (secondaryPlot != NULL)
 
    {
 
        secondaryPlot->deleteLater();
 
    }
 

	
 
    secondaryPlot = wid;
 
    ui->splitter->addWidget(wid);
 
    ui->splitter->setStretchFactor(0, 1);
 
    ui->splitter->setStretchFactor(1, 0);
 
}
 

	
 
void MainWindow::hideSecondary()
 
{
 
    if (secondaryPlot == NULL)
 
    {
 
        qFatal("Secondary plot doesn't exist!");
 
    }
 

	
 
    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 &msg)
src/mainwindow.h
Show inline comments
 
/*
 
  Copyright © 2018 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 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"
 

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

	
 
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;
 
    UpdateCheckDialog updateCheckDialog;
 

	
 
    /// 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 setStreamSource(Source* source);
 
    void onSourceChanged(Source* source);
 
    void onNumOfSamplesChanged(int value);
 

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

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

	
 
#endif // MAINWINDOW_H
src/samplecounter.cpp
Show inline comments
 
new file 100644
 
/*
 
  Copyright © 2018 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 <QDateTime>
 
#include "samplecounter.h"
 

	
 
SampleCounter::SampleCounter()
 
{
 
    prevTimeMs = QDateTime::currentMSecsSinceEpoch();
 
    count = 0;
 
}
 

	
 
#include <QtDebug>
 

	
 
void SampleCounter::feedIn(const SamplePack& data)
 
{
 
    count += data.numSamples();
 

	
 
    qint64 current = QDateTime::currentMSecsSinceEpoch();
 
    auto diff = current - prevTimeMs;
 
    if (diff > 1000) // 1sec
 
    {
 
        emit spsChanged(1000 * float(count) / diff);
 

	
 
        prevTimeMs = current;
 
        count = 0;
 
    }
 
}
src/samplecounter.h
Show inline comments
 
new file 100644
 
/*
 
  Copyright © 2018 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 SAMPLECOUNTER_H
 
#define SAMPLECOUNTER_H
 

	
 
#include <QObject>
 
#include "sink.h"
 

	
 
/// A `Sink` class for counting and reporting number of samples per second.
 
class SampleCounter : public QObject, public Sink
 
{
 
    Q_OBJECT
 

	
 
public:
 
    SampleCounter();
 

	
 
protected:
 
    // implementations for `Sink`
 
    virtual void feedIn(const SamplePack& data);
 

	
 
signals:
 
    /// Emitted per second if SPS value has changed.
 
    void spsChanged(float value);
 

	
 
private:
 
    qint64 prevTimeMs;
 
    unsigned count;
 
};
 

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