Changeset - d92b6daade5d
[Not reviewed]
stream
0 7 0
Hasan Yavuz Ă–ZDERYA - 8 years ago 2018-05-22 15:46:18
hy@ozderya.net
plotting works, only demo is tested

switching readers when demo is enabled breaks demo
7 files changed with 34 insertions and 15 deletions:
0 comments (0 inline, 0 general)
src/dataformatpanel.cpp
Show inline comments
 
@@ -26,50 +26,48 @@
 
#include "utils.h"
 
#include "setting_defines.h"
 

	
 
DataFormatPanel::DataFormatPanel(QSerialPort* port, QWidget *parent) :
 
    QWidget(parent),
 
    ui(new Ui::DataFormatPanel),
 
    bsReader(port, this),
 
    asciiReader(port, this),
 
    framedReader(port, this),
 
    demoReader(port, this)
 
{
 
    ui->setupUi(this);
 

	
 
    serialPort = port;
 
    paused = false;
 
    demoEnabled = false;
 

	
 
    // initalize default reader
 
    currentReader = &bsReader;
 
    bsReader.enable();
 
    ui->rbBinary->setChecked(true);
 
    ui->horizontalLayout->addWidget(bsReader.settingsWidget(), 1);
 
    connect(&bsReader, SIGNAL(numOfChannelsChanged(unsigned)),
 
            this, SIGNAL(numOfChannelsChanged(unsigned)));
 
    connect(&bsReader, SIGNAL(samplesPerSecondChanged(unsigned)),
 
            this, SIGNAL(samplesPerSecondChanged(unsigned)));
 

	
 
    // initalize reader selection buttons
 
    connect(ui->rbBinary, &QRadioButton::toggled, [this](bool checked)
 
            {
 
                if (checked) selectReader(&bsReader);
 
            });
 

	
 
    connect(ui->rbAscii, &QRadioButton::toggled, [this](bool checked)
 
            {
 
                if (checked) selectReader(&asciiReader);
 
            });
 

	
 
    connect(ui->rbFramed, &QRadioButton::toggled, [this](bool checked)
 
            {
 
                if (checked) selectReader(&framedReader);
 
            });
 

	
 
    // re-purpose numofchannels settings from actual reader settings to demo reader
 
    connect(this, &DataFormatPanel::numOfChannelsChanged,
 
            &demoReader, &DemoReader::setNumOfChannels);
 
}
 

	
 
DataFormatPanel::~DataFormatPanel()
 
{
 
@@ -77,72 +75,68 @@ DataFormatPanel::~DataFormatPanel()
 
}
 

	
 
unsigned DataFormatPanel::numChannels() const
 
{
 
    return currentReader->numChannels();
 
}
 

	
 
Source* DataFormatPanel::activeSource()
 
{
 
    return currentReader;
 
}
 

	
 
void DataFormatPanel::pause(bool enabled)
 
{
 
    paused = enabled;
 
    currentReader->pause(enabled);
 
    demoReader.pause(enabled);
 
}
 

	
 
void DataFormatPanel::enableDemo(bool enabled)
 
{
 
    if (enabled)
 
    {
 
        demoReader.enable();
 
        connect(&demoReader, &DemoReader::samplesPerSecondChanged,
 
                this, &DataFormatPanel::samplesPerSecondChanged);
 
        emit sourceChanged(&demoReader);
 
    }
 
    else
 
    {
 
        demoReader.enable(false);
 
        disconnect(&demoReader, 0, this, 0);
 
        emit sourceChanged(currentReader);
 
    }
 
    demoEnabled = enabled;
 
}
 

	
 
void DataFormatPanel::selectReader(AbstractReader* reader)
 
