File indexing completed on 2024-12-29 04:11:43

0001 /***************************************************************************
0002  *                                                                         *
0003  *   Copyright : (C) 2003 The University of Toronto                        *
0004  *   email     : netterfield@astro.utoronto.ca                             *
0005  *                                                                         *
0006  *   This program is free software; you can redistribute it and/or modify  *
0007  *   it under the terms of the GNU General Public License as published by  *
0008  *   the Free Software Foundation; either version 2 of the License, or     *
0009  *   (at your option) any later version.                                   *
0010  *                                                                         *
0011  ***************************************************************************/
0012 
0013 #include "asciiconfigwidget.h"
0014 #include "objectstore.h"
0015 
0016 #include "kst_atof.h"
0017 
0018 #include <QFile>
0019 #include <QFileInfo>
0020 #include <QButtonGroup>
0021 #include <QPlainTextEdit>
0022 #include <QMessageBox>
0023 
0024 //
0025 // AsciiConfigWidgetInternal
0026 //
0027 
0028 
0029 
0030 AsciiConfigWidgetInternal::AsciiConfigWidgetInternal(QWidget *parent) :
0031     QWidget(parent),
0032     Ui_AsciiConfig(),
0033     _index_offset(1)
0034 {
0035   setupUi(this);
0036 
0037   QButtonGroup* bgroup = new QButtonGroup(this);
0038   bgroup->addButton(_whitespace, AsciiSourceConfig::Whitespace);
0039   bgroup->addButton(_custom, AsciiSourceConfig::Custom);
0040   bgroup->addButton(_fixed, AsciiSourceConfig::Fixed);
0041 
0042   _showBeginning->setFont(QFont("Courier"));
0043   _showBeginning->setReadOnly(true);
0044   _showBeginning->setLineWrapMode(QPlainTextEdit::NoWrap);
0045   _showBeginning->setMinimumSize(640, 100);
0046 
0047   _previewWidget.setFont(QFont("Courier"));
0048   _previewWidget.setReadOnly(true);
0049   _previewWidget.setLineWrapMode(QPlainTextEdit::NoWrap);
0050   _previewWidget.setMinimumSize(640, 300);
0051 
0052   QObject::connect(_ctime, SIGNAL(toggled(bool)), this, SLOT(interpretationChanged(bool)));
0053   QObject::connect(_seconds, SIGNAL(toggled(bool)), this, SLOT(interpretationChanged(bool)));
0054   QObject::connect(_indexFreq, SIGNAL(toggled(bool)), this, SLOT(interpretationChanged(bool)));
0055   QObject::connect(_formattedString, SIGNAL(toggled(bool)), this, SLOT(interpretationChanged(bool)));
0056   QObject::connect(_previewButton, SIGNAL(clicked()), this, SLOT(showPreviewWindow()));
0057   //QObject::connect(_timeAsciiFormatString, SIGNAL(textEdited(QString)), this, SLOT(testAsciiFormatString(QString)));
0058 
0059 #ifdef KST_NO_THREAD_LOCAL
0060   _nanPrevious->hide();
0061 #endif
0062 }
0063 
0064 void AsciiConfigWidgetInternal::testAsciiFormatString(QString format) {
0065   // FIXME: add a format validator
0066 }
0067 
0068 QString AsciiConfigWidgetInternal::readLine(QTextStream& in, int maxLength)
0069 {
0070   const QString line = in.readLine();
0071   if (line.size() > maxLength) {
0072     // very log line, don't show it complete
0073     return line.mid(0, maxLength) + " ...";
0074   }
0075   return line;
0076 }
0077 
0078 void AsciiConfigWidgetInternal::showBeginning()
0079 {
0080   showBeginning(_showBeginning, 100);
0081   _labelBeginning->setText(tr("First lines of file '%1'").arg(QFileInfo(_filename).fileName()));
0082 }
0083 
0084 
0085 void AsciiConfigWidgetInternal::showPreviewWindow()
0086 {
0087   showBeginning(&_previewWidget, 1000);
0088   _previewWidget.setWindowTitle(_filename);
0089   _previewWidget.show();
0090 }
0091 
0092 void AsciiConfigWidgetInternal::showBeginning(QPlainTextEdit* widget, int numberOfLines)
0093 {
0094   QFile file(_filename);
0095   if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
0096     return;
0097   }
0098 
0099   int lines_read = 1;
0100   QTextStream in(&file);
0101   QStringList lines;
0102   while (!in.atEnd() && lines_read <= numberOfLines) {
0103     lines << QString("%1: ").arg(lines_read, 3) + readLine(in, 1000);
0104     lines_read++;
0105   }
0106 
0107   widget->setPlainText(lines.join("\n"));
0108   widget->moveCursor(QTextCursor::Start);
0109 }
0110 
0111 void AsciiConfigWidgetInternal::interpretationChanged(bool enabled) {
0112   if (enabled) {
0113     if (_ctime->isChecked()) {
0114       _offsetDateTime->setEnabled(false);
0115       _offsetFileDate->setEnabled(false);
0116       _offsetRelative->setEnabled(true);
0117       _offsetRelative->setChecked(true);
0118     } else if (_formattedString->isChecked()) {
0119       _offsetDateTime->setEnabled(true);
0120       _offsetFileDate->setEnabled(true);
0121       _offsetRelative->setEnabled(true);
0122     } else {
0123       _offsetDateTime->setEnabled(true);
0124       _offsetFileDate->setEnabled(true);
0125       _offsetRelative->setEnabled(false);
0126       if (_offsetRelative->isChecked()) {
0127         _offsetDateTime->setChecked(true);
0128       }
0129     }
0130   }
0131 }
0132 
0133 AsciiSourceConfig AsciiConfigWidgetInternal::config()
0134 {
0135   AsciiSourceConfig config;
0136   config._fileNamePattern = _fileNamePattern->text();
0137   config._indexVector = _indexVector->currentText();
0138 
0139   if (_interpret->isChecked()) {
0140     if (_ctime->isChecked()) {
0141       config._indexInterpretation = AsciiSourceConfig::CTime;
0142     } else if (_seconds->isChecked()) {
0143       config._indexInterpretation = AsciiSourceConfig::Seconds;
0144     } else if (_formattedString->isChecked()) {
0145       config._indexInterpretation = AsciiSourceConfig::FormattedTime;
0146     } else if (_indexFreq->isChecked()) {
0147       config._indexInterpretation = AsciiSourceConfig::FixedRate;
0148     } else {
0149       config._indexInterpretation = AsciiSourceConfig::NoInterpretation;
0150     }
0151   } else {
0152     config._indexInterpretation = AsciiSourceConfig::NoInterpretation;
0153   }
0154 
0155   config._delimiters = _delimiters->text();
0156 
0157   if (_whitespace->isChecked()) {
0158     config._columnType = AsciiSourceConfig::Whitespace;
0159   } else if (_custom->isChecked()) {
0160     config._columnType = AsciiSourceConfig::Custom;
0161   } else if (_fixed->isChecked()) {
0162     config._columnType = AsciiSourceConfig::Fixed;
0163   }
0164 
0165   config._columnDelimiter = _columnDelimiter->text();
0166   config._columnWidth = _columnWidth->value();
0167   config._columnWidthIsConst = _colWidthConst->isChecked();
0168   config._readFields = _readFields->isChecked();
0169   config._readUnits = _readUnits->isChecked();
0170   config._useDot = _useDot->isChecked();
0171 
0172   config._dataLine = _startLine->value() - _index_offset;
0173   config._fieldsLine = _fieldsLine->value() - _index_offset;
0174   config._unitsLine = _unitsLine->value() - _index_offset;
0175 
0176   config._limitFileBuffer = _limitFileBuffer->isChecked();
0177   config._limitFileBufferSize = (qint64)_limitFileBufferSize->value() * 1024 * 1024;
0178   config._useThreads =_useThreads->isChecked();
0179   config._timeAsciiFormatString = _timeAsciiFormatString->text();
0180   config._dataRate = _dataRate->value();
0181   config._offsetDateTime = _offsetDateTime->isChecked();
0182   config._offsetFileDate = _offsetFileDate->isChecked();
0183   config._offsetRelative = _offsetRelative->isChecked();
0184   config._dateTimeOffset = _dateTimeOffset->dateTime();
0185   config._relativeOffset = _relativeOffset->value();
0186   config._nanValue = _nanNull->isChecked()
0187                      ? 0 : _nanNAN->isChecked()
0188                            ? 1 : _nanPrevious->isChecked()
0189                                  ? 2 : 0;
0190   return config;
0191 }
0192 
0193 void AsciiConfigWidgetInternal::setFilename(const QString& filename)
0194 {
0195   _filename = filename;
0196   //_dateTimeOffset->setDateTime(QFileInfo(_filename).lastModified());
0197   showBeginning();
0198 }
0199 
0200 
0201 void AsciiConfigWidgetInternal::setConfig(const AsciiSourceConfig& config)
0202 {
0203   _delimiters->setText(config._delimiters);
0204 
0205   // "Always accept files matching" is ... odd and currently worthless.
0206   // Here is what it does:
0207   // If _fileNamePattern, which is saved only associated with <filename>
0208   // matches <filename> then assume <filename> is ascii and do no further
0209   // checks.  Why one would want this is unclear to me.
0210   // TODO: fix this!
0211   // Here we hide the 'feature' until it is made into something useful.
0212   //_fileNamePattern->setText(config._fileNamePattern);
0213   _fileNamePattern->hide();
0214   textLabel1_2->hide();
0215 
0216   _columnDelimiter->setText(config._columnDelimiter);
0217   _columnWidth->setValue(config._columnWidth);
0218   _colWidthConst->setChecked(config._columnWidthIsConst);
0219   _readFields->setChecked(config._readFields);
0220   _readUnits->setChecked(config._readUnits);
0221   _useDot->setChecked(config._useDot);
0222   _useComma->setChecked(!config._useDot);
0223 
0224   _startLine->setValue(config._dataLine + _index_offset);
0225   _fieldsLine->setValue(config._fieldsLine + _index_offset);
0226   _unitsLine->setValue(config._unitsLine + _index_offset);
0227 
0228   AsciiSourceConfig::ColumnType ct = (AsciiSourceConfig::ColumnType) config._columnType.value();
0229   if (ct == AsciiSourceConfig::Fixed) {
0230     _fixed->setChecked(true);
0231   } else if (ct == AsciiSourceConfig::Custom) {
0232     _custom->setChecked(true);
0233   } else {
0234     _whitespace->setChecked(true);
0235   }
0236 
0237   _limitFileBuffer->setChecked(config._limitFileBuffer);
0238   _limitFileBufferSize->setValue(config._limitFileBufferSize / 1024 / 1024);
0239 
0240   _useThreads->setChecked(config._useThreads);
0241   _timeAsciiFormatString->setText(config._timeAsciiFormatString);
0242   _dataRate->setValue(config._dataRate.value());
0243   _offsetDateTime->setChecked(config._offsetDateTime.value());
0244   _offsetFileDate->setChecked(config._offsetFileDate.value());
0245   _offsetRelative->setChecked(config._offsetRelative.value());
0246   _dateTimeOffset->setDateTime(config._dateTimeOffset.value());
0247   _relativeOffset->setValue(config._relativeOffset.value());
0248   switch (config._nanValue.value()) {
0249   case 0: _nanNull->setChecked(true); break;
0250   case 1: _nanNAN->setChecked(true); break;
0251   case 2: _nanPrevious->setChecked(true); break;
0252   default: _nanNull->setChecked(true); break;
0253   }
0254 }
0255 
0256 
0257 AsciiConfigWidget::AsciiConfigWidget(QSettings& s)
0258     : Kst::DataSourceConfigWidget(s),
0259     _busy_loading(false) {
0260   QGridLayout *layout = new QGridLayout(this);
0261   _ac = new AsciiConfigWidgetInternal(this);
0262   layout->addWidget(_ac, 0, 0);
0263   layout->activate();
0264   _oldConfig = _ac->config();
0265   connect(_ac->_readFields, SIGNAL(clicked()), this, SLOT(updateIndexVector()));
0266   connect(_ac->_fieldsLine, SIGNAL(valueChanged(int)), this, SLOT(updateIndexVector()));
0267   connect(_ac->_whitespace, SIGNAL(clicked()), this, SLOT(updateIndexVector()));
0268   connect(_ac->_custom, SIGNAL(clicked()), this, SLOT(updateIndexVector()));
0269   connect(_ac->_fixed, SIGNAL(clicked()), this, SLOT(updateIndexVector()));
0270 }
0271 
0272 
0273 AsciiConfigWidget::~AsciiConfigWidget() {
0274 }
0275 
0276 
0277 void AsciiConfigWidget::setDialogParent(QDialog* parent)
0278 {
0279   parent->setWindowModality(Qt::WindowModal);
0280   DataSourceConfigWidget::setDialogParent(parent);
0281 }
0282 
0283 void AsciiConfigWidget::setFilename(const QString& filename)
0284 {
0285   _ac->setFilename(filename);
0286 }
0287 
0288 void AsciiConfigWidget::updateIndexVector() {
0289   if (_busy_loading)
0290     return;
0291   save();
0292   _ac->_indexVector->clear();
0293 
0294   if (hasInstance()) {
0295     Kst::SharedPtr<AsciiSource> src = Kst::kst_cast<AsciiSource>(instance());
0296     _ac->_indexVector->addItems(src->fieldListFor(src->fileName(), _ac->config()));
0297   }
0298 }
0299 
0300 
0301 void AsciiConfigWidget::cancel() {
0302   // revert to _oldConfig
0303   _ac->setConfig(_oldConfig);
0304 
0305   if (hasInstance()) {
0306     Kst::SharedPtr<AsciiSource> src = Kst::kst_cast<AsciiSource>(instance());
0307     _ac->config().saveGroup(settings(), src->fileName());
0308 
0309     // Update the instance from our new settings
0310     if (src->reusable()) {
0311       src->_config.readGroup(settings(), src->fileName());
0312       if (_ac->config().isUpdateNecessary(_oldConfig)) {
0313         src->reset();
0314         src->updateLists();
0315       }
0316     }
0317   }
0318 }
0319 
0320 
0321 void AsciiConfigWidget::load() {
0322   _busy_loading = true;
0323   AsciiSourceConfig config;
0324   if (hasInstance())
0325     config.readGroup(settings(), instance()->fileName());
0326   else
0327     config.readGroup(settings());
0328 
0329   _ac->setConfig(config);
0330 
0331   // Now handle index
0332   _ac->_indexVector->clear();
0333   if (hasInstance()) {
0334     Kst::SharedPtr<AsciiSource> src = Kst::kst_cast<AsciiSource>(instance());
0335     _ac->_indexVector->addItems(src->fieldListFor(src->fileName(), _ac->config()));
0336 
0337     if (src->_config._indexInterpretation == AsciiSourceConfig::CTime) {
0338       _ac->_interpret->setChecked(true);
0339       _ac->_ctime->setChecked(true);
0340     } else if (src->_config._indexInterpretation == AsciiSourceConfig::Seconds) {
0341       _ac->_interpret->setChecked(true);
0342       _ac->_seconds->setChecked(true);
0343     } else if (src->_config._indexInterpretation == AsciiSourceConfig::FormattedTime) {
0344       _ac->_interpret->setChecked(true);
0345       _ac->_formattedString->setChecked(true);
0346     } else if (src->_config._indexInterpretation == AsciiSourceConfig::FixedRate) {
0347       _ac->_interpret->setChecked(true);
0348       _ac->_indexFreq->setChecked(true);
0349     } else if (src->_config._indexInterpretation == AsciiSourceConfig::NoInterpretation) {
0350       _ac->_interpret->setChecked(false);
0351     }
0352 
0353     if (src->vector().list().contains(src->_config._indexVector)) {
0354       int idx = _ac->_indexVector->findText(src->_config._indexVector);
0355       if (idx == -1)
0356         idx = _ac->_indexVector->findText("INDEX");
0357       _ac->_indexVector->setCurrentIndex(idx == -1 ? 0 : idx);
0358     }
0359   } else {
0360     _ac->_indexVector->addItem("INDEX");
0361 
0362     if (config._indexInterpretation == AsciiSourceConfig::CTime) {
0363       _ac->_interpret->setChecked(true);
0364       _ac->_ctime->setChecked(true);
0365     } else if (config._indexInterpretation == AsciiSourceConfig::Seconds) {
0366       _ac->_interpret->setChecked(true);
0367       _ac->_seconds->setChecked(true);
0368     } else if (config._indexInterpretation == AsciiSourceConfig::FormattedTime) {
0369       _ac->_interpret->setChecked(true);
0370       _ac->_formattedString->setChecked(true);
0371     } else if (config._indexInterpretation == AsciiSourceConfig::FixedRate) {
0372       _ac->_interpret->setChecked(true);
0373       _ac->_indexFreq->setChecked(true);
0374     } else if (config._indexInterpretation == AsciiSourceConfig::NoInterpretation) {
0375       _ac->_interpret->setChecked(false);
0376     }
0377 
0378   }
0379   if (_ac->_interpret->isChecked()) {
0380     _ac->_indexVector->setEnabled(hasInstance());
0381   }
0382   _oldConfig = _ac->config();
0383   _busy_loading = false;
0384 }
0385 
0386 
0387 void AsciiConfigWidget::save() {
0388   if (_busy_loading)
0389     return;
0390   if (hasInstance()) {
0391     Kst::SharedPtr<AsciiSource> src = Kst::kst_cast<AsciiSource>(instance());
0392     if (_ac->_applyDefault->isChecked()) {
0393       _ac->config().saveDefault(settings());
0394     }
0395     _ac->config().saveGroup(settings(), src->fileName());
0396 
0397     // Update the instance from our new settings
0398     if (src->reusable()) {
0399       src->_config.readGroup(settings(), src->fileName());
0400       if (_ac->config().isUpdateNecessary(_oldConfig)) {
0401         src->reset();
0402         src->updateLists();
0403         src->store()->resetDataSourceDependents(src->fileName());
0404       }
0405     }
0406   }
0407 }
0408 
0409 bool AsciiConfigWidget::isOkAcceptabe() const {
0410   AsciiSourceConfig config = _ac->config();
0411   QString msg;
0412   if (config._readFields) {
0413     if (config._fieldsLine == config._dataLine) {
0414       msg = tr("Line %1 can not list field names AND values!").arg(config._fieldsLine + 1);
0415     }
0416     if (config._readUnits) {
0417       if (config._unitsLine == config._dataLine) {
0418         msg = tr("Line %1 can not list units AND values!").arg(config._unitsLine + 1);
0419       }
0420       if (config._unitsLine == config._fieldsLine) {
0421         msg = tr("Line %1 can not list field names AND units!").arg(config._unitsLine + 1);
0422       }
0423     }
0424   }
0425   if (!msg.isEmpty()) {
0426     QMessageBox::critical(0, tr("Inconsistent parameters"), msg);
0427     return false;
0428   }
0429   return true;
0430 }
0431 
0432 
0433 // vim: ts=2 sw=2 et