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

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 "asciiplugin.h"
0014 #include "asciiconfigwidget.h"
0015 #include "asciisourceconfig.h"
0016 #include "kst_atof.h"
0017 
0018 #include <QFile>
0019 #include <QFileInfo>
0020 #include <QButtonGroup>
0021 #include <QPlainTextEdit>
0022 #include <QMessageBox>
0023 QString AsciiPlugin::pluginName() const { return tr("ASCII File Reader"); }
0024 QString AsciiPlugin::pluginDescription() const { return tr("ASCII File Reader"); }
0025 
0026 const int max_line_length = 1000000;
0027 
0028 
0029 Kst::DataSource *AsciiPlugin::create(Kst::ObjectStore *store, QSettings *cfg,
0030                                             const QString &filename,
0031                                             const QString &type,
0032                                             const QDomElement &element) const {
0033 
0034   return new AsciiSource(store, cfg, filename, type, element);
0035 }
0036 
0037 
0038 QStringList AsciiPlugin::matrixList(QSettings *cfg,
0039                                              const QString& filename,
0040                                              const QString& type,
0041                                              QString *typeSuggestion,
0042                                              bool *complete) const {
0043 
0044   if (typeSuggestion) {
0045     *typeSuggestion = AsciiSource::asciiTypeKey();
0046   }
0047   if ((!type.isEmpty() && !provides().contains(type)) ||
0048       0 == understands(cfg, filename)) {
0049     if (complete) {
0050       *complete = false;
0051     }
0052     return QStringList();
0053   }
0054   return QStringList();
0055 }
0056 
0057 
0058 QStringList AsciiPlugin::fieldList(QSettings *cfg,
0059                                             const QString& filename,
0060                                             const QString& type,
0061                                             QString *typeSuggestion,
0062                                             bool *complete) const {
0063 
0064   if ((!type.isEmpty() && !provides().contains(type)) ||
0065       0 == understands(cfg, filename)) {
0066     if (complete) {
0067       *complete = false;
0068     }
0069     return QStringList();
0070   }
0071 
0072   if (typeSuggestion) {
0073     *typeSuggestion = AsciiSource::asciiTypeKey();
0074   }
0075 
0076   AsciiSourceConfig config;
0077   config.readGroup(*cfg, filename);
0078   QStringList rc = AsciiSource::fieldListFor(filename, config);
0079 
0080   if (complete) {
0081     *complete = rc.count() > 1;
0082   }
0083 
0084   return rc;
0085 
0086 }
0087 
0088 
0089 QStringList AsciiPlugin::scalarList(QSettings *cfg,
0090                                     const QString& filename,
0091                                     const QString& type,
0092                                     QString *typeSuggestion,
0093                                     bool *complete) const {
0094 
0095   if ((!type.isEmpty() && !provides().contains(type)) ||
0096       0 == understands(cfg, filename)) {
0097     if (complete) {
0098       *complete = false;
0099     }
0100     return QStringList();
0101   }
0102 
0103   if (typeSuggestion) {
0104     *typeSuggestion = AsciiSource::asciiTypeKey();
0105   }
0106 
0107   AsciiSourceConfig config;
0108   config.readGroup(*cfg, filename);
0109   QStringList rc = AsciiSource::scalarListFor(filename, config);
0110 
0111   if (complete) {
0112     *complete = rc.count() > 1;
0113   }
0114 
0115   return rc;
0116 
0117 }
0118 
0119 
0120 QStringList AsciiPlugin::stringList(QSettings *cfg,
0121                                     const QString& filename,
0122                                     const QString& type,
0123                                     QString *typeSuggestion,
0124                                     bool *complete) const {
0125 
0126   if ((!type.isEmpty() && !provides().contains(type)) ||
0127       0 == understands(cfg, filename)) {
0128     if (complete) {
0129       *complete = false;
0130     }
0131     return QStringList();
0132   }
0133 
0134   if (typeSuggestion) {
0135     *typeSuggestion = AsciiSource::asciiTypeKey();
0136   }
0137 
0138   AsciiSourceConfig config;
0139   config.readGroup(*cfg, filename);
0140   QStringList rc = AsciiSource::stringListFor(filename, config);
0141 
0142   if (complete) {
0143     *complete = rc.count() > 1;
0144   }
0145 
0146   return rc;
0147 
0148 }
0149 
0150 
0151 int AsciiPlugin::understands(QSettings *cfg, const QString& filename) const {
0152   AsciiSourceConfig config;
0153   config.readGroup(*cfg, filename);
0154 
0155   if (!QFile::exists(filename) || QFileInfo(filename).isDir()) {
0156     return 0;
0157   }
0158 
0159   // Apparently "Always accept files matching" is ... odd..
0160   // If _fileNamePattern, which is saved only associated with <filename>
0161   // matches <filename> then assume <filename> is ascii and do no further
0162   // checks.  Why one would want this is unclear to me.
0163   // TODO: fix this!
0164   if (!config._fileNamePattern.value().isEmpty()) {
0165     QRegExp filenamePattern(config._fileNamePattern);
0166     filenamePattern.setPatternSyntax(QRegExp::Wildcard);
0167     if (filenamePattern.exactMatch(filename)) {
0168       return 100;
0169     }
0170   }
0171 
0172   QFile f(filename);
0173   if (f.open(QIODevice::ReadOnly)) {    
0174 
0175     QRegExp commentRE;
0176     QRegExp dataRE;
0177     if (config._columnType == AsciiSourceConfig::Custom && !config._columnDelimiter.value().isEmpty()) {
0178       commentRE.setPattern(QString("^[%1]*[%2].*").arg(QRegExp::escape(config._columnDelimiter)).arg(config._delimiters));
0179       dataRE.setPattern(QString("^[%1]*(([Nn][Aa][Nn]|(\\-\\+)?[Ii][Nn][Ff]|[0-9\\+\\-\\.eE]+)[\\s]*)+").arg(QRegExp::escape(config._columnDelimiter)));
0180     } else {
0181       commentRE.setPattern(QString("^\\s*[%1].*").arg(config._delimiters));
0182       dataRE.setPattern(QString("^[\\s]*(([Nn][Aa][Nn]|(\\-\\+)?[Ii][Nn][Ff]|[0-9\\+\\-\\.eE]+)[\\s]*)+"));
0183     }
0184 
0185     int skip = config._dataLine;
0186     bool done = false;
0187     while (!done) {
0188       const QByteArray line = f.readLine(max_line_length);
0189       const int rc = line.size();
0190       if (skip > 0) {
0191         --skip;
0192         if (rc <= 0) {
0193           done = true;
0194         }
0195         continue;
0196       }
0197       if (rc <= 0) {
0198         done = true;
0199       } else if (rc == 1) {
0200         // empty line; do nothing
0201       } else if (commentRE.exactMatch(line)) {
0202         // comment; do nothing
0203       } else if (dataRE.exactMatch(line)) {
0204         // a number - this may be an ascii file - assume that it is
0205         // This line checks for an indirect file and gives that a chance too.
0206         // Indirect files look like ascii files.
0207         return 75;
0208         //return QFile::exists(line.trimmed()) ? 49 : 75;
0209       } else {
0210         return 20;
0211       }
0212     }
0213   } else {
0214     return 0;
0215   }
0216 
0217   return 1; // still might be ascii - ex: header with no data yet.
0218 }
0219 
0220 
0221 bool AsciiPlugin::supportsTime(QSettings *cfg, const QString& filename) const {
0222   //FIXME
0223   Q_UNUSED(cfg)
0224   Q_UNUSED(filename)
0225   return true;
0226 }
0227 
0228 
0229 QStringList AsciiPlugin::provides() const {
0230   return QStringList() <<AsciiSource::asciiTypeKey();
0231 }
0232 
0233 
0234 Kst::DataSourceConfigWidget *AsciiPlugin::configWidget(QSettings *cfg, const QString& filename) const {
0235   Q_UNUSED(filename)
0236   AsciiConfigWidget *config = new AsciiConfigWidget(*cfg);
0237   config->load();
0238   config->setFilename(filename);
0239   return config;
0240 }
0241 
0242 #ifndef QT5
0243 Q_EXPORT_PLUGIN2(kstdata_ascii, AsciiPlugin)
0244 #endif
0245 
0246 // vim: ts=2 sw=2 et