svcore  1.9
SparseTimeValueModel.h
Go to the documentation of this file.
00001 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
00002 
00003 /*
00004     Sonic Visualiser
00005     An audio file viewer and annotation editor.
00006     Centre for Digital Music, Queen Mary, University of London.
00007     This file copyright 2006 Chris Cannam.
00008     
00009     This program is free software; you can redistribute it and/or
00010     modify it under the terms of the GNU General Public License as
00011     published by the Free Software Foundation; either version 2 of the
00012     License, or (at your option) any later version.  See the file
00013     COPYING included with this distribution for more information.
00014 */
00015 
00016 #ifndef _SPARSE_TIME_VALUE_MODEL_H_
00017 #define _SPARSE_TIME_VALUE_MODEL_H_
00018 
00019 #include "SparseValueModel.h"
00020 #include "base/PlayParameterRepository.h"
00021 #include "base/RealTime.h"
00022 
00029 struct TimeValuePoint
00030 {
00031 public:
00032     TimeValuePoint(long _frame) : frame(_frame), value(0.0f) { }
00033     TimeValuePoint(long _frame, float _value, QString _label) : 
00034         frame(_frame), value(_value), label(_label) { }
00035 
00036     int getDimensions() const { return 2; }
00037     
00038     long frame;
00039     float value;
00040     QString label;
00041 
00042     QString getLabel() const { return label; }
00043     
00044     void toXml(QTextStream &stream, QString indent = "",
00045                QString extraAttributes = "") const
00046     {
00047         stream << QString("%1<point frame=\"%2\" value=\"%3\" label=\"%4\" %5/>\n")
00048             .arg(indent).arg(frame).arg(value).arg(XmlExportable::encodeEntities(label))
00049             .arg(extraAttributes);
00050     }
00051 
00052     QString toDelimitedDataString(QString delimiter, int sampleRate) const
00053     {
00054         QStringList list;
00055         list << RealTime::frame2RealTime(frame, sampleRate).toString().c_str();
00056         list << QString("%1").arg(value);
00057         if (label != "") list << label;
00058         return list.join(delimiter);
00059     }
00060 
00061     struct Comparator {
00062         bool operator()(const TimeValuePoint &p1,
00063                         const TimeValuePoint &p2) const {
00064             if (p1.frame != p2.frame) return p1.frame < p2.frame;
00065             if (p1.value != p2.value) return p1.value < p2.value;
00066             return p1.label < p2.label;
00067         }
00068     };
00069     
00070     struct OrderComparator {
00071         bool operator()(const TimeValuePoint &p1,
00072                         const TimeValuePoint &p2) const {
00073             return p1.frame < p2.frame;
00074         }
00075     };
00076 };
00077 
00078 
00079 class SparseTimeValueModel : public SparseValueModel<TimeValuePoint>
00080 {
00081     Q_OBJECT
00082     
00083 public:
00084     SparseTimeValueModel(int sampleRate, int resolution,
00085                          bool notifyOnAdd = true) :
00086         SparseValueModel<TimeValuePoint>(sampleRate, resolution,
00087                                          notifyOnAdd)
00088     {
00089         // Model is playable, but may not sound (if units not Hz or
00090         // range unsuitable)
00091         PlayParameterRepository::getInstance()->addPlayable(this);
00092     }
00093 
00094     SparseTimeValueModel(int sampleRate, int resolution,
00095                          float valueMinimum, float valueMaximum,
00096                          bool notifyOnAdd = true) :
00097         SparseValueModel<TimeValuePoint>(sampleRate, resolution,
00098                                          valueMinimum, valueMaximum,
00099                                          notifyOnAdd)
00100     {
00101         // Model is playable, but may not sound (if units not Hz or
00102         // range unsuitable)
00103         PlayParameterRepository::getInstance()->addPlayable(this);
00104     }
00105 
00106     virtual ~SparseTimeValueModel()
00107     {
00108         PlayParameterRepository::getInstance()->removePlayable(this);
00109     }
00110 
00111     QString getTypeName() const { return tr("Sparse Time-Value"); }
00112 
00113     virtual bool canPlay() const { return true; }
00114     virtual bool getDefaultPlayAudible() const { return false; } // user must unmute
00115 
00120     virtual int getColumnCount() const
00121     {
00122         return 4;
00123     }
00124 
00125     virtual QString getHeading(int column) const
00126     {
00127         switch (column) {
00128         case 0: return tr("Time");
00129         case 1: return tr("Frame");
00130         case 2: return tr("Value");
00131         case 3: return tr("Label");
00132         default: return tr("Unknown");
00133         }
00134     }
00135 
00136     virtual QVariant getData(int row, int column, int role) const
00137     {
00138         if (column < 2) {
00139             return SparseValueModel<TimeValuePoint>::getData
00140                 (row, column, role);
00141         }
00142 
00143         PointListConstIterator i = getPointListIteratorForRow(row);
00144         if (i == m_points.end()) return QVariant();
00145 
00146         switch (column) {
00147         case 2:
00148             if (role == Qt::EditRole || role == SortRole) return i->value;
00149             else return QString("%1 %2").arg(i->value).arg(getScaleUnits());
00150         case 3: return i->label;
00151         default: return QVariant();
00152         }
00153     }
00154 
00155     virtual Command *getSetDataCommand(int row, int column, const QVariant &value, int role)
00156     {
00157         if (column < 2) {
00158             return SparseValueModel<TimeValuePoint>::getSetDataCommand
00159                 (row, column, value, role);
00160         }
00161 
00162         if (role != Qt::EditRole) return 0;
00163         PointListConstIterator i = getPointListIteratorForRow(row);
00164         if (i == m_points.end()) return 0;
00165         EditCommand *command = new EditCommand(this, tr("Edit Data"));
00166 
00167         Point point(*i);
00168         command->deletePoint(point);
00169 
00170         switch (column) {
00171         case 2: point.value = value.toDouble(); break;
00172         case 3: point.label = value.toString(); break;
00173         }
00174 
00175         command->addPoint(point);
00176         return command->finish();
00177     }
00178 
00179     virtual bool isColumnTimeValue(int column) const
00180     {
00181         return (column < 2); 
00182     }
00183 
00184     virtual SortType getSortType(int column) const
00185     {
00186         if (column == 3) return SortAlphabetical;
00187         return SortNumeric;
00188     }
00189 };
00190 
00191 
00192 #endif
00193 
00194 
00195