comparison layer/TimeValueLayer.cpp @ 0:2a4f26e85b4c

initial import
author Chris Cannam
date Tue, 10 Jan 2006 16:33:16 +0000
parents
children 7af44e8578c8
comparison
equal deleted inserted replaced
-1:000000000000 0:2a4f26e85b4c
1 /* -*- c-basic-offset: 4 -*- vi:set ts=8 sts=4 sw=4: */
2
3 /*
4 A waveform viewer and audio annotation editor.
5 Chris Cannam, Queen Mary University of London, 2005
6
7 This is experimental software. Not for distribution.
8 */
9
10 #include "TimeValueLayer.h"
11
12 #include "base/Model.h"
13 #include "base/RealTime.h"
14 #include "base/Profiler.h"
15 #include "base/View.h"
16
17 #include "model/SparseTimeValueModel.h"
18
19 #include <QPainter>
20
21 #include <iostream>
22 #include <cmath>
23
24 TimeValueLayer::TimeValueLayer(View *w) :
25 Layer(w),
26 m_model(0),
27 m_colour(Qt::black),
28 m_plotStyle(PlotLines)
29 {
30 m_view->addLayer(this);
31 }
32
33 void
34 TimeValueLayer::setModel(SparseTimeValueModel *model)
35 {
36 if (m_model == model) return;
37 m_model = model;
38
39 connect(m_model, SIGNAL(modelChanged()), this, SIGNAL(modelChanged()));
40 connect(m_model, SIGNAL(modelChanged(size_t, size_t)),
41 this, SIGNAL(modelChanged(size_t, size_t)));
42
43 connect(m_model, SIGNAL(completionChanged()),
44 this, SIGNAL(modelCompletionChanged()));
45
46 std::cerr << "TimeValueLayer::setModel(" << model << ")" << std::endl;
47
48 emit modelReplaced();
49 }
50
51 Layer::PropertyList
52 TimeValueLayer::getProperties() const
53 {
54 PropertyList list;
55 list.push_back(tr("Colour"));
56 list.push_back(tr("Plot Type"));
57 return list;
58 }
59
60 Layer::PropertyType
61 TimeValueLayer::getPropertyType(const PropertyName &name) const
62 {
63 return ValueProperty;
64 }
65
66 int
67 TimeValueLayer::getPropertyRangeAndValue(const PropertyName &name,
68 int *min, int *max) const
69 {
70 //!!! factor this colour handling stuff out into a colour manager class
71
72 int deft = 0;
73
74 if (name == tr("Colour")) {
75
76 *min = 0;
77 *max = 5;
78
79 if (m_colour == Qt::black) deft = 0;
80 else if (m_colour == Qt::darkRed) deft = 1;
81 else if (m_colour == Qt::darkBlue) deft = 2;
82 else if (m_colour == Qt::darkGreen) deft = 3;
83 else if (m_colour == QColor(200, 50, 255)) deft = 4;
84 else if (m_colour == QColor(255, 150, 50)) deft = 5;
85
86 } else if (name == tr("Plot Type")) {
87
88 *min = 0;
89 *max = 2;
90
91 deft = int(m_plotStyle);
92
93 } else {
94
95 deft = Layer::getPropertyRangeAndValue(name, min, max);
96 }
97
98 return deft;
99 }
100
101 QString
102 TimeValueLayer::getPropertyValueLabel(const PropertyName &name,
103 int value) const
104 {
105 if (name == tr("Colour")) {
106 switch (value) {
107 default:
108 case 0: return tr("Black");
109 case 1: return tr("Red");
110 case 2: return tr("Blue");
111 case 3: return tr("Green");
112 case 4: return tr("Purple");
113 case 5: return tr("Orange");
114 }
115 } else if (name == tr("Plot Type")) {
116 switch (value) {
117 default:
118 case 0: return tr("Points");
119 case 1: return tr("Stems");
120 case 2: return tr("Lines");
121 }
122 }
123 return tr("<unknown>");
124 }
125
126 void
127 TimeValueLayer::setProperty(const PropertyName &name, int value)
128 {
129 if (name == tr("Colour")) {
130 switch (value) {
131 default:
132 case 0: setBaseColour(Qt::black); break;
133 case 1: setBaseColour(Qt::darkRed); break;
134 case 2: setBaseColour(Qt::darkBlue); break;
135 case 3: setBaseColour(Qt::darkGreen); break;
136 case 4: setBaseColour(QColor(200, 50, 255)); break;
137 case 5: setBaseColour(QColor(255, 150, 50)); break;
138 }
139 } else if (name == tr("Plot Type")) {
140 setPlotStyle(PlotStyle(value));
141 }
142 }
143
144 void
145 TimeValueLayer::setBaseColour(QColor colour)
146 {
147 if (m_colour == colour) return;
148 m_colour = colour;
149 emit layerParametersChanged();
150 }
151
152 void
153 TimeValueLayer::setPlotStyle(PlotStyle style)
154 {
155 if (m_plotStyle == style) return;
156 m_plotStyle = style;
157 emit layerParametersChanged();
158 }
159
160 bool
161 TimeValueLayer::isLayerScrollable() const
162 {
163 QPoint discard;
164 return !m_view->shouldIlluminateLocalFeatures(this, discard);
165 }
166
167 QRect
168 TimeValueLayer::getFeatureDescriptionRect(QPainter &paint, QPoint pos) const
169 {
170 return QRect(0, 0,
171 std::max(100, paint.fontMetrics().width(tr("No local points"))),
172 70); //!!!
173 }
174
175 //!!! too much in common with TimeInstantLayer
176
177 SparseTimeValueModel::PointList
178 TimeValueLayer::getLocalPoints(int x) const
179 {
180 if (!m_model) return SparseTimeValueModel::PointList();
181
182 long startFrame = m_view->getStartFrame();
183 long endFrame = m_view->getEndFrame();
184 int zoomLevel = m_view->getZoomLevel();
185 long frame = startFrame + x * zoomLevel;
186
187 SparseTimeValueModel::PointList onPoints =
188 m_model->getPoints(frame);
189
190 if (!onPoints.empty()) {
191 return onPoints;
192 }
193
194 SparseTimeValueModel::PointList prevPoints =
195 m_model->getPreviousPoints(frame);
196 SparseTimeValueModel::PointList nextPoints =
197 m_model->getNextPoints(frame);
198
199 SparseTimeValueModel::PointList usePoints = prevPoints;
200
201 if (prevPoints.empty()) {
202 usePoints = nextPoints;
203 } else if (prevPoints.begin()->frame < startFrame &&
204 !(nextPoints.begin()->frame > endFrame)) {
205 usePoints = nextPoints;
206 } else if (nextPoints.begin()->frame - frame <
207 frame - prevPoints.begin()->frame) {
208 usePoints = nextPoints;
209 }
210
211 return usePoints;
212 }
213
214 void
215 TimeValueLayer::paintLocalFeatureDescription(QPainter &paint, QRect rect,
216 QPoint pos) const
217 {
218 //!!! bleagh
219
220 int x = pos.x();
221
222 if (!m_model || !m_model->getSampleRate()) return;
223
224 SparseTimeValueModel::PointList points = getLocalPoints(x);
225
226 QFontMetrics metrics = paint.fontMetrics();
227 int xbase = rect.x() + 5;
228 int ybase = rect.y() + 5;
229
230 if (points.empty()) {
231 QString label = tr("No local points");
232 if (!m_model->isReady()) {
233 label = tr("In progress");
234 }
235 paint.drawText(xbase + 5, ybase + 5 + metrics.ascent(), label);
236 return;
237 }
238
239 long useFrame = points.begin()->frame;
240
241 RealTime rt = RealTime::frame2RealTime(useFrame, m_model->getSampleRate());
242 QString timeText = QString("%1").arg(rt.toText(true).c_str());
243 QString valueText = QString("%1").arg(points.begin()->value);
244
245 int timewidth = metrics.width(timeText);
246 int valuewidth = metrics.width(valueText);
247 int labelwidth = metrics.width(points.begin()->label);
248
249 int boxheight = metrics.height() * 3 + 4;
250 int boxwidth = std::max(std::max(timewidth, labelwidth), valuewidth);
251
252 paint.drawRect(xbase, ybase, boxwidth + 10,
253 boxheight + 10 - metrics.descent() + 1);
254
255 paint.drawText(xbase + 5, ybase + 5 + metrics.ascent(), timeText);
256 paint.drawText(xbase + 5, ybase + 7 + metrics.ascent() + metrics.height(),
257 valueText);
258 paint.drawText(xbase + 5, ybase + 9 + metrics.ascent() + 2*metrics.height(),
259 points.begin()->label);
260 }
261
262 void
263 TimeValueLayer::paint(QPainter &paint, QRect rect) const
264 {
265 if (!m_model || !m_model->isOK()) return;
266
267 int sampleRate = m_model->getSampleRate();
268 if (!sampleRate) return;
269
270 // Profiler profiler("TimeValueLayer::paint", true);
271
272 long startFrame = m_view->getStartFrame();
273 int zoomLevel = m_view->getZoomLevel();
274
275 int x0 = rect.left(), x1 = rect.right();
276 long frame0 = startFrame + x0 * zoomLevel;
277 long frame1 = startFrame + x1 * zoomLevel;
278
279 SparseTimeValueModel::PointList points(m_model->getPoints
280 (frame0, frame1));
281
282 paint.setPen(m_colour);
283
284 QColor brushColour(m_colour);
285 brushColour.setAlpha(80);
286 paint.setBrush(brushColour);
287
288 // std::cerr << "TimeValueLayer::paint: resolution is "
289 // << m_model->getResolution() << " frames" << std::endl;
290
291 float min = m_model->getValueMinimum();
292 float max = m_model->getValueMaximum();
293 if (max == min) max = min + 1.0;
294
295 int origin = int(nearbyint(m_view->height() -
296 (-min * m_view->height()) / (max - min)));
297
298 QPoint localPos;
299 long illuminateFrame = -1;
300
301 if (m_view->shouldIlluminateLocalFeatures(this, localPos)) {
302 SparseTimeValueModel::PointList localPoints =
303 getLocalPoints(localPos.x());
304 if (!localPoints.empty()) illuminateFrame = localPoints.begin()->frame;
305 }
306
307 for (SparseTimeValueModel::PointList::const_iterator i = points.begin();
308 i != points.end(); ++i) {
309
310 const SparseTimeValueModel::Point &p(*i);
311
312 int x = (p.frame - startFrame) / zoomLevel;
313 int y = int(nearbyint(m_view->height() -
314 ((p.value - min) * m_view->height()) /
315 (max - min)));
316 int w = m_model->getResolution() / zoomLevel;
317
318 if (w < 1) w = 1;
319
320 paint.setPen(m_colour);
321 paint.setBrush(brushColour);
322
323 if (m_plotStyle == PlotStems) {
324 paint.setPen(brushColour);
325 if (y < origin - 1) {
326 paint.drawRect(x + w/2, y + 1, 1, origin - y);
327 } else if (y > origin + 1) {
328 paint.drawRect(x + w/2, origin, 1, y - origin - 1);
329 }
330 paint.setPen(m_colour);
331 }
332
333 if (illuminateFrame == p.frame) {
334 //!!! aside from the problem of choosing a colour, it'd be
335 //better to save the highlighted rects and draw them at
336 //the end perhaps
337 paint.setPen(Qt::black);//!!!
338 paint.setBrush(Qt::black);//!!!
339 }
340
341 paint.drawRect(x, y - 1, w, 2);
342
343 // if (w > 1) {
344 // paint.setPen(brushColour);
345 // paint.drawRect(x, y - 1, w - 1, 2);
346 // paint.setPen(m_colour);
347 // }
348 // paint.drawLine(x, 0, x, m_view->height());
349
350 if (m_plotStyle == PlotLines) {
351
352 paint.setPen(brushColour);
353 SparseTimeValueModel::PointList::const_iterator j = i;
354 ++j;
355 if (j != points.end()) {
356 const SparseTimeValueModel::Point &q(*j);
357 int nx = (q.frame - startFrame) / zoomLevel;
358 int ny = int(nearbyint(m_view->height() -
359 ((q.value - min) * m_view->height()) /
360 (max - min)));
361 paint.drawLine(x + w, y, nx, ny);
362 }
363 }
364
365
366 /// if (p.label != "") {
367 /// paint.drawText(x + 5, y - paint.fontMetrics().height() + paint.fontMetrics().ascent(), p.label);
368 /// }
369 }
370
371
372 }
373
374
375 #ifdef INCLUDE_MOCFILES
376 #include "TimeValueLayer.moc.cpp"
377 #endif
378