44 changes: 12 additions & 32 deletions src/datasources/ascii/asciiconfig.ui
Original file line number Diff line number Diff line change
Expand Up @@ -408,28 +408,24 @@
</widget>
</item>
<item>
<widget class="QLineEdit" name="_limitFileBufferSize">
<widget class="QSpinBox" name="_limitFileBufferSize">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>256</string>
<property name="suffix">
<string> MB</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_4">
<property name="enabled">
<bool>false</bool>
<property name="minimum">
<number>0</number>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
<property name="maximum">
<number>16000</number>
</property>
<property name="text">
<string>MB</string>
<property name="singleStep">
<number>100</number>
</property>
<property name="value">
<number>100</number>
</property>
</widget>
</item>
Expand Down Expand Up @@ -947,22 +943,6 @@
</hint>
</hints>
</connection>
<connection>
<sender>_limitFileBuffer</sender>
<signal>toggled(bool)</signal>
<receiver>label_4</receiver>
<slot>setEnabled(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>751</x>
<y>263</y>
</hint>
<hint type="destinationlabel">
<x>914</x>
<y>259</y>
</hint>
</hints>
</connection>
<connection>
<sender>_interpret</sender>
<signal>toggled(bool)</signal>
Expand Down
9 changes: 2 additions & 7 deletions src/datasources/ascii/asciiconfigwidget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -169,12 +169,7 @@ AsciiSourceConfig AsciiConfigWidgetInternal::config()
config._unitsLine = _unitsLine->value() - _index_offset;

config._limitFileBuffer = _limitFileBuffer->isChecked();
bool ok;
int size = _limitFileBufferSize->text().toInt(&ok);
if (ok) {
config._limitFileBufferSize = size * 1024 * 1024;
}

config._limitFileBufferSize = (qint64)_limitFileBufferSize->value() * 1024 * 1024;
config._useThreads =_useThreads->isChecked();
config._timeAsciiFormatString = _timeAsciiFormatString->text();
config._dataRate = _dataRate->value();
Expand Down Expand Up @@ -220,7 +215,7 @@ void AsciiConfigWidgetInternal::setConfig(const AsciiSourceConfig& config)
}

_limitFileBuffer->setChecked(config._limitFileBuffer);
_limitFileBufferSize->setText(QString::number(config._limitFileBufferSize / 1024 / 1024));
_limitFileBufferSize->setValue(config._limitFileBufferSize / 1024 / 1024);

_useThreads->setChecked(config._useThreads);
_timeAsciiFormatString->setText(config._timeAsciiFormatString);
Expand Down
27 changes: 24 additions & 3 deletions src/datasources/ascii/asciidatareader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@
#include <QDebug>
#include <QMutexLocker>
#include <QStringList>
#include <QLabel>
#include <QApplication>


#include <ctype.h>
#include <stdlib.h>

Expand All @@ -40,6 +44,13 @@ using namespace AsciiCharacterTraits;

//-------------------------------------------------------------------------------------------
AsciiDataReader::AsciiDataReader(AsciiSourceConfig& config) :
_progress(0),
_progressRows(0),
_progressObj(0),
_updateRowProgress(0),
_numFrames(0),
_progressMax(0),
_progressDone(0),
_config(config),
isDigit(),
isWhiteSpace()
Expand Down Expand Up @@ -112,9 +123,12 @@ void AsciiDataReader::toDouble(const LexicalCast& lexc, const char* buffer, qint
}

//-------------------------------------------------------------------------------------------
bool AsciiDataReader::findDataRows(bool read_completely, QFile& file, qint64 _byteLength, int col_count)
bool AsciiDataReader::findAllDataRows(bool read_completely, QFile* file, qint64 byteLength, int col_count)
{
detectLineEndingType(file);
detectLineEndingType(*file);

_progressMax = byteLength;
_progressDone = 0;

bool new_data = false;
AsciiFileData buf;
Expand All @@ -123,7 +137,7 @@ bool AsciiDataReader::findDataRows(bool read_completely, QFile& file, qint64 _by
buf.clear();

qint64 bufstart = _rowIndex[_numFrames]; // always read from the start of a line
buf.read(file, bufstart, _byteLength - bufstart, AsciiFileData::Prealloc - 1);
_progressDone += buf.read(*file, bufstart, byteLength - bufstart, AsciiFileData::Prealloc - 1);
if (buf.bytesRead() == 0) {
return false;
}
Expand All @@ -150,6 +164,13 @@ bool AsciiDataReader::findDataRows(bool read_completely, QFile& file, qint64 _by
new_data = findDataRows(buf.checkedData(), buf.begin(), buf.bytesRead(), IsLineBreakCR(_lineending), comment_del, col_count);
}
}

if (_updateRowProgress && _progress && _progressRows) {
*_progressRows = _numFrames;
*_progress = _progressDone * 100 / _progressMax;
(*_updateRowProgress)(_progressObj);
}

} while (buf.bytesRead() == AsciiFileData::Prealloc - 1 && read_completely);

