annotate data/model/IntervalModel.h @ 660:5db8181ea521

* getNativeRate needs to be virtual!
author Chris Cannam
date Mon, 18 Oct 2010 14:17:02 +0100
parents b1dc68507e46
children e22b6e89a7f7
rev   line source
Chris@437 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@437 2
Chris@437 3 /*
Chris@437 4 Sonic Visualiser
Chris@437 5 An audio file viewer and annotation editor.
Chris@437 6 Centre for Digital Music, Queen Mary, University of London.
Chris@437 7 This file copyright 2006-2008 Chris Cannam and QMUL.
Chris@437 8
Chris@437 9 This program is free software; you can redistribute it and/or
Chris@437 10 modify it under the terms of the GNU General Public License as
Chris@437 11 published by the Free Software Foundation; either version 2 of the
Chris@437 12 License, or (at your option) any later version. See the file
Chris@437 13 COPYING included with this distribution for more information.
Chris@437 14 */
Chris@437 15
Chris@437 16 #ifndef _INTERVAL_MODEL_H_
Chris@437 17 #define _INTERVAL_MODEL_H_
Chris@437 18
Chris@437 19 #include "SparseValueModel.h"
Chris@437 20 #include "base/RealTime.h"
Chris@437 21
Chris@437 22 /**
Chris@437 23 * Model containing sparse data (points with some properties) of which
Chris@437 24 * the properties include a duration and an arbitrary float value.
Chris@437 25 * The other properties depend on the point type.
Chris@437 26 */
Chris@437 27
Chris@437 28 template <typename PointType>
Chris@437 29 class IntervalModel : public SparseValueModel<PointType>
Chris@437 30 {
Chris@437 31 public:
Chris@437 32 IntervalModel(size_t sampleRate, size_t resolution,
Chris@437 33 bool notifyOnAdd = true) :
Chris@437 34 SparseValueModel<PointType>(sampleRate, resolution, notifyOnAdd)
Chris@437 35 { }
Chris@437 36
Chris@437 37 IntervalModel(size_t sampleRate, size_t resolution,
Chris@437 38 float valueMinimum, float valueMaximum,
Chris@437 39 bool notifyOnAdd = true) :
Chris@437 40 SparseValueModel<PointType>(sampleRate, resolution,
Chris@437 41 valueMinimum, valueMaximum,
Chris@437 42 notifyOnAdd)
Chris@437 43 { }
Chris@437 44
Chris@437 45 /**
Chris@437 46 * PointTypes have a duration, so this returns all points that span any
Chris@437 47 * of the given range (as well as the usual additional few before
Chris@437 48 * and after). Consequently this can be very slow (optimised data
Chris@437 49 * structures still to be done!).
Chris@437 50 */
Chris@437 51 virtual typename SparseValueModel<PointType>::PointList getPoints(long start, long end) const;
Chris@437 52
Chris@437 53 /**
Chris@437 54 * PointTypes have a duration, so this returns all points that span the
Chris@437 55 * given frame. Consequently this can be very slow (optimised
Chris@437 56 * data structures still to be done!).
Chris@437 57 */
Chris@437 58 virtual typename SparseValueModel<PointType>::PointList getPoints(long frame) const;
Chris@437 59
Chris@459 60 virtual const typename SparseModel<PointType>::PointList &getPoints() const {
Chris@459 61 return SparseModel<PointType>::getPoints();
Chris@459 62 }
Chris@459 63
Chris@437 64 /**
Chris@437 65 * TabularModel methods.
Chris@437 66 */
Chris@437 67
Chris@437 68 virtual QVariant getData(int row, int column, int role) const
Chris@437 69 {
Chris@437 70 if (column < 2) {
Chris@437 71 return SparseValueModel<PointType>::getData
Chris@437 72 (row, column, role);
Chris@437 73 }
Chris@437 74
Chris@437 75 typename SparseModel<PointType>::PointList::const_iterator i
Chris@437 76 = SparseModel<PointType>::getPointListIteratorForRow(row);
Chris@437 77 if (i == SparseModel<PointType>::m_points.end()) return QVariant();
Chris@437 78
Chris@437 79 switch (column) {
Chris@437 80 case 2:
Chris@437 81 if (role == Qt::EditRole || role == TabularModel::SortRole) return i->value;
Chris@437 82 else return QString("%1 %2").arg(i->value).arg
Chris@437 83 (IntervalModel<PointType>::getScaleUnits());
Chris@437 84 case 3: return int(i->duration); //!!! could be better presented
Chris@437 85 default: return QVariant();
Chris@437 86 }
Chris@437 87 }
Chris@437 88
Chris@437 89 virtual Command *getSetDataCommand(int row, int column, const QVariant &value, int role)
Chris@437 90 {
Chris@438 91 typedef IntervalModel<PointType> I;
Chris@438 92
Chris@437 93 if (column < 2) {
Chris@437 94 return SparseValueModel<PointType>::getSetDataCommand
Chris@437 95 (row, column, value, role);
Chris@437 96 }
Chris@437 97
Chris@437 98 if (role != Qt::EditRole) return false;
Chris@438 99 typename I::PointList::const_iterator i
Chris@438 100 = I::getPointListIteratorForRow(row);
Chris@438 101 if (i == I::m_points.end()) return false;
Chris@438 102 typename I::EditCommand *command = new typename I::EditCommand
Chris@438 103 (this, I::tr("Edit Data"));
Chris@437 104
Chris@437 105 PointType point(*i);
Chris@437 106 command->deletePoint(point);
Chris@437 107
Chris@437 108 switch (column) {
Chris@437 109 case 0: case 1: point.frame = value.toInt(); break;
Chris@437 110 case 2: point.value = value.toDouble(); break;
Chris@437 111 case 3: point.duration = value.toInt(); break;
Chris@437 112 }
Chris@437 113
Chris@437 114 command->addPoint(point);
Chris@437 115 return command->finish();
Chris@437 116 }
Chris@437 117
Chris@437 118 virtual bool isColumnTimeValue(int column) const
Chris@437 119 {
Chris@618 120 // NB duration is not a "time value" -- that's for columns
Chris@618 121 // whose sort ordering is exactly that of the frame time
Chris@618 122 return (column < 2);
Chris@437 123 }
Chris@437 124 };
Chris@437 125
Chris@437 126 template <typename PointType>
Chris@437 127 typename SparseValueModel<PointType>::PointList
Chris@437 128 IntervalModel<PointType>::getPoints(long start, long end) const
Chris@437 129 {
Chris@437 130 typedef IntervalModel<PointType> I;
Chris@437 131
Chris@437 132 if (start > end) return typename I::PointList();
Chris@437 133
Chris@437 134 QMutex &mutex(I::m_mutex);
Chris@437 135 QMutexLocker locker(&mutex);
Chris@437 136
Chris@437 137 PointType endPoint(end);
Chris@437 138
Chris@608 139 typename I::PointListConstIterator endItr = I::m_points.upper_bound(endPoint);
Chris@437 140
Chris@437 141 if (endItr != I::m_points.end()) ++endItr;
Chris@437 142 if (endItr != I::m_points.end()) ++endItr;
Chris@437 143
Chris@437 144 typename I::PointList rv;
Chris@437 145
Chris@608 146 for (typename I::PointListConstIterator i = endItr; i != I::m_points.begin(); ) {
Chris@437 147 --i;
Chris@437 148 if (i->frame < start) {
Chris@437 149 if (i->frame + long(i->duration) >= start) {
Chris@437 150 rv.insert(*i);
Chris@437 151 }
Chris@437 152 } else if (i->frame <= end) {
Chris@437 153 rv.insert(*i);
Chris@437 154 }
Chris@437 155 }
Chris@437 156
Chris@437 157 return rv;
Chris@437 158 }
Chris@437 159
Chris@437 160 template <typename PointType>
Chris@437 161 typename SparseValueModel<PointType>::PointList
Chris@437 162 IntervalModel<PointType>::getPoints(long frame) const
Chris@437 163 {
Chris@437 164 typedef IntervalModel<PointType> I;
Chris@437 165
Chris@437 166 QMutex &mutex(I::m_mutex);
Chris@437 167 QMutexLocker locker(&mutex);
Chris@437 168
Chris@437 169 if (I::m_resolution == 0) return typename I::PointList();
Chris@437 170
Chris@437 171 long start = (frame / I::m_resolution) * I::m_resolution;
Chris@437 172 long end = start + I::m_resolution;
Chris@437 173
Chris@437 174 PointType endPoint(end);
Chris@437 175
Chris@608 176 typename I::PointListConstIterator endItr = I::m_points.upper_bound(endPoint);
Chris@437 177
Chris@437 178 typename I::PointList rv;
Chris@437 179
Chris@608 180 for (typename I::PointListConstIterator i = endItr; i != I::m_points.begin(); ) {
Chris@437 181 --i;
Chris@437 182 if (i->frame < start) {
Chris@437 183 if (i->frame + long(i->duration) >= start) {
Chris@437 184 rv.insert(*i);
Chris@437 185 }
Chris@437 186 } else if (i->frame <= end) {
Chris@437 187 rv.insert(*i);
Chris@437 188 }
Chris@437 189 }
Chris@437 190
Chris@437 191 return rv;
Chris@437 192 }
Chris@437 193
Chris@437 194 #endif