File indexing completed on 2024-12-22 04:17:19

0001 /***************************************************************************
0002                      datasource.h  -  abstract data source
0003                              -------------------
0004     begin                : Thu Oct 16 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 #ifndef DATASOURCE_H
0019 #define DATASOURCE_H
0020 
0021 #include "kst_export.h"
0022 #include "object.h"
0023 #include "dateparser.h"
0024 #include "objectlist.h"
0025 
0026 #include "datascalar.h"
0027 #include "datastring.h"
0028 #include "datavector.h"
0029 #include "datamatrix.h"
0030 #include "vscalar.h"
0031 
0032 #include <QRunnable>
0033 #include <QDialog>
0034 #include <QMap>
0035 
0036 class QSettings;
0037 class QXmlStreamWriter;
0038 class QXmlStreamAttributes;
0039 class QFileSystemWatcher;
0040 
0041 namespace Kst {
0042 
0043 class DataSourceConfigWidget;
0044 //class DataSourcePlugin;
0045 
0046 
0047 class KSTCORE_EXPORT DataSource : public Object
0048 {
0049   Q_OBJECT
0050 
0051   public:
0052     DataSource(ObjectStore *store, QSettings *cfg, const QString& filename, const QString& type);
0053     virtual ~DataSource();
0054 
0055     /************************************************************/
0056     /* Same interface for all supported Primitives              */
0057     /************************************************************/
0058 
0059     template<class T>
0060     struct DataInterface
0061     {
0062 
0063       virtual ~DataInterface() {}
0064       // read data.  The buffer and range info are in ReadInfo
0065       virtual int read(const QString& name, typename T::ReadInfo&) = 0;
0066       virtual void prepareRead(int number_of_read_calls) {}
0067       virtual void readingDone() {}
0068 
0069       // named elements
0070       virtual QStringList list() const = 0;
0071       virtual bool isListComplete() const = 0;
0072       virtual bool isValid(const QString& name) const = 0;
0073 
0074       // T specific
0075       virtual const typename T::DataInfo dataInfo(const QString& name, int frame=0) const = 0;
0076       virtual void setDataInfo(const QString& name, const typename T::DataInfo&) = 0;
0077 
0078       // meta data
0079       virtual QMap<QString, double> metaScalars(const QString& name) = 0;
0080       virtual QMap<QString, QString> metaStrings(const QString& name) = 0;
0081     };
0082 
0083 
0084     DataInterface<DataScalar>& scalar() {Q_ASSERT(interf_scalar); return *interf_scalar; }
0085     DataInterface<DataString>& string() {Q_ASSERT(interf_string); return *interf_string; }
0086     DataInterface<DataVector>& vector() {Q_ASSERT(interf_vector); return *interf_vector; }
0087     DataInterface<DataMatrix>& matrix() {Q_ASSERT(interf_matrix); return *interf_matrix; }
0088 
0089     const DataInterface<DataScalar>& scalar() const {Q_ASSERT(interf_scalar); return *interf_scalar; }
0090     const DataInterface<DataString>& string() const {Q_ASSERT(interf_string); return *interf_string; }
0091     const DataInterface<DataVector>& vector() const {Q_ASSERT(interf_vector); return *interf_vector; }
0092     const DataInterface<DataMatrix>& matrix() const {Q_ASSERT(interf_matrix); return *interf_matrix; }
0093 
0094 
0095 
0096     /************************************************************/
0097     /* Dynamic type system                                      */
0098     /************************************************************/
0099     virtual const QString& typeString() const;
0100     static const QString staticTypeString;
0101     static const QString staticTypeTag;
0102 
0103 
0104     /************************************************************/
0105     /* Methods for update system                                */
0106     /************************************************************/
0107 
0108     enum UpdateCheckType { Timer, File, None };
0109     virtual void setUpdateType(UpdateCheckType updateType);
0110     UpdateCheckType updateType() const;
0111     void startUpdating(UpdateCheckType updateType, const QString& file = QString());
0112 
0113 
0114     virtual UpdateType objectUpdate(qint64 newSerial);
0115 
0116     void internalUpdate() {return;} // unused - just here for linkage.
0117     
0118     qint64 minInputSerial() const {return 0;}
0119     qint64 maxInputSerialOfLastChange() const {return 0;}
0120 
0121    /** Updates number of samples.
0122       For ascii files, it also reads and writes to a temporary binary file.
0123       It must be implemented by the datasource. */
0124     virtual UpdateType internalDataSourceUpdate() = 0;
0125 
0126     /** some constructors create their datasource with their updates disabled
0127         because it may be expensive to parse the whole file.
0128         Call this function before actually using the data source (eg,
0129         in 'apply'. **/
0130     virtual void enableUpdates() {return;}
0131     /************************************************************/
0132     /* Methods for handling time in vectors.                    */
0133     /* not currently used - may be reworked (remove this note   */
0134     /* if you use it)                                           */
0135     /************************************************************/
0136     static bool supportsTime(const QString& plugin, const QString& type = QString());
0137     virtual QString timeFormat() const;
0138 
0139     /** Does it support time conversion of sample numbers, in general? */
0140     virtual bool supportsTimeConversions() const;
0141 
0142     virtual int sampleForTime(const QDateTime& time, bool *ok = 0L);
0143 
0144     virtual int sampleForTime(double milliseconds, bool *ok = 0L);
0145 
0146     virtual QDateTime timeForSample(int sample, bool *ok = 0L);
0147 
0148     // in (ms)
0149     virtual double relativeTimeForSample(int sample, bool *ok = 0L);
0150 
0151     /************************************************************/
0152     /* Methods for handling time in vectors. These are used.    */
0153     /************************************************************/
0154     virtual bool isTime(const QString &field) const;
0155 
0156 
0157     /************************************************************/
0158     /* Methods for using custom lookup vectors, like TIME.      */
0159     /* "Index" refers to custom lookup vector.                  */
0160     /* For all of these, a default implementation is provided   */
0161     /* in the base class.                                       */
0162     /************************************************************/
0163     /** returns the frame number corresponding to an index value from a frame */
0164     virtual int indexToFrame(double index, const QString &field);
0165     virtual double frameToIndex(int frame, const QString &field);
0166     virtual double readDespikedIndex(int frame, const QString &field);
0167     virtual double framePerIndex(const QString &field);
0168     virtual QStringList &timeFields();
0169     virtual QStringList &indexFields();
0170 
0171 
0172     /************************************************************/
0173     /* UI TODO leave here?                                      */
0174     /************************************************************/
0175     bool hasConfigWidget() const;
0176     DataSourceConfigWidget *configWidget();
0177     virtual void parseProperties(QXmlStreamAttributes &properties);
0178 
0179     bool reusable() const;
0180     void disableReuse();
0181 
0182     /************************************************************/
0183     /* Color for the "assign curve color per file" tool         */
0184     /************************************************************/
0185     QColor color() const;
0186     void setColor(const QColor& color);
0187 
0188     /************************************************************/
0189     /* File/data specific                                      */
0190     /************************************************************/
0191     virtual bool isValid() const; // generally you don't need to change this
0192 
0193     virtual QString fileName() const;
0194     QString alternateFilename() const;
0195     void setAlternateFilename(const QString &file);
0196 
0197     QMap<QString, QString> fileMetas() const;
0198 
0199     /** return true if <field> is an indexable list of matrices */
0200     virtual bool isImageStream(QString field) {Q_UNUSED(field) return false;}
0201 
0202     /** return true if <field> is an indexable list of strings */
0203     virtual bool isStringStream(QString field) {Q_UNUSED(field) return false;}
0204 
0205     /** Returns the file type or an error message in a static string
0206       The string is stored in a separate static variable, so changes
0207       to this are ignored.  It is updated each time the fn is called */
0208     virtual QString fileType() const;
0209 
0210     void saveSource(QXmlStreamWriter &s);
0211 
0212     /** Save file description info into stream s. */
0213     virtual void save(QXmlStreamWriter &s);
0214 
0215     const QString& sourceName() const { return _source; }
0216 
0217     /** Returns true if this file is empty */
0218     virtual bool isEmpty() const;
0219 
0220     /** Reset to initial state of the source, just as though no data had been
0221      *  read and the file had just been opened.
0222      */
0223     virtual void reset();
0224 
0225     virtual void deleteDependents();
0226 
0227     virtual QString descriptionTip() const;
0228 
0229     /** Creates a list of curves without user interaction
0230     */
0231     virtual ObjectList<Object> autoCurves(ObjectStore&) { return ObjectList<Object>(); }
0232 
0233     PrimitiveList slavePrimitives;
0234 
0235 
0236     static QString cleanPath(QString abs_path);
0237 
0238   public Q_SLOTS:
0239     virtual void checkUpdate();
0240 
0241   Q_SIGNALS:
0242     void sourceUpdated(ObjectPtr sourceObject);
0243     void progress(int percent, const QString& message);
0244 
0245 
0246   protected:
0247 
0248     /** Is the object valid? */
0249     bool _valid;
0250 
0251     bool _reusable;
0252 
0253     bool _writable;
0254 
0255     /** The filename.  Populated by the base class constructor.  */
0256     QString _filename;
0257 
0258     /** an alias for the file: for example if the file were replaced at load time */
0259     QString _alternateFilename;
0260 
0261     //friend class DataSourcePlugin;
0262 
0263     /** The source type name. */
0264     QString _source;
0265 
0266     QSettings *_cfg;
0267 
0268     UpdateCheckType _updateCheckType;
0269     void resetFileWatcher();
0270 
0271     virtual QString _automaticDescriptiveName() const;
0272     void _initializeShortName();
0273 
0274     void setInterface(DataInterface<DataScalar>*);
0275     void setInterface(DataInterface<DataString>*);
0276     void setInterface(DataInterface<DataVector>*);
0277     void setInterface(DataInterface<DataMatrix>*);
0278 
0279     QStringList _frameFields;
0280     QStringList _timeFields;
0281   private:
0282     DataSource();
0283 
0284     DataInterface<DataScalar>* interf_scalar;
0285     DataInterface<DataString>* interf_string;
0286     DataInterface<DataVector>* interf_vector;
0287     DataInterface<DataMatrix>* interf_matrix;
0288 
0289     QFileSystemWatcher *_watcher;
0290 
0291     QColor _color;
0292 
0293     // NOTE: You must bump the version key if you add new member variables
0294     //       or change or add virtual functions.
0295 };
0296 
0297 
0298 
0299 
0300 class DataSourceList : public QList<DataSourcePtr> {
0301   public:
0302     DataSourceList() : QList<DataSourcePtr>() {}
0303     DataSourceList(const DataSourceList& x) : QList<DataSourcePtr>(x) {}
0304     virtual ~DataSourceList() {}
0305 
0306     virtual DataSourcePtr findName(const QString name) {
0307       for (DataSourceList::Iterator it = begin(); it != end(); ++it) {
0308         if ((*it)->Name() == name) {
0309           return *it;
0310         }
0311       }
0312       return 0;
0313     }
0314 
0315     virtual DataSourcePtr findFileName(const QString& x) {
0316       for (DataSourceList::Iterator it = begin(); it != end(); ++it) {
0317         if ((*it)->fileName() == x) {
0318           return *it;
0319         }
0320       }
0321       return 0;
0322     }
0323 
0324     // @since 1.1.0
0325     DataSourcePtr findReusableFileName(const QString& x) {
0326       for (DataSourceList::Iterator it = begin(); it != end(); ++it) {
0327         if ((*it)->reusable()) {
0328           if ((*it)->fileName() == x) {
0329             return *it;
0330           } else if ((*it)->alternateFilename() == x) {
0331             return *it;
0332           }
0333         }
0334       }
0335       return 0;
0336     }
0337 
0338     // @since 1.1.0
0339     QStringList fileNames() const {
0340       QStringList rc;
0341       for (DataSourceList::ConstIterator it = begin(); it != end(); ++it) {
0342         rc << (*it)->fileName();
0343       }
0344       return rc;
0345     }
0346 
0347 #if QT_VERSION < 0x040500
0348     void append(const DataSourcePtr& ptr) {
0349       QList<DataSourcePtr>::append(ptr);
0350     }
0351     void append(const DataSourceList& list) {
0352       foreach(const DataSourcePtr& ptr, list) {
0353         QList<DataSourcePtr>::append(ptr);
0354       }
0355     }
0356 #endif
0357 
0358 };
0359 
0360 
0361 // @since 1.1.0
0362 class KSTCORE_EXPORT DataSourceConfigWidget : public QWidget
0363 {
0364   Q_OBJECT
0365 
0366   public:
0367     explicit DataSourceConfigWidget(QSettings&); // will be reparented later
0368     virtual ~DataSourceConfigWidget();
0369 
0370     QSettings& settings() const;
0371 
0372     // If _instance is nonzero, then your settings are to be saved for this
0373     // particular instance of the source, as opposed to globally.
0374     void setInstance(DataSourcePtr inst);
0375     DataSourcePtr instance() const;
0376     bool hasInstance() const;
0377 
0378     // Check if the widget could be closed,
0379     // and the user has not entered invalid parameters.
0380     virtual bool isOkAcceptabe() const;
0381 
0382     virtual void setDialogParent(QDialog* parent) { setParent(parent); }
0383 
0384   public slots:
0385     virtual void load() = 0;
0386     virtual void save() = 0;
0387     virtual void cancel() {return;}
0388 
0389   private:
0390     DataSourcePtr _instance;
0391     QSettings& _cfg;
0392     friend class DataSource;
0393 };
0394 
0395 
0396 class KSTCORE_EXPORT ValidateDataSourceThread : public QObject, public QRunnable
0397 {
0398   Q_OBJECT
0399 
0400   public:
0401     ValidateDataSourceThread(const QString& file, const int requestID);
0402     void run();
0403 
0404   Q_SIGNALS:
0405     void dataSourceValid(QString filename, int requestID);
0406     void dataSourceInvalid(int requestID);
0407 
0408   private:
0409     //ObjectStore *_store;
0410     QString _file;
0411     int _requestID;
0412 };
0413 
0414 
0415 }
0416 #endif
0417 // vim: ts=2 sw=2 et