return new_data;
Expand Down
12 changes: 10 additions & 2 deletions src/datasources/ascii/asciidatareader.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,16 +39,24 @@ class AsciiDataReader
const AsciiFileBuffer::RowIndex& rowIndex() const { return _rowIndex; }

void detectLineEndingType(QFile& file);
bool findDataRows(bool read_completely, QFile& file, qint64 _byteLength, int col_count);

bool findAllDataRows(bool read_completely, QFile* file, qint64 _byteLength, int col_count);
int readField(const AsciiFileData &buf, int col, double *v, const QString& field, int start, int n);
int readFieldFromChunk(const AsciiFileData& chunk, int col, double *v, int start, const QString& field);

template<typename ColumnDelimiter>
static int splitColumns(const QByteArray& line, const ColumnDelimiter& column_del, QStringList* cols = 0);


int* _progress;
qint64* _progressRows;
QObject* _progressObj;
void(*_updateRowProgress)(QObject*);

private:
qint64 _numFrames;
qint64 _progressMax;
qint64 _progressDone;
AsciiFileBuffer::RowIndex _rowIndex;
AsciiSourceConfig& _config;
AsciiCharacterTraits::LineEndingType _lineending;
Expand Down
14 changes: 8 additions & 6 deletions src/datasources/ascii/asciifiledata.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -152,31 +152,33 @@ void AsciiFileData::clear(bool forceDeletingArray)
}

//-------------------------------------------------------------------------------------------
void AsciiFileData::read(QFile& file, qint64 start, qint64 bytesToRead, qint64 maximalBytes)
qint64 AsciiFileData::read(QFile& file, qint64 start, qint64 bytesToRead, qint64 maximalBytes)
{
_begin = -1;
_bytesRead = 0;

if (bytesToRead <= 0 || start < 0)
return;
return 0;

if (maximalBytes == -1) {
if (!resize(bytesToRead + 1))
return;
return 0;
} else {
bytesToRead = qMin(bytesToRead, maximalBytes);
if (!resize(bytesToRead + 1))
return;
return 0;
}
if (!file.seek(start)) // expensive?
return;
return 0;
qint64 bytesRead = file.read(_array->data(), bytesToRead);
if (!resize(bytesRead + 1))
return;
return 0;

_array->data()[bytesRead] = '\0';
_begin = start;
_bytesRead = bytesRead;

return bytesRead;
}

//-------------------------------------------------------------------------------------------
Expand Down
2 changes: 1 addition & 1 deletion src/datasources/ascii/asciifiledata.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ class AsciiFileData

inline void setFile(QFile* file) { _file = file; }
bool read();
void read(QFile&, qint64 start, qint64 numberOfBytes, qint64 maximalBytes = -1);
qint64 read(QFile&, qint64 start, qint64 numberOfBytes, qint64 maximalBytes = -1);

char* data();
const char* const constPointer() const;
Expand Down
76 changes: 74 additions & 2 deletions src/datasources/ascii/asciisource.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,26 @@
#include <QThread>
#include <QtConcurrentRun>
#include <QFutureSynchronizer>
#include <QLabel>
#include <QApplication>
#include <QVBoxLayout>
#include <QProgressBar>


#include <ctype.h>
#include <stdlib.h>


using namespace Kst;


//-------------------------------------------------------------------------------------------
struct ms : QThread
{
static void sleep(int t) { QThread::msleep(t); }
};


//-------------------------------------------------------------------------------------------
static const QString asciiTypeString = I18N_NOOP("ASCII file");

