@@ -30,24 +30,31 @@ AsciiReader::AsciiReader(QIODevice* devi
{
paused = false;
discardFirstLine = true;
_numOfChannels = _settingsWidget.numOfChannels();
autoNumOfChannels = (_numOfChannels == NUMOFCHANNELS_AUTO);
delimiter = _settingsWidget.delimiter();
connect(&_settingsWidget, &AsciiReaderSettings::numOfChannelsChanged,
[this](unsigned value)
_numOfChannels = value;
if (!autoNumOfChannels)
emit numOfChannelsChanged(value);
}
});
connect(&_settingsWidget, &AsciiReaderSettings::delimiterChanged,
[this](QChar d)
delimiter = d;
connect(device, &QIODevice::aboutToClose, [this](){discardFirstLine=true;});
QWidget* AsciiReader::settingsWidget()
return &_settingsWidget;
@@ -87,13 +94,13 @@ void AsciiReader::pause(bool enabled)
void AsciiReader::onDataReady()
while(_device->canReadLine())
QByteArray line = _device->readLine();
QString line = QString(_device->readLine());
// discard only once when we just started reading
if (discardFirstLine)
discardFirstLine = false;
continue;
@@ -113,13 +120,13 @@ void AsciiReader::onDataReady()
// empty lines in the input when the port is just opened.
if (line.isEmpty())
auto separatedValues = line.split(',');
auto separatedValues = line.split(delimiter, QString::SkipEmptyParts);
unsigned numReadChannels; // effective number of channels to read
unsigned numComingChannels = separatedValues.length();
if (autoNumOfChannels)
@@ -140,22 +147,24 @@ void AsciiReader::onDataReady()
numReadChannels = separatedValues.length();
qWarning() << "Incoming data is missing data for some channels!";
qWarning() << "Read line: " << line;
// parse read line
unsigned numDataBroken = 0;
double* channelSamples = new double[_numOfChannels]();
for (unsigned ci = 0; ci < numReadChannels; ci++)
bool ok;
channelSamples[ci] = separatedValues[ci].toDouble(&ok);
if (!ok)
qWarning() << "Data parsing error for channel: " << ci;
channelSamples[ci] = 0;
numDataBroken++;
// commit data
addData(channelSamples, _numOfChannels);
@@ -45,12 +45,13 @@ public slots:
private:
AsciiReaderSettings _settingsWidget;
unsigned _numOfChannels;
/// number of channels will be determined from incoming data
unsigned autoNumOfChannels;
QChar delimiter; ///< selected column delimiter
bool paused;
// We may have (usually true) started reading in the middle of a
// line, so its a better idea to just discard first line.
bool discardFirstLine;
/*
Copyright © 2016 Hasan Yavuz Özderya
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
@@ -14,26 +14,41 @@
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 <QRegularExpressionValidator>
#include <QRegularExpression>
#include "utils.h"
#include "setting_defines.h"
#include "asciireadersettings.h"
#include "ui_asciireadersettings.h"
#include <QtDebug>
AsciiReaderSettings::AsciiReaderSettings(QWidget *parent) :
QWidget(parent),
ui(new Ui::AsciiReaderSettings)
ui->setupUi(this);
auto validator = new QRegularExpressionValidator(QRegularExpression("[^\\d]?"), this);
ui->leDelimiter->setValidator(validator);
connect(ui->rbComma, &QAbstractButton::toggled,
this, &AsciiReaderSettings::delimiterToggled);
connect(ui->rbSpace, &QAbstractButton::toggled,
connect(ui->rbTab, &QAbstractButton::toggled,
connect(ui->rbOtherDelimiter, &QAbstractButton::toggled,
connect(ui->leDelimiter, &QLineEdit::textChanged,
this, &AsciiReaderSettings::customDelimiterChanged);
// Note: if directly connected we get a runtime warning on incompatible signal arguments
connect(ui->spNumOfChannels, SELECT<int>::OVERLOAD_OF(&QSpinBox::valueChanged),
[this](int value)
@@ -41,17 +56,57 @@ AsciiReaderSettings::AsciiReaderSettings
AsciiReaderSettings::~AsciiReaderSettings()
delete ui;
unsigned AsciiReaderSettings::numOfChannels()
unsigned AsciiReaderSettings::numOfChannels() const
return ui->spNumOfChannels->value();
QChar AsciiReaderSettings::delimiter() const
if (ui->rbComma->isChecked())
return QChar(',');
else if (ui->rbSpace->isChecked())
return QChar(' ');
else if (ui->rbTab->isChecked())
return QChar('\t');
else // rbOther
auto t = ui->leDelimiter->text();
return t.isEmpty() ? QChar() : t.at(0);
void AsciiReaderSettings::delimiterToggled(bool checked)
if (!checked) return;
auto d = delimiter();
if (!d.isNull())
emit delimiterChanged(d);
void AsciiReaderSettings::customDelimiterChanged(const QString text)
if (ui->rbOtherDelimiter->isChecked())
if (!text.isEmpty()) emit delimiterChanged(text.at(0));
void AsciiReaderSettings::saveSettings(QSettings* settings)
settings->beginGroup(SettingGroup_ASCII);
// save number of channels setting
QString numOfChannelsSetting = QString::number(numOfChannels());
@@ -19,12 +19,13 @@
#ifndef ASCIIREADERSETTINGS_H
#define ASCIIREADERSETTINGS_H
#include <QWidget>
#include <QSettings>
#include <QChar>
namespace Ui {
class AsciiReaderSettings;
class AsciiReaderSettings : public QWidget
@@ -32,20 +33,27 @@ class AsciiReaderSettings : public QWidg
Q_OBJECT
public:
explicit AsciiReaderSettings(QWidget *parent = 0);
~AsciiReaderSettings();
unsigned numOfChannels();
unsigned numOfChannels() const;
QChar delimiter() const;
/// Stores settings into a `QSettings`
void saveSettings(QSettings* settings);
/// Loads settings from a `QSettings`.
void loadSettings(QSettings* settings);
signals:
void numOfChannelsChanged(unsigned);
/// Signaled only with a valid delimiter
void delimiterChanged(QChar);
Ui::AsciiReaderSettings *ui;
private slots:
void delimiterToggled(bool checked);
void customDelimiterChanged(const QString text);
};
#endif // ASCIIREADERSETTINGS_H
@@ -3,42 +3,43 @@
<class>AsciiReaderSettings</class>
<widget class="QWidget" name="AsciiReaderSettings">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>414</width>
<width>493</width>
<height>171</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
<layout class="QVBoxLayout" name="verticalLayout">
<layout class="QFormLayout" name="formLayout">
<property name="fieldGrowthPolicy">
<enum>QFormLayout::ExpandingFieldsGrow</enum>
<property name="leftMargin">
<number>0</number>
<property name="topMargin">
<property name="rightMargin">
<property name="bottomMargin">
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item row="0" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Number Of Channels:</string>
</widget>
</item>
<item row="0" column="1">
<widget class="QSpinBox" name="spNumOfChannels">
<property name="minimumSize">
<size>
<width>60</width>
<height>0</height>
</size>
@@ -57,39 +58,78 @@
<property name="maximum">
<number>32</number>
<item row="2" column="0">
<widget class="QLabel" name="label">
<string>Column Delimiter:</string>
<item row="2" column="1">
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
<widget class="QRadioButton" name="rbComma">
<string>comma</string>
<property name="checked">
<bool>true</bool>
<widget class="QRadioButton" name="rbSpace">
<string>space</string>
<property name="sizeHint" stdset="0">
<widget class="QRadioButton" name="rbTab">
<string>tab</string>
<widget class="QRadioButton" name="rbOtherDelimiter">
<string>other:</string>
<widget class="QLineEdit" name="leDelimiter">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
<property name="maximumSize">
<width>1</width>
<height>20</height>
<width>30</width>
<height>16777215</height>
</spacer>
<property name="toolTip">
<string>Enter a custom delimiter character</string>
<property name="inputMask">
<string/>
<string>|</string>
</layout>
<spacer name="verticalSpacer">
<enum>Qt::Vertical</enum>
<width>20</width>
<height>1</height>
<resources/>
<connections/>
</ui>
Status change: