svcore  1.9
IntervalModel.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-2008 Chris Cannam and QMUL.
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 _INTERVAL_MODEL_H_
00017 #define _INTERVAL_MODEL_H_
00018 
00019 #include "SparseValueModel.h"
00020 #include "base/RealTime.h"
00021 
00028 template <typename PointType>
00029 class IntervalModel : public SparseValueModel<PointType>
00030 {
00031 public:
00032     IntervalModel(int sampleRate, int resolution,
00033                   bool notifyOnAdd = true) :
00034         SparseValueModel<PointType>(sampleRate, resolution, notifyOnAdd)
00035     { }
00036 
00037     IntervalModel(int sampleRate, int resolution,
00038                   float valueMinimum, float valueMaximum,
00039                   bool notifyOnAdd = true) :
00040         SparseValueModel<PointType>(sampleRate, resolution,
00041                                     valueMinimum, valueMaximum,
00042                                     notifyOnAdd)
00043     { }
00044 
00051     virtual typename SparseValueModel<PointType>::PointList getPoints(long start, long end) const;
00052 
00058     virtual typename SparseValueModel<PointType>::PointList getPoints(long frame) const;
00059 
00060     virtual const typename SparseModel<PointType>::PointList &getPoints() const {
00061         return SparseModel<PointType>::getPoints(); 
00062     }
00063 
00068     virtual QVariant getData(int row, int column, int role) const
00069     {
00070         if (column < 2) {
00071             return SparseValueModel<PointType>::getData
00072                 (row, column, role);
00073         }
00074 
00075         typename SparseModel<PointType>::PointList::const_iterator i
00076             = SparseModel<PointType>::getPointListIteratorForRow(row);
00077         if (i == SparseModel<PointType>::m_points.end()) return QVariant();
00078 
00079         switch (column) {
00080         case 2:
00081             if (role == Qt::EditRole || role == TabularModel::SortRole) return i->value;
00082             else return QString("%1 %2").arg(i->value).arg
00083                      (IntervalModel<PointType>::getScaleUnits());
00084         case 3: return int(i->duration); 
00085         default: return QVariant();
00086         }
00087     }
00088 
00089     virtual Command *getSetDataCommand(int row, int column, const QVariant &value, int role)
00090     {
00091         typedef IntervalModel<PointType> I;
00092 
00093         if (column < 2) {
00094             return SparseValueModel<PointType>::getSetDataCommand
00095                 (row, column, value, role);
00096         }
00097 
00098         if (role != Qt::EditRole) return 0;
00099         typename I::PointList::const_iterator i
00100             = I::getPointListIteratorForRow(row);
00101         if (i == I::m_points.end()) return 0;
00102         typename I::EditCommand *command = new typename I::EditCommand
00103             (this, I::tr("Edit Data"));
00104 
00105         PointType point(*i);
00106         command->deletePoint(point);
00107 
00108         switch (column) {
00109         // column cannot be 0 or 1, those cases were handled above
00110         case 2: point.value = value.toDouble(); break;
00111         case 3: point.duration = value.toInt(); break;
00112         }
00113 
00114         command->addPoint(point);
00115         return command->finish();
00116     }
00117 
00118     virtual bool isColumnTimeValue(int column) const
00119     {
00120         // NB duration is not a "time value" -- that's for columns
00121         // whose sort ordering is exactly that of the frame time
00122         return (column < 2);
00123     }
00124 };
00125 
00126 template <typename PointType>
00127 typename SparseValueModel<PointType>::PointList
00128 IntervalModel<PointType>::getPoints(long start, long end) const
00129 {
00130     typedef IntervalModel<PointType> I;
00131 
00132     if (start > end) return typename I::PointList();
00133 
00134     QMutex &mutex(I::m_mutex);
00135     QMutexLocker locker(&mutex);
00136 
00137     PointType endPoint(end);
00138     
00139     typename I::PointListConstIterator endItr = I::m_points.upper_bound(endPoint);
00140 
00141     if (endItr != I::m_points.end()) ++endItr;
00142     if (endItr != I::m_points.end()) ++endItr;
00143 
00144     typename I::PointList rv;
00145 
00146     for (typename I::PointListConstIterator i = endItr; i != I::m_points.begin(); ) {
00147         --i;
00148         if (i->frame < start) {
00149             if (i->frame + long(i->duration) >= start) {
00150                 rv.insert(*i);
00151             }
00152         } else if (i->frame <= end) {
00153             rv.insert(*i);
00154         }
00155     }
00156 
00157     return rv;
00158 }
00159 
00160 template <typename PointType>
00161 typename SparseValueModel<PointType>::PointList
00162 IntervalModel<PointType>::getPoints(long frame) const
00163 {
00164     typedef IntervalModel<PointType> I;
00165 
00166     QMutex &mutex(I::m_mutex);
00167     QMutexLocker locker(&mutex);
00168 
00169     if (I::m_resolution == 0) return typename I::PointList();
00170 
00171     long start = (frame / I::m_resolution) * I::m_resolution;
00172     long end = start + I::m_resolution;
00173 
00174     PointType endPoint(end);
00175     
00176     typename I::PointListConstIterator endItr = I::m_points.upper_bound(endPoint);
00177 
00178     typename I::PointList rv;
00179 
00180     for (typename I::PointListConstIterator i = endItr; i != I::m_points.begin(); ) {
00181         --i;
00182         if (i->frame < start) {
00183             if (i->frame + long(i->duration) >= start) {
00184                 rv.insert(*i);
00185             }
00186         } else if (i->frame <= end) {
00187             rv.insert(*i);
00188         }
00189     }
00190 
00191     return rv;
00192 }
00193 
00194 #endif