Expand All @@ -52,7 +65,10 @@ AsciiSource::AsciiSource(Kst::ObjectStore *store, QSettings *cfg, const QString&
_reader(_config),
_fileBuffer(),
is(new DataInterfaceAsciiString(*this)),
iv(new DataInterfaceAsciiVector(*this))
iv(new DataInterfaceAsciiVector(*this)),
_progress(0),
_progressBar(0),
_progressLabel(0)
{
setInterface(is);
setInterface(iv);
Expand All @@ -75,6 +91,8 @@ AsciiSource::AsciiSource(Kst::ObjectStore *store, QSettings *cfg, const QString&
_valid = true;
registerChange();
internalDataSourceUpdate(false);

connect(this, SIGNAL(signalRowProgress()), this, SLOT(updateRowProgress()));
}


Expand Down Expand Up @@ -196,12 +214,66 @@ Kst::Object::UpdateType AsciiSource::internalDataSourceUpdate(bool read_complete
_fileCreationTime_t = QFileInfo(file).created().toTime_t();

int col_count = _fieldList.size() - 1; // minus INDEX
bool new_data = _reader.findDataRows(read_completely, file, _fileSize, col_count);

bool new_data = false;
if (!useThreads()) {
new_data = _reader.findAllDataRows(read_completely, &file, _fileSize, col_count);
} else {
// TODO ugly
_reader._progressRows = &_progressRows;
_reader._progress = &_progressValue;
_reader._progressObj = this;
_reader._updateRowProgress = &AsciiSource::rowProgress;
QFuture<bool> future = QtConcurrent::run(&_reader, &AsciiDataReader::findAllDataRows, read_completely, &file, _fileSize, col_count);
bool busy = true;
while (busy) {
if (future.isFinished()) {
new_data = future;
busy = false;
} else {
ms::sleep(500);
qApp->processEvents(QEventLoop::ExcludeUserInputEvents);
}
}
if (_progress) {
_progress->hide();
}
}

return (!new_data && !force_update ? NoChange : Updated);
}


//-------------------------------------------------------------------------------------------
void AsciiSource::rowProgress(QObject* obj)
{
((AsciiSource*)obj)->triggerRowProgress();
}


//-------------------------------------------------------------------------------------------
void AsciiSource::updateRowProgress()
{
if (!_progress) {
_progress = new QWidget();
_progressLabel = new QLabel;
_progressBar = new QProgressBar;
_progressLabel->setAlignment(Qt::AlignHCenter);
QVBoxLayout* l = new QVBoxLayout;
l->addStretch();
l->addWidget(_progressBar);
l->addWidget(_progressLabel);
l->addStretch();
_progress->setLayout(l);
_progress->setWindowTitle("Kst's ASCII Data Reader");
_progress->resize(300, 50);
}
_progressBar->setValue(_progressValue);
double mill = _progressRows * 1e-6;
_progressLabel->setText(QString("%1 millon rows found.").arg(mill, 0, 'f', 1));
_progress->show();
}

//-------------------------------------------------------------------------------------------
int AsciiSource::columnOfField(const QString& field) const
{
Expand Down
19 changes: 18 additions & 1 deletion src/datasources/ascii/asciisource.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@
class QFile;
class DataInterfaceAsciiString;
class DataInterfaceAsciiVector;

class QProgressBar;
class QLabel;

class AsciiSource : public Kst::DataSource
{
Expand Down Expand Up @@ -70,6 +71,15 @@ class AsciiSource : public Kst::DataSource

QString timeFormat() const;

void triggerRowProgress() { emit signalRowProgress(); }

signals:
void signalRowProgress();


private slots:
void updateRowProgress();

private:
AsciiDataReader _reader;
AsciiFileBuffer _fileBuffer;
Expand Down Expand Up @@ -104,6 +114,13 @@ class AsciiSource : public Kst::DataSource
DataInterfaceAsciiString* is;
DataInterfaceAsciiVector* iv;

QWidget* _progress;
QProgressBar* _progressBar;
QLabel* _progressLabel;
int _progressValue;
qint64 _progressRows;
static void rowProgress(QObject*);

// TODO remove
friend class DataInterfaceAsciiString;
friend class DataInterfaceAsciiVector;
Expand Down
2 changes: 1 addition & 1 deletion src/datasources/ascii/asciisourceconfig.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ AsciiSourceConfig::AsciiSourceConfig() :
_unitsLine(0),
_useDot(true),
_limitFileBuffer(false),
_limitFileBufferSize(128),
_limitFileBufferSize(100),
_useThreads(false),
_dataRate(1.0),
_offsetDateTime(false),
Expand Down
2 changes: 1 addition & 1 deletion src/datasources/ascii/asciisourceconfig.h
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ class AsciiSourceConfig {
NamedParameter<int, Key_unitsLine, Tag_unitsLine> _unitsLine;
NamedParameter<bool, Key_useDot, Tag_useDot> _useDot;
NamedParameter<bool, Key_limitFileBuffer, Tag_limitFileBuffer> _limitFileBuffer;
NamedParameter<int, Key_limitFileBufferSize, Tag_limitFileBufferSize> _limitFileBufferSize;
NamedParameter<qint64, Key_limitFileBufferSize, Tag_limitFileBufferSize> _limitFileBufferSize;
NamedParameter<int, Key_useThreads, Tag_useThreads> _useThreads;
NamedParameter<double, Key_dataRate, Tag_dataRate> _dataRate;
NamedParameter<bool, Key_offsetDateTime, Tag_offsetDateTime> _offsetDateTime;
Expand Down
Loading