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@1040
|
32 IntervalModel(sv_samplerate_t sampleRate, int resolution,
|
Chris@437
|
33 bool notifyOnAdd = true) :
|
Chris@437
|
34 SparseValueModel<PointType>(sampleRate, resolution, notifyOnAdd)
|
Chris@437
|
35 { }
|
Chris@437
|
36
|
Chris@1040
|
37 IntervalModel(sv_samplerate_t sampleRate, int 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@1055
|
51 virtual typename SparseValueModel<PointType>::PointList getPoints(sv_frame_t start, sv_frame_t 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@1038
|
58 virtual typename SparseValueModel<PointType>::PointList getPoints(sv_frame_t 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@740
|
98 if (role != Qt::EditRole) return 0;
|
Chris@438
|
99 typename I::PointList::const_iterator i
|
Chris@438
|
100 = I::getPointListIteratorForRow(row);
|
Chris@740
|
101 if (i == I::m_points.end()) return 0;
|
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@970
|
109 // column cannot be 0 or 1, those cases were handled above
|
Chris@1038
|
110 case 2: point.value = float(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@1038
|
128 IntervalModel<PointType>::getPoints(sv_frame_t start, sv_frame_t 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@1038
|
149 if (i->frame + 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@1038
|
162 IntervalModel<PointType>::getPoints(sv_frame_t 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@1038
|
171 sv_frame_t start = (frame / I::m_resolution) * I::m_resolution;
|
Chris@1038
|
172 sv_frame_t 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@1038
|
183 if (i->frame + 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
|