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@437
|
60 /**
|
Chris@437
|
61 * TabularModel methods.
|
Chris@437
|
62 */
|
Chris@437
|
63
|
Chris@437
|
64 virtual QVariant getData(int row, int column, int role) const
|
Chris@437
|
65 {
|
Chris@437
|
66 if (column < 2) {
|
Chris@437
|
67 return SparseValueModel<PointType>::getData
|
Chris@437
|
68 (row, column, role);
|
Chris@437
|
69 }
|
Chris@437
|
70
|
Chris@437
|
71 typename SparseModel<PointType>::PointList::const_iterator i
|
Chris@437
|
72 = SparseModel<PointType>::getPointListIteratorForRow(row);
|
Chris@437
|
73 if (i == SparseModel<PointType>::m_points.end()) return QVariant();
|
Chris@437
|
74
|
Chris@437
|
75 switch (column) {
|
Chris@437
|
76 case 2:
|
Chris@437
|
77 if (role == Qt::EditRole || role == TabularModel::SortRole) return i->value;
|
Chris@437
|
78 else return QString("%1 %2").arg(i->value).arg
|
Chris@437
|
79 (IntervalModel<PointType>::getScaleUnits());
|
Chris@437
|
80 case 3: return int(i->duration); //!!! could be better presented
|
Chris@437
|
81 default: return QVariant();
|
Chris@437
|
82 }
|
Chris@437
|
83 }
|
Chris@437
|
84
|
Chris@437
|
85 virtual Command *getSetDataCommand(int row, int column, const QVariant &value, int role)
|
Chris@437
|
86 {
|
Chris@437
|
87 if (column < 2) {
|
Chris@437
|
88 return SparseValueModel<PointType>::getSetDataCommand
|
Chris@437
|
89 (row, column, value, role);
|
Chris@437
|
90 }
|
Chris@437
|
91
|
Chris@437
|
92 if (role != Qt::EditRole) return false;
|
Chris@437
|
93 // gah. This is such garbage. Thank you, C++! I love you too
|
Chris@437
|
94 typename SparseModel<PointType>::PointList::const_iterator i
|
Chris@437
|
95 = SparseModel<PointType>::getPointListIteratorForRow(row);
|
Chris@437
|
96 if (i == SparseModel<PointType>::m_points.end()) return false;
|
Chris@437
|
97 typename IntervalModel<PointType>::EditCommand *command
|
Chris@437
|
98 = new typename IntervalModel<PointType>::EditCommand
|
Chris@437
|
99 (this, IntervalModel<PointType>::tr("Edit Data"));
|
Chris@437
|
100
|
Chris@437
|
101 PointType point(*i);
|
Chris@437
|
102 command->deletePoint(point);
|
Chris@437
|
103
|
Chris@437
|
104 switch (column) {
|
Chris@437
|
105 case 0: case 1: point.frame = value.toInt(); break;
|
Chris@437
|
106 case 2: point.value = value.toDouble(); break;
|
Chris@437
|
107 case 3: point.duration = value.toInt(); break;
|
Chris@437
|
108 }
|
Chris@437
|
109
|
Chris@437
|
110 command->addPoint(point);
|
Chris@437
|
111 return command->finish();
|
Chris@437
|
112 }
|
Chris@437
|
113
|
Chris@437
|
114 virtual bool isColumnTimeValue(int column) const
|
Chris@437
|
115 {
|
Chris@437
|
116 return (column < 2 || column == 3);
|
Chris@437
|
117 }
|
Chris@437
|
118 };
|
Chris@437
|
119
|
Chris@437
|
120 template <typename PointType>
|
Chris@437
|
121 typename SparseValueModel<PointType>::PointList
|
Chris@437
|
122 IntervalModel<PointType>::getPoints(long start, long end) const
|
Chris@437
|
123 {
|
Chris@437
|
124 typedef IntervalModel<PointType> I;
|
Chris@437
|
125
|
Chris@437
|
126 if (start > end) return typename I::PointList();
|
Chris@437
|
127
|
Chris@437
|
128 QMutex &mutex(I::m_mutex);
|
Chris@437
|
129 QMutexLocker locker(&mutex);
|
Chris@437
|
130
|
Chris@437
|
131 PointType endPoint(end);
|
Chris@437
|
132
|
Chris@437
|
133 typename I::PointListIterator endItr = I::m_points.upper_bound(endPoint);
|
Chris@437
|
134
|
Chris@437
|
135 if (endItr != I::m_points.end()) ++endItr;
|
Chris@437
|
136 if (endItr != I::m_points.end()) ++endItr;
|
Chris@437
|
137
|
Chris@437
|
138 typename I::PointList rv;
|
Chris@437
|
139
|
Chris@437
|
140 for (typename I::PointListIterator i = endItr; i != I::m_points.begin(); ) {
|
Chris@437
|
141 --i;
|
Chris@437
|
142 if (i->frame < start) {
|
Chris@437
|
143 if (i->frame + long(i->duration) >= start) {
|
Chris@437
|
144 rv.insert(*i);
|
Chris@437
|
145 }
|
Chris@437
|
146 } else if (i->frame <= end) {
|
Chris@437
|
147 rv.insert(*i);
|
Chris@437
|
148 }
|
Chris@437
|
149 }
|
Chris@437
|
150
|
Chris@437
|
151 return rv;
|
Chris@437
|
152 }
|
Chris@437
|
153
|
Chris@437
|
154 template <typename PointType>
|
Chris@437
|
155 typename SparseValueModel<PointType>::PointList
|
Chris@437
|
156 IntervalModel<PointType>::getPoints(long frame) const
|
Chris@437
|
157 {
|
Chris@437
|
158 typedef IntervalModel<PointType> I;
|
Chris@437
|
159
|
Chris@437
|
160 QMutex &mutex(I::m_mutex);
|
Chris@437
|
161 QMutexLocker locker(&mutex);
|
Chris@437
|
162
|
Chris@437
|
163 if (I::m_resolution == 0) return typename I::PointList();
|
Chris@437
|
164
|
Chris@437
|
165 long start = (frame / I::m_resolution) * I::m_resolution;
|
Chris@437
|
166 long end = start + I::m_resolution;
|
Chris@437
|
167
|
Chris@437
|
168 PointType endPoint(end);
|
Chris@437
|
169
|
Chris@437
|
170 typename I::PointListIterator endItr = I::m_points.upper_bound(endPoint);
|
Chris@437
|
171
|
Chris@437
|
172 typename I::PointList rv;
|
Chris@437
|
173
|
Chris@437
|
174 for (typename I::PointListIterator i = endItr; i != I::m_points.begin(); ) {
|
Chris@437
|
175 --i;
|
Chris@437
|
176 if (i->frame < start) {
|
Chris@437
|
177 if (i->frame + long(i->duration) >= start) {
|
Chris@437
|
178 rv.insert(*i);
|
Chris@437
|
179 }
|
Chris@437
|
180 } else if (i->frame <= end) {
|
Chris@437
|
181 rv.insert(*i);
|
Chris@437
|
182 }
|
Chris@437
|
183 }
|
Chris@437
|
184
|
Chris@437
|
185 return rv;
|
Chris@437
|
186 }
|
Chris@437
|
187
|
Chris@437
|
188 #endif
|