svcore  1.9
RegionModel.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 _REGION_MODEL_H_
00017 #define _REGION_MODEL_H_
00018 
00019 #include "IntervalModel.h"
00020 #include "base/RealTime.h"
00021 
00036 struct RegionRec
00037 {
00038 public:
00039     RegionRec() : frame(0), value(0.f), duration(0) { }
00040     RegionRec(long _frame) : frame(_frame), value(0.0f), duration(0) { }
00041     RegionRec(long _frame, float _value, int _duration, QString _label) :
00042         frame(_frame), value(_value), duration(_duration), label(_label) { }
00043 
00044     int getDimensions() const { return 3; }
00045 
00046     long frame;
00047     float value;
00048     int duration;
00049     QString label;
00050 
00051     QString getLabel() const { return label; }
00052     
00053     void toXml(QTextStream &stream,
00054                QString indent = "",
00055                QString extraAttributes = "") const
00056     {
00057         stream <<
00058             QString("%1<point frame=\"%2\" value=\"%3\" duration=\"%4\" label=\"%5\" %6/>\n")
00059             .arg(indent).arg(frame).arg(value).arg(duration)
00060             .arg(XmlExportable::encodeEntities(label)).arg(extraAttributes);
00061     }
00062 
00063     QString toDelimitedDataString(QString delimiter, int sampleRate) const
00064     {
00065         QStringList list;
00066         list << RealTime::frame2RealTime(frame, sampleRate).toString().c_str();
00067         list << QString("%1").arg(value);
00068         list << RealTime::frame2RealTime(duration, sampleRate).toString().c_str();
00069         if (label != "") list << label;
00070         return list.join(delimiter);
00071     }
00072 
00073     struct Comparator {
00074         bool operator()(const RegionRec &p1,
00075                         const RegionRec &p2) const {
00076             if (p1.frame != p2.frame) return p1.frame < p2.frame;
00077             if (p1.value != p2.value) return p1.value < p2.value;
00078             if (p1.duration != p2.duration) return p1.duration < p2.duration;
00079             return p1.label < p2.label;
00080         }
00081     };
00082     
00083     struct OrderComparator {
00084         bool operator()(const RegionRec &p1,
00085                         const RegionRec &p2) const {
00086             return p1.frame < p2.frame;
00087         }
00088     };
00089 };
00090 
00091 
00092 class RegionModel : public IntervalModel<RegionRec>
00093 {
00094     Q_OBJECT
00095     
00096 public:
00097     RegionModel(int sampleRate, int resolution,
00098                 bool notifyOnAdd = true) :
00099         IntervalModel<RegionRec>(sampleRate, resolution, notifyOnAdd),
00100         m_valueQuantization(0),
00101         m_haveDistinctValues(false)
00102     {
00103     }
00104 
00105     RegionModel(int sampleRate, int resolution,
00106                 float valueMinimum, float valueMaximum,
00107                 bool notifyOnAdd = true) :
00108         IntervalModel<RegionRec>(sampleRate, resolution,
00109                             valueMinimum, valueMaximum,
00110                             notifyOnAdd),
00111         m_valueQuantization(0),
00112         m_haveDistinctValues(false)
00113     {
00114     }
00115 
00116     virtual ~RegionModel()
00117     {
00118     }
00119 
00120     float getValueQuantization() const { return m_valueQuantization; }
00121     void setValueQuantization(float q) { m_valueQuantization = q; }
00122 
00123     bool haveDistinctValues() const { return m_haveDistinctValues; }
00124 
00125     QString getTypeName() const { return tr("Region"); }
00126 
00127     virtual void toXml(QTextStream &out,
00128                        QString indent = "",
00129                        QString extraAttributes = "") const
00130     {
00131         std::cerr << "RegionModel::toXml: extraAttributes = \"" 
00132                   << extraAttributes.toStdString() << std::endl;
00133 
00134         IntervalModel<RegionRec>::toXml
00135             (out,
00136              indent,
00137              QString("%1 subtype=\"region\" valueQuantization=\"%2\"")
00138              .arg(extraAttributes).arg(m_valueQuantization));
00139     }
00140 
00145     virtual int getColumnCount() const
00146     {
00147         return 5;
00148     }
00149 
00150     virtual QString getHeading(int column) const
00151     {
00152         switch (column) {
00153         case 0: return tr("Time");
00154         case 1: return tr("Frame");
00155         case 2: return tr("Value");
00156         case 3: return tr("Duration");
00157         case 4: return tr("Label");
00158         default: return tr("Unknown");
00159         }
00160     }
00161 
00162     virtual QVariant getData(int row, int column, int role) const
00163     {
00164         if (column < 4) {
00165             return IntervalModel<RegionRec>::getData(row, column, role);
00166         }
00167 
00168         PointListConstIterator i = getPointListIteratorForRow(row);
00169         if (i == m_points.end()) return QVariant();
00170 
00171         switch (column) {
00172         case 4: return i->label;
00173         default: return QVariant();
00174         }
00175     }
00176 
00177     virtual Command *getSetDataCommand(int row, int column, const QVariant &value, int role)
00178     {
00179         if (column < 4) {
00180             return IntervalModel<RegionRec>::getSetDataCommand
00181                 (row, column, value, role);
00182         }
00183 
00184         if (role != Qt::EditRole) return 0;
00185         PointListIterator i = getPointListIteratorForRow(row);
00186         if (i == m_points.end()) return 0;
00187         EditCommand *command = new EditCommand(this, tr("Edit Data"));
00188 
00189         Point point(*i);
00190         command->deletePoint(point);
00191 
00192         switch (column) {
00193         case 4: point.label = value.toString(); break;
00194         }
00195 
00196         command->addPoint(point);
00197         return command->finish();
00198     }
00199 
00200     virtual SortType getSortType(int column) const
00201     {
00202         if (column == 4) return SortAlphabetical;
00203         return SortNumeric;
00204     }
00205 
00206     virtual void addPoint(const Point &point)
00207     {
00208         if (point.value != 0.f) m_haveDistinctValues = true;
00209         IntervalModel<RegionRec>::addPoint(point);
00210     }
00211     
00212 protected:
00213     float m_valueQuantization;
00214     bool m_haveDistinctValues;
00215 };
00216 
00217 #endif