{
 
    currentReader->enable(false);
 
    reader->enable();
 

	
 
    // re-connect signals
 
    disconnect(currentReader, 0, this, 0);
 
    connect(reader, SIGNAL(numOfChannelsChanged(unsigned)),
 
            this, SIGNAL(numOfChannelsChanged(unsigned)));
 
    connect(reader, SIGNAL(samplesPerSecondChanged(unsigned)),
 
            this, SIGNAL(samplesPerSecondChanged(unsigned)));
 

	
 
    // switch the settings widget
 
    ui->horizontalLayout->removeWidget(currentReader->settingsWidget());
 
    currentReader->settingsWidget()->hide();
 
    ui->horizontalLayout->addWidget(reader->settingsWidget(), 1);
 
    reader->settingsWidget()->show();
 

	
 
    // notify if number of channels is different
 
    if (currentReader->numChannels() != reader->numChannels())
 
    {
 
        emit numOfChannelsChanged(reader->numChannels());
 
    }
 

	
 
    reader->pause(paused);
 

	
 
    currentReader = reader;
 
    emit sourceChanged(currentReader);
 
}
 

	
 
void DataFormatPanel::saveSettings(QSettings* settings)
 
{
 
    settings->beginGroup(SettingGroup_DataFormat);
 

	
 
    // save selected format
src/mainwindow.cpp
Show inline comments
 
@@ -185,76 +185,81 @@ MainWindow::MainWindow(QWidget *parent) 
 
                     [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 data arrays and plot
 
    // 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,
 
                     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());
 

	
 
    // 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())
 
    {
 
@@ -320,48 +325,60 @@ Try fixing the permissions of file: %1, 
 
    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)
 
{
 
    // disconnect previous source
 
    auto currentSource = stream.connectedSource();
 
    if (currentSource != nullptr)
 
    {
 
        currentSource->disconnect((Sink*) &stream);
 
    }
 
    // connect to new source
 
    source->connectSink(&stream);
 
}
 

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

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

	
 
void MainWindow::onSpsChanged(unsigned sps)
 
{
 
    spsLabel.setText(QString::number(sps) + "sps");
 
}
 

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

	
 
void MainWindow::enableDemo(bool enabled)
src/mainwindow.h
Show inline comments
 
@@ -91,38 +91,38 @@ private:
 
    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 onNumOfSamplesChanged(int value);
 

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

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

	
 
#endif // MAINWINDOW_H
src/sink.cpp
Show inline comments
 
@@ -34,32 +34,37 @@ void Sink::disconnectFollower(Sink* sink
 

	
 
    followers.removeOne(sink);
 
}
 

	
 
void Sink::feedIn(const SamplePack& data)
 
{
 
    for (auto sink : followers)
 
    {
 
        sink->feedIn(data);
 
    }
 
}
 

	
 
void Sink::setNumChannels(unsigned nc, bool x)
 
{
 
    _numChannels = nc;
 
    _hasX = x;
 
    for (auto sink : followers)
 
    {
 
        sink->setNumChannels(nc, x);
 
    }
 
}
 

	
 
void Sink::setSource(const Source* s)
 
{
 
    Q_ASSERT((source == NULL) != (s == NULL));
 
    Q_ASSERT((source == nullptr) != (s == nullptr));
 
    source = s;
 
}
 

	
 
const Source* Sink::connectedSource() const
 
{
 
    return source;
 
}
 

	
 
Source* Sink::connectedSource()
 
{
 
    return const_cast<Source*>(static_cast<const Sink&>(*this).connectedSource());
 
}
src/sink.h
Show inline comments
 
@@ -18,53 +18,54 @@
 
*/
 

	
 
#ifndef SINK_H
 
#define SINK_H
 

	
 
#include <QList>
 
#include "samplepack.h"
 

	
 
class Source;
 

	
 
class Sink
 
{
 
public:
 
    /// Placeholder virtual destructor
 
    virtual ~Sink() {};
 

	
 
    /// Connects a sink to get any data that this sink
 
    /// gets. Connecting an already connected sink is an error.
 
    void connectFollower(Sink* sink);
 

	
 
    /// Disconnects a follower. Disconnecting an unconnected sink is
 
    /// an error.
 
    void disconnectFollower(Sink* sink);
 

	
 
    /// Returns the connected source. `NULL` if it's not connected.
 
    /// Returns the connected source. `nullptr` if it's not connected.
 
    const Source* connectedSource() const;
 
    Source* connectedSource();
 

	
 
protected:
 
    /// Entry point for incoming data. Re-implementations should
 
    /// call this function to feed followers.
 
    virtual void feedIn(const SamplePack& data);
 

	
 
    /// Is set by connected source. Re-implementations should call
 
    /// this function to update followers.
 
    virtual void setNumChannels(unsigned nc, bool x);
 

	
 
    /// Set by the connected source when its connected. When
 
    /// disconnecting it's set to `NULL`.
 
    ///
 
    /// @important Trying to connect a source while its already
 
    /// connected is an error.
 
    void setSource(const Source* s);
 

	
 
    friend Source;
 

	
 
private:
 
    QList<Sink*> followers;
 
    const Source* source = NULL;   ///< source that this sink is connected to
 
    const Source* source = nullptr;   ///< source that this sink is connected to
 
    bool _hasX;
 
    unsigned _numChannels;
 
};
 

	
 
#endif // SINK_H
src/source.cpp
Show inline comments
 
@@ -4,71 +4,71 @@
 
  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 <QtGlobal>
 

	
 
#include "source.h"
 

	
 
Source::~Source()
 
{
 
    for (auto sink : sinks)
 
    {
 
        sink->setSource(NULL);
 
        sink->setSource(nullptr);
 
    }
 
}
 

	
 
void Source::connectSink(Sink* sink)
 
{
 
    Q_ASSERT(!sinks.contains(sink));
 
    Q_ASSERT(sink->connectedSource() == NULL);
 
    Q_ASSERT(sink->connectedSource() == nullptr);
 

	
 
    sinks.append(sink);
 
    sink->setSource(this);
 
    sink->setNumChannels(numChannels(), hasX());
 
}
 

	
 
void Source::disconnect(Sink* sink)
 
{
 
    Q_ASSERT(sinks.contains(sink));
 
    Q_ASSERT(sink->connectedSource() == this);
 

	
 
    sink->setSource(NULL);
 
    sink->setSource(nullptr);
 
    sinks.removeOne(sink);
 
}
 

	
 
void Source::disconnectSinks()
 
{
 
    while (!sinks.isEmpty())
 
    {
 
        auto sink = sinks.takeFirst();
 
        sink->setSource(NULL);
 
        sink->setSource(nullptr);
 
    }
 
}
 

	
 
void Source::feedOut(const SamplePack& data) const
 
{
 
    for (auto sink : sinks)
 
    {
 
        sink->feedIn(data);
 
    }
 
}
 

	
 
void Source::updateNumChannels() const
 
{
 
    for (auto sink : sinks)
 
    {
 
        sink->setNumChannels(numChannels(), hasX());
 
    }
 
}
src/stream.cpp
Show inline comments
 
@@ -136,48 +136,50 @@ void Stream::setNumChannels(unsigned nc,
 
        emit numChannelsChanged(nc);
 
    }
 

	
 
    Sink::setNumChannels(nc, x);
 
}
 

	
 
