374 lines
9.4 KiB
C++
374 lines
9.4 KiB
C++
#include "export.h"
|
|
#include <qapplication.h>
|
|
#include <qvariant.h>
|
|
#include <qdialog.h>
|
|
#include <qpushbutton.h>
|
|
#include <qcheckbox.h>
|
|
#include <qlabel.h>
|
|
#include <qlayout.h>
|
|
#include <qtooltip.h>
|
|
#include <qwhatsthis.h>
|
|
#include <stdio.h>
|
|
#include <qvalidator.h>
|
|
#include <math.h>
|
|
#include <unistd.h>
|
|
#include <qtimer.h>
|
|
#include <qdatetime.h>
|
|
#include <qsizepolicy.h>
|
|
#include <qfiledialog.h>
|
|
#include "seaset.h"
|
|
#include "sicsconn.h"
|
|
#include <assert.h>
|
|
#include <stdlib.h>
|
|
|
|
void Export::addRow(QString label, QWidget *widget, QString tip) {
|
|
QLabel *labelW;
|
|
if (label != "") {
|
|
labelW = new QLabel(label, this);
|
|
lay->addWidget(labelW, row, 0);
|
|
if (tip != "") {
|
|
QToolTip::add(labelW, tip);
|
|
}
|
|
}
|
|
lay->addWidget(widget, row, 1);
|
|
if (tip != "") {
|
|
QToolTip::add(widget, tip);
|
|
}
|
|
row++;
|
|
}
|
|
|
|
Export::Export(SeaSet *setArg, QWidget *parent, const char *instr)
|
|
: QWidget(parent)
|
|
{
|
|
QPushButton *ok, *cancel;
|
|
char wd[PATH_MAX];
|
|
|
|
set = setArg;
|
|
row = 0;
|
|
instrument = instr;
|
|
|
|
lay = new QGridLayout(this, 1, 3, 3, -1, "exportLayout");
|
|
lay->setColStretch(2,1);
|
|
|
|
addRow("export: ", new QLabel("all active curves", this), "");
|
|
|
|
lay->addWidget(new QLabel("step [sec]", this), 1, 0);
|
|
stepLE = new QLineEdit(this);
|
|
QValidator* validator = new QIntValidator( 1, 24*3600, this );
|
|
stepLE->setValidator(validator);
|
|
stepLE->setText("auto");
|
|
stepLE->setAlignment(Qt::AlignRight);
|
|
stepLE->setFixedWidth(100);
|
|
addRow("step [sec]", stepLE,
|
|
"time step [sec] (auto: 5 sec or more, max. 1000 points)"
|
|
);
|
|
|
|
scaleLE = new QLineEdit(this);
|
|
scaleLE->setText("1");
|
|
scaleLE->setAlignment(Qt::AlignRight);
|
|
scaleLE->setFixedWidth(100);
|
|
addRow("x-scale [sec]", scaleLE, "enter 60 for minutes / 3600 for hours");
|
|
|
|
noneLE = new QLineEdit(this);
|
|
noneLE->setText("NaN");
|
|
noneLE->setFixedWidth(100);
|
|
addRow("none value", noneLE, "value to be used for undefined numbers");
|
|
|
|
filePath = getcwd(wd, sizeof wd);
|
|
filePath.append("/seaexport.dat");
|
|
|
|
cancel = new QPushButton("Quit", this);
|
|
lay->addWidget(cancel, row, 0);
|
|
connect(cancel, SIGNAL(clicked()), this, SIGNAL(finish()));
|
|
|
|
ok = new QPushButton("Export", this);
|
|
lay->addWidget(ok, 5, 1);
|
|
ok->setDefault(true);
|
|
ok->setFixedWidth(100);
|
|
addRow("", ok, "");
|
|
connect(ok, SIGNAL(clicked()), this, SLOT(exportXY()));
|
|
|
|
message = new QLabel("", this);
|
|
lay->addWidget(message, row, 1);
|
|
row++;
|
|
|
|
lay->setRowStretch(row,1);
|
|
}
|
|
|
|
void Export::showMe() {
|
|
show();
|
|
updateCurveList();
|
|
}
|
|
|
|
void Export::updateCurveList() {
|
|
QString text("The following curves are active and to be exported:");
|
|
int cnt=0;
|
|
SeaData *d;
|
|
|
|
if (isHidden()) return;
|
|
for (d = set->dataList.first(); d != 0; d = set->dataList.next()) {
|
|
if (d->isActive()) {
|
|
text.append("\n ");
|
|
text.append(d->label);
|
|
cnt++;
|
|
}
|
|
}
|
|
if (cnt == 0) {
|
|
text = "no active curves";
|
|
}
|
|
text.append("\n\ncurves are de-/activated by clicking on their legend");
|
|
message->setText(text);
|
|
show();
|
|
}
|
|
|
|
void Export::progress(int bytes) {
|
|
QString text;
|
|
|
|
if (progressBytes < 0) return;
|
|
if (isHidden()) return;
|
|
progressBytes += bytes;
|
|
if (progressBytes >= 0 && lastProgress.elapsed() > 250) {
|
|
lastProgress.start();
|
|
text.sprintf("%.2f MBytes read", progressBytes * 0.000001);
|
|
message->setText(text);
|
|
show();
|
|
procEvt();
|
|
}
|
|
}
|
|
|
|
void Export::exportXY() {
|
|
|
|
QString cmd;
|
|
QString line;
|
|
int iret, cnt, icol;
|
|
bool ok;
|
|
time_t dt, t, from, to, step, lastRead, basis;
|
|
time_t i, lasti, len, siz, scale, mag, endi;
|
|
int prec;
|
|
SeaData *d;
|
|
QString text;
|
|
double val;
|
|
double *data;
|
|
double yy, yy0;
|
|
FILE *fil;
|
|
QString fileResult;
|
|
double eps;
|
|
static double undefpluseps = 0;
|
|
|
|
fileResult = QFileDialog::getSaveFileName(
|
|
filePath, QString::null, this,
|
|
"save file dialog",
|
|
"select file to save exported data"
|
|
);
|
|
if (fileResult == "") {
|
|
return;
|
|
}
|
|
filePath = fileResult;
|
|
|
|
from = set->startRange;
|
|
to = set->endRange;
|
|
step = stepLE->text().toInt();
|
|
if (step == 0) { /* auto */
|
|
step = ((to - from) / 5000 + 1) * 5;
|
|
}
|
|
from = (from / step) * step;
|
|
scale = scaleLE->text().toInt();
|
|
if (scale < 1) {
|
|
scale = 1;
|
|
}
|
|
len = (to - from - 1) / step;
|
|
to = from + len * step;
|
|
|
|
if (step == 1) {
|
|
cmd.sprintf("graph %ld %ld text", from, to);
|
|
} else {
|
|
cmd.sprintf("graph %ld %ld np %ld", from, to, to - from + 2);
|
|
}
|
|
|
|
cnt = 0;
|
|
for (d = set->dataList.first(); d != 0; d = set->dataList.next()) {
|
|
if (d->isActive()) {
|
|
cmd.append(" ");
|
|
cmd.append(d->name);
|
|
cnt++;
|
|
}
|
|
}
|
|
if (cnt == 0) {
|
|
message->setText("no curves active");
|
|
show();
|
|
return;
|
|
}
|
|
siz = len * cnt;
|
|
data = (double *)malloc(siz * sizeof(*data));
|
|
if (data == NULL) {
|
|
message->setText("no memory");
|
|
show();
|
|
return;
|
|
}
|
|
|
|
progressBytes = 0;
|
|
message->setText("waiting for server");
|
|
procEvt();
|
|
lastProgress.start();
|
|
iret = set->ec->command(cmd);
|
|
progressBytes = -1;
|
|
|
|
if (iret < 0) {
|
|
message->setText("can not connect to the GraphServer");
|
|
goto err2;
|
|
}
|
|
//printf("%s\n", cmd.latin1());
|
|
|
|
text = "Curves:";
|
|
message->setText(text);
|
|
procEvt();
|
|
|
|
iret = set->ec->getLine(line);
|
|
if (iret <= 0) {
|
|
message->setText("can not get response 1");
|
|
goto err2;
|
|
}
|
|
//printf("> %s\n", line.latin1());
|
|
|
|
/* get returned absolute time */
|
|
lastRead = line.toLong();
|
|
//sscanf(line, "%ld", &lastRead);
|
|
|
|
iret = set->ec->getLine(line);
|
|
if (iret <= 0) {
|
|
message->setText("can not get response 2");
|
|
goto err2;
|
|
}
|
|
//printf("> %s\n", line.latin1());
|
|
if (!line.startsWith("*")) {
|
|
message->setText("missing *");
|
|
goto err2;
|
|
}
|
|
|
|
icol = 0;
|
|
fil = fopen(filePath.latin1(), "w");
|
|
fprintf(fil, "# SEA export from %s\n", instrument);
|
|
fprintf(fil, "# col 1: Time/%d sec since %s 0:00\n", (int)scale, set->dateLabel(0).latin1());
|
|
|
|
endi = 0;
|
|
for (d = set->dataList.first(); d != 0; set->dataList.findRef(d), d = set->dataList.next()) {
|
|
if (d->isActive()) {
|
|
yy0 = DATA_UNDEF;
|
|
yy = DATA_UNDEF;
|
|
lasti = -1;
|
|
//printf("- %s\n", d->label.latin1());
|
|
fprintf(fil, "# col %d: %s (%s) %s\n",
|
|
icol + 2, d->name.latin1(), d->label.latin1(),
|
|
d->row->tagLabel->text().latin1());
|
|
text.append("\n ");
|
|
text.append(d->label);
|
|
line = line.section(' ', 0, 0);
|
|
if (d->name == line.mid(1)) {
|
|
t = 0;
|
|
do {
|
|
iret = set->ec->getLine(line);
|
|
if (iret <= 0) {
|
|
message->setText("can not get line");
|
|
goto err;
|
|
}
|
|
//printf("> %s\n", line.latin1());
|
|
if (line.startsWith("*")) {
|
|
i = len;
|
|
} else {
|
|
/* decode line to x[n] / y[n] */
|
|
dt = line.section(' ', 0, 0).toLong(&ok);
|
|
/*
|
|
iret = sscanf(line, "%ld %n", &dt, &pos);
|
|
if (iret < 1) {
|
|
*/
|
|
if (!ok) {
|
|
message->setText("bad timestep");
|
|
goto err;
|
|
}
|
|
t += dt;
|
|
i = (t - from) / step;
|
|
yy0 = yy;
|
|
yy = line.section(' ', 1, 1).toDouble(&ok);
|
|
//iret = sscanf(line + pos, "%lf", &yy);
|
|
// printf("scan %8ld %9.4f\n", t - from, yy);
|
|
if (!ok) { // not a valid value
|
|
yy = DATA_UNDEF;
|
|
} else {
|
|
if (yy == DATA_UNDEF) { // by chance
|
|
if (undefpluseps == 0) { // create closest possible (but different) value to DATA_UNDEF
|
|
undefpluseps = yy;
|
|
eps = undefpluseps * 1e-9;
|
|
while (undefpluseps == DATA_UNDEF) {
|
|
undefpluseps += eps;
|
|
eps = eps * 2;
|
|
}
|
|
}
|
|
yy = undefpluseps;
|
|
}
|
|
}
|
|
}
|
|
/*---*/
|
|
|
|
if (lasti < i) {
|
|
if (lasti < 0) {
|
|
lasti = 0;
|
|
}
|
|
while (lasti < i - 1 && lasti < len) {
|
|
assert(lasti * cnt + icol < siz);
|
|
data[lasti*cnt + icol] = yy0;
|
|
lasti++;
|
|
}
|
|
if (lasti < len) {
|
|
data[lasti*cnt + icol] = yy;
|
|
// printf("%ld %9.4f\n", lasti, yy);
|
|
if (yy != DATA_UNDEF) {
|
|
if (lasti > endi && lasti != len) endi = lasti;
|
|
}
|
|
}
|
|
lasti++;
|
|
}
|
|
} while (!line.startsWith("*"));
|
|
} else {
|
|
for (i = 0; i<len; i++) {
|
|
assert(i * cnt + icol < siz);
|
|
data[i*cnt + icol] = DATA_UNDEF;
|
|
}
|
|
}
|
|
icol++;
|
|
message->setText(text);
|
|
procEvt();
|
|
}
|
|
}
|
|
//fprintf(fil, "\n");
|
|
basis = (from - set->base) / step;
|
|
//printf("endi %ld\n", endi);
|
|
for (i = 0; i < endi; i++) {
|
|
if (scale == 1) {
|
|
fprintf(fil, "%ld", (basis + i) * step);
|
|
} else {
|
|
mag = 10 * scale / step;
|
|
for (prec = 0; mag > 1; prec++,mag/=10);
|
|
fprintf(fil, "%.*f", prec, (double)(basis + i) * step / scale);
|
|
}
|
|
for (icol = 0; icol < cnt; icol++) {
|
|
val = data[i*cnt + icol];
|
|
if (val == DATA_UNDEF) {
|
|
fprintf(fil, "\t%s", noneLE->text().latin1());
|
|
} else {
|
|
// fprintf(fil, "\t%.7g", val);
|
|
// we might write here full precision, this will not watse space in case step is not 1
|
|
fprintf(fil, "\t%.14g", val);
|
|
}
|
|
}
|
|
fprintf(fil,"\n");
|
|
}
|
|
text.append("\n\nwritten to\n");
|
|
text.append(filePath.latin1());
|
|
message->setText(text);
|
|
err:
|
|
fclose(fil);
|
|
err2:
|
|
free(data);
|
|
show();
|
|
}
|