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