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