void Stream::feedIn(const SamplePack& data)
 
{
 
    Q_ASSERT(data.numChannels() == numChannels() &&
 
             data.hasX() == hasX());
 

	
 
    if (_paused) return;
 

	
 
    unsigned ns = data.numSamples();
 
    if (_hasx)
 
    {
 
        static_cast<RingBuffer*>(xData)->addSamples(data.xData(), ns);
 
    }
 
    for (unsigned i = 0; i < numChannels(); i++)
 
    {
 
        static_cast<RingBuffer*>(channels[i]->yData())->addSamples(data.data(i), ns);
 
    }
 

	
 
    Sink::feedIn(data);
 

	
 
    emit dataAdded();
 
}
 

	
 
void Stream::pause(bool paused)
 
{
 
    _paused = paused;
 
}
 

	
 
void Stream::clear()
 
{
 
    for (auto c : channels)
 
    {
 
        static_cast<RingBuffer*>(c->yData())->clear();
 
    }
 
}
 

	
 
void Stream::setNumSamples(unsigned value)
 
{
 
    if (value == _numSamples) return;
 
    _numSamples = value;
 

	
 
    xData->resize(value);
 
    for (auto c : channels)
 
    {
 
        static_cast<RingBuffer*>(c->yData())->resize(value);
0 comments (0 inline, 0 general)