diff --git a/CMakeLists.txt b/CMakeLists.txt --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -126,6 +126,7 @@ add_executable(${PROGRAM_NAME} WIN32 src/ringbuffer.cpp src/ringbuffer.cpp src/indexbuffer.cpp + src/readonlybuffer.cpp src/framebufferseries.cpp src/numberformatbox.cpp src/endiannessbox.cpp diff --git a/src/plotmanager.cpp b/src/plotmanager.cpp --- a/src/plotmanager.cpp +++ b/src/plotmanager.cpp @@ -47,7 +47,6 @@ PlotManager::PlotManager(QWidget* plotAr {}); // roles ignored }); - connect(stream, &Stream::numChannelsChanged, this, &PlotManager::onNumChannelsChanged); connect(stream, &Stream::dataAdded, this, &PlotManager::replot); @@ -71,7 +70,7 @@ PlotManager::PlotManager(QWidget* plotAr for (unsigned ci = 0; ci < snapshot->numChannels(); ci++) { - addCurve(snapshot->channelName(ci), snapshot->data[ci]); + addCurve(snapshot->channelName(ci), snapshot->yData[ci]); } connect(infoModel, &QAbstractItemModel::dataChanged, @@ -338,13 +337,6 @@ void PlotManager::addCurve(QString title _addCurve(curve); } -void PlotManager::addCurve(QString title, QVector data) -{ - auto curve = new QwtPlotCurve(title); - curve->setSamples(data); - _addCurve(curve); -} - void PlotManager::_addCurve(QwtPlotCurve* curve) { // store and init the curve diff --git a/src/plotmanager.h b/src/plotmanager.h --- a/src/plotmanager.h +++ b/src/plotmanager.h @@ -50,8 +50,6 @@ public: /// Add a new curve with title and buffer. A color is /// automatically chosen for curve. void addCurve(QString title, const FrameBuffer* buffer); - /// Alternative of `addCurve` for static curve data (snapshots). - void addCurve(QString title, QVector data); /// Removes curves from the end void removeCurves(unsigned number); /// Returns current number of curves known by plot manager diff --git a/src/readonlybuffer.cpp b/src/readonlybuffer.cpp --- a/src/readonlybuffer.cpp +++ b/src/readonlybuffer.cpp @@ -1,5 +1,5 @@ /* - Copyright © 2017 Hasan Yavuz Özderya + Copyright © 2018 Hasan Yavuz Özderya This file is part of serialplot. @@ -18,13 +18,14 @@ */ #include +#include #include "readonlybuffer.h" ReadOnlyBuffer::ReadOnlyBuffer(const FrameBuffer* source) : ReadOnlyBuffer(source, 0, source->size()) { - // empty + // intentionally empty, see ↑ } ReadOnlyBuffer::ReadOnlyBuffer(const FrameBuffer* source, unsigned start, unsigned n) @@ -47,22 +48,18 @@ ReadOnlyBuffer::ReadOnlyBuffer(const Fra } else { - // TODO: code duplication with RingBuffer::updateLimits, consider reuse - _limits.start = data[0]; - _limits.end = data[0]; + updateLimits(); + } +} - for (unsigned i = 0; i < _size; i++) - { - if (data[i] > _limits.end) - { - _limits.end = data[i]; - } - else if (data[i] < _limits.start) - { - _limits.start = data[i]; - } - } - } +ReadOnlyBuffer::ReadOnlyBuffer(const double* source, unsigned ssize) +{ + Q_ASSERT(source != nullptr && ssize); + + _size = ssize; + data = new double[_size]; + memcpy(data, source, sizeof(double) * ssize); + updateLimits(); } ReadOnlyBuffer::~ReadOnlyBuffer() @@ -84,3 +81,23 @@ Range ReadOnlyBuffer::limits() const { return _limits; } + +void ReadOnlyBuffer::updateLimits() +{ + Q_ASSERT(_size); + + _limits.start = data[0]; + _limits.end = data[0]; + + for (unsigned i = 0; i < _size; i++) + { + if (data[i] > _limits.end) + { + _limits.end = data[i]; + } + else if (data[i] < _limits.start) + { + _limits.start = data[i]; + } + } +} diff --git a/src/readonlybuffer.h b/src/readonlybuffer.h --- a/src/readonlybuffer.h +++ b/src/readonlybuffer.h @@ -41,6 +41,9 @@ public: /// otherwise it's an error. ReadOnlyBuffer(const FrameBuffer* source, unsigned start, unsigned n); + /// Creates a buffer with data copied from an array + ReadOnlyBuffer(const double* source, unsigned ssize); + ~ReadOnlyBuffer(); virtual unsigned size() const; @@ -51,6 +54,9 @@ private: double* data; ///< data storage unsigned _size; ///< data size Range _limits; ///< limits cache + + // TODO: duplicate with `RingBuffer` + void updateLimits(); ///< Updates limits cache }; #endif // READONLYBUFFER_H diff --git a/src/snapshot.cpp b/src/snapshot.cpp --- a/src/snapshot.cpp +++ b/src/snapshot.cpp @@ -110,12 +110,12 @@ void Snapshot::setName(QString name) unsigned Snapshot::numChannels() const { - return data.size(); + return yData.size(); } unsigned Snapshot::numSamples() const { - return data[0].size(); + return yData[0]->size(); } const ChannelInfoModel* Snapshot::infoModel() const @@ -135,31 +135,27 @@ QString Snapshot::channelName(unsigned c void Snapshot::save(QString fileName) { - // TODO: remove code duplication (MainWindow::onExportCsv) QSaveFile file(fileName); if (file.open(QIODevice::WriteOnly | QIODevice::Text)) { QTextStream fileStream(&file); - unsigned numOfChannels = data.size(); - unsigned numOfSamples = data[0].size(); - // print header - for (unsigned int ci = 0; ci < numOfChannels; ci++) + for (unsigned int ci = 0; ci < numChannels(); ci++) { fileStream << channelName(ci); - if (ci != numOfChannels-1) fileStream << ","; + if (ci != numChannels()-1) fileStream << ","; } fileStream << '\n'; // print rows - for (unsigned int i = 0; i < numOfSamples; i++) + for (unsigned int i = 0; i < numSamples(); i++) { - for (unsigned int ci = 0; ci < numOfChannels; ci++) + for (unsigned int ci = 0; ci < numChannels(); ci++) { - fileStream << data[ci][i].y(); - if (ci != numOfChannels-1) fileStream << ","; + fileStream << yData[ci]->sample(i); + if (ci != numChannels()-1) fileStream << ","; } fileStream << '\n'; } diff --git a/src/snapshot.h b/src/snapshot.h --- a/src/snapshot.h +++ b/src/snapshot.h @@ -27,6 +27,7 @@ #include #include "channelinfomodel.h" +#include "readonlybuffer.h" class SnapshotView; class MainWindow; @@ -39,7 +40,8 @@ public: Snapshot(MainWindow* parent, QString name, ChannelInfoModel infoModel, bool saved = false); ~Snapshot(); - QVector> data; + // TODO: yData of snapshot shouldn't be public, preferable should be handled in constructor + QVector yData; QAction* showAction(); QAction* deleteAction(); diff --git a/src/snapshotmanager.cpp b/src/snapshotmanager.cpp --- a/src/snapshotmanager.cpp +++ b/src/snapshotmanager.cpp @@ -68,18 +68,9 @@ Snapshot* SnapshotManager::makeSnapshot( QString name = QTime::currentTime().toString("'Snapshot ['HH:mm:ss']'"); auto snapshot = new Snapshot(_mainWindow, name, *(_stream->infoModel())); - unsigned numChannels = _stream->numChannels(); - unsigned numSamples = _stream->numSamples(); - - for (unsigned ci = 0; ci < numChannels; ci++) + for (unsigned ci = 0; ci < _stream->numChannels(); ci++) { - snapshot->data.append(QVector(numSamples)); - auto x = _stream->channel(ci)->xData(); - auto y = _stream->channel(ci)->yData(); - for (unsigned i = 0; i < numSamples; i++) - { - snapshot->data[ci][i] = QPointF(x->sample(i), y->sample(i)); - } + snapshot->yData.append(new ReadOnlyBuffer(_stream->channel(ci)->yData())); } return snapshot; @@ -160,7 +151,7 @@ void SnapshotManager::loadSnapshotFromFi unsigned numOfChannels = channelNames.size(); // read data - QVector> data(numOfChannels); + QVector> data(numOfChannels); unsigned lineNum = 1; while (file.canReadLine()) { @@ -188,17 +179,20 @@ void SnapshotManager::loadSnapshotFromFi << "\" to double."; return; } - data[ci].append(QPointF(lineNum-1, y)); + data[ci].append(y); } lineNum++; } - ChannelInfoModel channelInfo(channelNames); - + // create snapshot auto snapshot = new Snapshot( _mainWindow, QFileInfo(fileName).baseName(), ChannelInfoModel(channelNames), true); - snapshot->data = data; + + for (unsigned ci = 0; ci < numOfChannels; ci++) + { + snapshot->yData.append(new ReadOnlyBuffer(data[ci].data(), data[ci].size())); + } addSnapshot(snapshot, false); }