File indexing completed on 2024-12-22 04:17:13
0001 /*************************************************************************** 0002 dirfile.cpp - data source for dirfiles 0003 ------------------- 0004 begin : Tue Oct 21 2003 0005 copyright : (C) 2003 The University of Toronto 0006 email : netterfield@astro.utoronto.ca 0007 ***************************************************************************/ 0008 0009 /*************************************************************************** 0010 * * 0011 * This program is free software; you can redistribute it and/or modify * 0012 * it under the terms of the GNU General Public License as published by * 0013 * the Free Software Foundation; either version 2 of the License, or * 0014 * (at your option) any later version. * 0015 * * 0016 ***************************************************************************/ 0017 0018 #include "dirfilesource.h" 0019 0020 0021 #include <QXmlStreamWriter> 0022 #include <QFileSystemWatcher> 0023 #include <QDir> 0024 0025 using namespace Kst; 0026 0027 static const QString dirfileTypeString = "Directory of Binary Files"; 0028 0029 class DirFileSource::Config { 0030 public: 0031 Config() { 0032 } 0033 0034 void read(QSettings *cfg, const QString& fileName = QString()) { 0035 Q_UNUSED(fileName); 0036 cfg->beginGroup(dirfileTypeString); 0037 cfg->endGroup(); 0038 } 0039 0040 void save(QXmlStreamWriter& s) { 0041 Q_UNUSED(s); 0042 } 0043 0044 void load(const QDomElement& e) { 0045 Q_UNUSED(e); 0046 } 0047 }; 0048 0049 // 0050 // Scalar Interface 0051 // 0052 class DataInterfaceDirFileScalar : public DataSource::DataInterface<DataScalar> 0053 { 0054 public: 0055 DataInterfaceDirFileScalar(DirFileSource& d) : dir(d) {} 0056 0057 // read one element 0058 int read(const QString&, DataScalar::ReadInfo&); 0059 0060 // named elements 0061 QStringList list() const { return dir._scalarList; } 0062 bool isListComplete() const { return true; } 0063 bool isValid(const QString& field) const { return dir._scalarList.contains( field ); } 0064 0065 // T specific: not used for scalars 0066 const DataScalar::DataInfo dataInfo(const QString&, int frame = 0) const { Q_UNUSED(frame) return DataScalar::DataInfo(); } 0067 void setDataInfo(const QString&, const DataScalar::DataInfo&) {} 0068 0069 // meta data 0070 QMap<QString, double> metaScalars(const QString&) { return QMap<QString, double>(); } 0071 QMap<QString, QString> metaStrings(const QString&) { return QMap<QString, QString>(); } 0072 0073 0074 DirFileSource& dir; 0075 }; 0076 0077 int DataInterfaceDirFileScalar::read(const QString& field, DataScalar::ReadInfo& p) 0078 { 0079 return dir.readScalar(*p.value, field); 0080 } 0081 0082 // 0083 // String Interface 0084 // 0085 class DataInterfaceDirFileString : public DataSource::DataInterface<DataString> 0086 { 0087 public: 0088 DataInterfaceDirFileString(DirFileSource& d) : dir(d) {} 0089 0090 // read one element 0091 int read(const QString&, DataString::ReadInfo&); 0092 0093 // named elements 0094 QStringList list() const { return dir._stringList; } 0095 bool isListComplete() const { return true; } 0096 bool isValid(const QString& field) const { return dir._stringList.contains( field ); } 0097 0098 // T specific: not used for Strings 0099 virtual const DataString::DataInfo dataInfo(const QString&, int frame=0) const; 0100 void setDataInfo(const QString&, const DataString::DataInfo&) {} 0101 0102 // meta data 0103 QMap<QString, double> metaScalars(const QString&) { return QMap<QString, double>(); } 0104 QMap<QString, QString> metaStrings(const QString&) { return QMap<QString, QString>(); } 0105 0106 0107 DirFileSource& dir; 0108 }; 0109 0110 int DataInterfaceDirFileString::read(const QString& field, DataString::ReadInfo& p) 0111 { 0112 if (dir.isStringStream(field)) { 0113 return dir.readSindir(*p.value, field, p.frame); 0114 } else { 0115 return dir.readString(*p.value, field); 0116 } 0117 } 0118 0119 const DataString::DataInfo DataInterfaceDirFileString::dataInfo(const QString &, int frame) const 0120 { 0121 Q_UNUSED(frame) 0122 0123 DataString::DataInfo info; 0124 info.frameCount = dir.frameCount(); 0125 0126 return info; 0127 } 0128 0129 0130 // 0131 // Vector interface 0132 // 0133 0134 class DataInterfaceDirFileVector : public DataSource::DataInterface<DataVector> 0135 { 0136 public: 0137 DataInterfaceDirFileVector(DirFileSource& d) : dir(d) {} 0138 0139 // read one element 0140 int read(const QString&, DataVector::ReadInfo&); 0141 0142 // named elements 0143 QStringList list() const { return dir._fieldList; } 0144 bool isListComplete() const { return true; } 0145 bool isValid(const QString& field) const { return dir._fieldList.contains( field ); } 0146 0147 // T specific 0148 const DataVector::DataInfo dataInfo(const QString&, int frame = 0) const; 0149 void setDataInfo(const QString&, const DataVector::DataInfo&) {} 0150 0151 // meta data 0152 QMap<QString, double> metaScalars(const QString&); 0153 QMap<QString, QString> metaStrings(const QString&); 0154 0155 0156 DirFileSource& dir; 0157 }; 0158 0159 0160 0161 const DataVector::DataInfo DataInterfaceDirFileVector::dataInfo(const QString &field, int frame) const 0162 { 0163 Q_UNUSED(frame) 0164 if (!dir._fieldList.contains(field)) 0165 return DataVector::DataInfo(); 0166 0167 return DataVector::DataInfo(dir._frameCount, dir.samplesPerFrame(field)); 0168 } 0169 0170 0171 int DataInterfaceDirFileVector::read(const QString& field, DataVector::ReadInfo& p) 0172 { 0173 return dir.readField(p.data, field, p.startingFrame, p.numberOfFrames); 0174 } 0175 0176 0177 QMap<QString, double> DataInterfaceDirFileVector::metaScalars(const QString& field) 0178 { 0179 QStringList keys = dir.fieldScalars(field); 0180 QList<double> values; 0181 int scalars = dir.readFieldScalars(values, field, true); 0182 QMap<QString, double> m; 0183 for (int i = 0; i < scalars; i++) { 0184 if (values.size() > i && keys.size() > i) 0185 m[keys.at(i)] = values.at(i); 0186 } 0187 return m; 0188 } 0189 0190 0191 QMap<QString, QString> DataInterfaceDirFileVector::metaStrings(const QString& field) 0192 { 0193 QStringList keys = dir.fieldStrings(field); 0194 QStringList values; 0195 int strings = dir.readFieldStrings(values, field, true); 0196 QMap<QString, QString> m; 0197 for (int i = 0; i < strings; i++) { 0198 if (values.size() > i && keys.size() > i) 0199 m[keys.at(i)] = values.at(i); 0200 } 0201 return m; 0202 } 0203 0204 // 0205 // DirFileSource 0206 // 0207 0208 DirFileSource::DirFileSource(Kst::ObjectStore *store, QSettings *cfg, const QString& filename, const QString& type, const QDomElement& e) : 0209 Kst::DataSource(store, cfg, filename, type), _config(0L), 0210 iv(new DataInterfaceDirFileVector(*this)), ix(new DataInterfaceDirFileScalar(*this)), 0211 is(new DataInterfaceDirFileString(*this)), _resetNeeded(false) 0212 { 0213 setInterface(iv); 0214 setInterface(ix); 0215 setInterface(is); 0216 0217 setUpdateType(None); 0218 0219 _valid = false; 0220 if (!type.isEmpty() && type != dirfileTypeString) { 0221 return; 0222 } 0223 0224 _config = new DirFileSource::Config; 0225 _config->read(cfg, _filename); 0226 if (!e.isNull()) { 0227 _config->load(e); 0228 } 0229 0230 _valid = true; 0231 _directoryName = DirFilePlugin::getDirectory(_filename); 0232 0233 init(); 0234 registerChange(); 0235 0236 } 0237 0238 0239 0240 DirFileSource::~DirFileSource() 0241 { 0242 delete _config; 0243 _config = 0L; 0244 delete _dirfile; 0245 _dirfile = 0L; 0246 } 0247 0248 0249 void DirFileSource::reset() 0250 { 0251 resetFileWatcher(); 0252 if (_dirfile) { 0253 delete _dirfile; 0254 } 0255 0256 init(); 0257 Object::reset(); 0258 } 0259 0260 0261 bool DirFileSource::init() { 0262 _fieldList.clear(); 0263 _scalarList.clear(); 0264 _stringList.clear(); 0265 _sindirList.clear(); 0266 0267 _frameCount = 0; 0268 0269 _dirfile = new Dirfile(_directoryName.toLatin1(), GD_RDONLY); 0270 0271 if (_dirfile->Error() == GD_E_OK) { 0272 0273 const char **vl = _dirfile->VectorList(); 0274 for (int i = 0; vl[i]!=NULL; i++) { 0275 _fieldList.append(QString::fromUtf8(vl[i])); 0276 } 0277 0278 _scalarList.append("FRAMES"); 0279 const char **xl = _dirfile->FieldListByType(ConstEntryType); 0280 for (int i = 0; xl[i]!=NULL; i++) { 0281 _scalarList.append(QString::fromUtf8(xl[i])); 0282 } 0283 0284 _stringList.append("FILE"); 0285 const char **tl = _dirfile->FieldListByType(StringEntryType); 0286 for (int i = 0; tl[i]!=NULL; i++) { 0287 _stringList.append(QString::fromUtf8(tl[i])); 0288 } 0289 0290 const char **nl = _dirfile->FieldListByType(SindirEntryType); 0291 for (int i = 0; nl[i]!=NULL; i++) { 0292 _sindirList.append(QString::fromUtf8(nl[i])); 0293 _stringList.append(QString::fromUtf8(nl[i])); // _stringList contains both 0294 } 0295 0296 _writable = true; 0297 _frameCount = _dirfile->NFrames(); 0298 } 0299 0300 if (_fieldList.count() > 1) { 0301 QString filePath = _dirfile->ReferenceFilename(); 0302 } 0303 setUpdateType(Timer); 0304 0305 registerChange(); 0306 return true; 0307 } 0308 0309 0310 Kst::Object::UpdateType DirFileSource::internalDataSourceUpdate() { 0311 int newNF = _dirfile->NFrames(); 0312 bool isnew = newNF != _frameCount; 0313 0314 _resetNeeded |= (_frameCount>newNF); 0315 0316 _frameCount = newNF; 0317 0318 if (_resetNeeded && newNF>0) { 0319 _resetNeeded = false; 0320 reset(); 0321 } 0322 return (isnew ? Updated : NoChange); 0323 } 0324 0325 int DirFileSource::readField(double *v, const QString& field, int s, int n) { 0326 0327 if (n < 0) { 0328 return _dirfile->GetData(field.toUtf8().constData(), 0329 s, 0, /* 1st sframe, 1st samp */ 0330 0, 1, /* num sframes, num samps */ 0331 Float64, (void*)v); 0332 } else { 0333 return _dirfile->GetData(field.toUtf8().constData(), 0334 s, 0, /* 1st sframe, 1st samp */ 0335 n, 0, /* num sframes, num samps */ 0336 Float64, (void*)v); 0337 } 0338 } 0339 0340 0341 // int DirFileSource::writeField(const double *v, const QString& field, int s, int n) { 0342 // int err = 0; 0343 // 0344 // return PutData(_directoryName.toLatin1(), field.left(FIELD_LENGTH).toLatin1(), 0345 // s, 0, /* 1st sframe, 1st samp */ 0346 // n, 0, /* num sframes, num samps */ 0347 // 'd', (void*)v, 0348 // &err); 0349 // } 0350 0351 0352 int DirFileSource::samplesPerFrame(const QString &field) { 0353 return int(_dirfile->SamplesPerFrame(field.toUtf8().constData())); 0354 } 0355 0356 0357 int DirFileSource::frameCount(const QString& field) const { 0358 Q_UNUSED(field) 0359 return _frameCount; 0360 } 0361 0362 0363 bool DirFileSource::isEmpty() const { 0364 return _frameCount < 1; 0365 } 0366 0367 0368 QString DirFileSource::fileType() const { 0369 return dirfileTypeString; 0370 } 0371 0372 0373 void DirFileSource::save(QXmlStreamWriter &streamWriter) { 0374 Kst::DataSource::save(streamWriter); 0375 } 0376 0377 0378 int DirFileSource::readScalar(double &S, const QString& scalar) { 0379 if (scalar == "FRAMES") { 0380 S = _frameCount; 0381 return 1; 0382 } else { 0383 _dirfile->GetConstant(scalar.toUtf8().constData(), Float64, (void *)&S); 0384 if (_dirfile->Error() == GD_E_OK) { 0385 return 1; 0386 } 0387 } 0388 0389 return 0; 0390 } 0391 0392 0393 int DirFileSource::readString(QString &S, const QString& string) { 0394 if (string == "FILE") { 0395 S = _filename; 0396 return 1; 0397 } else { 0398 char tmpstr[4097]; 0399 _dirfile->GetString(string.toUtf8().constData(), 4097, tmpstr); 0400 if (_dirfile->Error() == GD_E_OK) { 0401 S = QString::fromUtf8(tmpstr); 0402 return 1; 0403 } 0404 } 0405 0406 return 0; 0407 } 0408 0409 int DirFileSource::readSindir(QString &S, const QString &field, int frame) { 0410 const char *tmpstr[1]; 0411 0412 _dirfile->GetData(field.toUtf8().constData(), frame, 0, 0, 1, tmpstr); 0413 if (_dirfile->Error() == GD_E_OK) { 0414 S = QString::fromUtf8(tmpstr[0]); 0415 return 1; 0416 } 0417 0418 return 0; 0419 } 0420 0421 //QStringList fieldScalars(const QString& field); 0422 0423 QStringList DirFileSource::fieldScalars(const QString& field) { 0424 const char **mflist = _dirfile->MFieldListByType(field.toAscii(), ConstEntryType); 0425 if (!mflist) { 0426 return QStringList(); 0427 } 0428 QStringList scalars; 0429 for (int i=0; mflist[i]; i++) { 0430 scalars.append(mflist[i]); 0431 } 0432 return scalars; 0433 } 0434 0435 int DirFileSource::readFieldScalars(QList<double> &v, const QString& field, bool init) { 0436 int nc=0; 0437 if (init) { // only update if we need to initialize. Otherwise preserve old values. 0438 v.clear(); 0439 nc = _dirfile->NMFieldsByType(field.toAscii(),ConstEntryType); 0440 double *vin = (double *)_dirfile->MConstants(field.toAscii(), Float64); 0441 for (int i=0; i<nc; i++) { 0442 v.append(vin[i]); 0443 } 0444 } 0445 return (nc); 0446 } 0447 0448 0449 QStringList DirFileSource::fieldStrings(const QString& field) { 0450 const char **mflist = _dirfile->MFieldListByType(field.toAscii(), StringEntryType); 0451 if (!mflist) { 0452 return QStringList(); 0453 } 0454 QStringList strings; 0455 for (int i=0; mflist[i]; i++) { 0456 strings.append(mflist[i]); 0457 } 0458 return strings; 0459 } 0460 0461 int DirFileSource::readFieldStrings(QStringList &v, const QString& field, bool init) { 0462 int nc=0; 0463 if (init) { // only update if we need to initialize. Otherwise preserve old values. 0464 v.clear(); 0465 nc = _dirfile->NMFieldsByType(field.toAscii(),StringEntryType); 0466 char **str_in = (char **)_dirfile->MStrings(field.toAscii()); 0467 for (int i=0; i<nc; i++) { 0468 v.append(str_in[i]); 0469 } 0470 } 0471 return (nc); 0472 } 0473 0474 0475 QString DirFilePlugin::pluginName() const { return tr("DirFile Reader"); } 0476 QString DirFilePlugin::pluginDescription() const { return tr("DirFile Reader"); } 0477 0478 0479 Kst::DataSource *DirFilePlugin::create(Kst::ObjectStore *store, 0480 QSettings *cfg, 0481 const QString &filename, 0482 const QString &type, 0483 const QDomElement &element) const { 0484 return new DirFileSource(store, cfg, filename, type, element); 0485 } 0486 0487 0488 0489 QStringList DirFilePlugin::matrixList(QSettings *cfg, 0490 const QString& filename, 0491 const QString& type, 0492 QString *typeSuggestion, 0493 bool *complete) const { 0494 0495 0496 if (typeSuggestion) { 0497 *typeSuggestion = dirfileTypeString; 0498 } 0499 if ((!type.isEmpty() && !provides().contains(type)) || 0500 0 == understands(cfg, filename)) { 0501 if (complete) { 0502 *complete = false; 0503 } 0504 return QStringList(); 0505 } 0506 return QStringList(); 0507 } 0508 0509 const QString& DirFileSource::typeString() const { 0510 return dirfileTypeString; 0511 } 0512 0513 bool DirFileSource::isStringStream(QString field) 0514 { 0515 if (_sindirList.contains(field)) { 0516 return true; 0517 } else { 0518 return false; 0519 } 0520 } 0521 0522 0523 0524 QStringList DirFilePlugin::scalarList(QSettings *cfg, 0525 const QString& filename, 0526 const QString& type, 0527 QString *typeSuggestion, 0528 bool *complete) const { 0529 0530 Q_UNUSED(cfg); 0531 Q_UNUSED(type) 0532 QStringList scalarList; 0533 0534 Dirfile dirfile(getDirectory(filename).toLatin1(), GD_RDONLY); 0535 if (dirfile.Error() == GD_E_OK) { 0536 0537 scalarList.append("FRAMES"); 0538 const char **xl = dirfile.FieldListByType(ConstEntryType); 0539 for (int i = 0; xl[i]!=NULL; i++) { 0540 scalarList.append(QString::fromUtf8(xl[i])); 0541 } 0542 } 0543 0544 if (complete) { 0545 *complete = true; 0546 } 0547 0548 if (typeSuggestion) { 0549 *typeSuggestion = dirfileTypeString; 0550 } 0551 0552 return scalarList; 0553 } 0554 0555 QStringList DirFilePlugin::stringList(QSettings *cfg, 0556 const QString& filename, 0557 const QString& type, 0558 QString *typeSuggestion, 0559 bool *complete) const { 0560 Q_UNUSED(cfg); 0561 Q_UNUSED(type) 0562 QStringList stringList; 0563 0564 Dirfile dirfile(getDirectory(filename).toLatin1(), GD_RDONLY); 0565 0566 if (dirfile.Error() == GD_E_OK) { 0567 0568 stringList.append("FILE"); 0569 const char **tl = dirfile.FieldListByType(StringEntryType); 0570 for (int i = 0; tl[i]!=NULL; i++) { 0571 stringList.append(QString::fromUtf8(tl[i])); 0572 } 0573 } 0574 0575 if (complete) { 0576 *complete = true; 0577 } 0578 0579 if (typeSuggestion) { 0580 *typeSuggestion = dirfileTypeString; 0581 } 0582 0583 return stringList; 0584 } 0585 0586 QStringList DirFilePlugin::fieldList(QSettings *cfg, 0587 const QString& filename, 0588 const QString& type, 0589 QString *typeSuggestion, 0590 bool *complete) const { 0591 Q_UNUSED(cfg); 0592 Q_UNUSED(type) 0593 0594 QStringList fieldList; 0595 0596 Dirfile dirfile(getDirectory(filename).toLatin1(), GD_RDONLY); 0597 0598 if (dirfile.Error() == GD_E_OK) { 0599 0600 const char **vl = dirfile.VectorList(); 0601 for (int i = 0; vl[i]!=NULL; i++) { 0602 fieldList.append(QString::fromUtf8(vl[i])); 0603 } 0604 } 0605 0606 if (complete) { 0607 *complete = true; 0608 } 0609 0610 if (typeSuggestion) { 0611 *typeSuggestion = dirfileTypeString; 0612 } 0613 0614 return fieldList; 0615 } 0616 0617 0618 QString DirFilePlugin::getDirectory(QString filepath) { 0619 QFileInfo info(filepath); 0620 QString properDirPath = info.path(); 0621 if (info.fileName() == "format") { 0622 //do nothing... allows for format file to be selected. 0623 } else if (info.isDir()) { 0624 //do nothing... a directory was selected. 0625 properDirPath = filepath; 0626 } else { 0627 QFile file(filepath); 0628 if (file.open(QFile::ReadOnly)) { 0629 QTextStream stream(&file); 0630 QString directoryName = stream.readLine(1000); 0631 properDirPath += '/'; 0632 properDirPath += directoryName; 0633 } 0634 } 0635 return properDirPath; 0636 } 0637 0638 0639 int DirFilePlugin::understands(QSettings *cfg, const QString& filename) const { 0640 Q_UNUSED(cfg); 0641 0642 Dirfile dirfile(getDirectory(filename).toLatin1(), GD_RDONLY); 0643 0644 if (dirfile.Error() == GD_E_OK) { 0645 return 98; 0646 } 0647 return 0; 0648 } 0649 0650 0651 0652 bool DirFilePlugin::supportsTime(QSettings *cfg, const QString& filename) const { 0653 //FIXME 0654 Q_UNUSED(cfg) 0655 Q_UNUSED(filename) 0656 return true; 0657 } 0658 0659 0660 QStringList DirFilePlugin::provides() const { 0661 QStringList rc; 0662 rc += dirfileTypeString; 0663 return rc; 0664 } 0665 0666 0667 Kst::DataSourceConfigWidget *DirFilePlugin::configWidget(QSettings *cfg, const QString& filename) const { 0668 0669 Q_UNUSED(cfg) 0670 Q_UNUSED(filename) 0671 return 0;; 0672 0673 } 0674 0675 #ifndef QT5 0676 Q_EXPORT_PLUGIN2(kstdata_dirfile, DirFilePlugin) 0677 #endif 0678 0679 // vim: ts=2 sw=2 et