comparison layer/TimeInstantLayer.cpp @ 0:2a4f26e85b4c

initial import
author Chris Cannam
date Tue, 10 Jan 2006 16:33:16 +0000
parents
children 77dad696d740
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 "TimeInstantLayer.h"
11
12 #include "base/Model.h"
13 #include "base/RealTime.h"
14 #include "base/View.h"
15 #include "base/Profiler.h"
16
17 #include "model/SparseOneDimensionalModel.h"
18
19 #include <QPainter>
20
21 #include <iostream>
22
23 TimeInstantLayer::TimeInstantLayer(View *w) :
24 Layer(w),
25 m_model(0),
26 m_colour(QColor(200, 50, 255))
27 {
28 m_view->addLayer(this);
29 }
30
31 void
32 TimeInstantLayer::setModel(SparseOneDimensionalModel *model)
33 {
34 if (m_model == model) return;
35 m_model = model;
36
37 connect(m_model, SIGNAL(modelChanged()), this, SIGNAL(modelChanged()));
38 connect(m_model, SIGNAL(modelChanged(size_t, size_t)),
39 this, SIGNAL(modelChanged(size_t, size_t)));
40
41 connect(m_model, SIGNAL(completionChanged()),
42 this, SIGNAL(modelCompletionChanged()));
43
44 std::cerr << "TimeInstantLayer::setModel(" << model << ")" << std::endl;
45
46 emit modelReplaced();
47 }
48
49 Layer::PropertyList
50 TimeInstantLayer::getProperties() const
51 {
52 PropertyList list;
53 list.push_back(tr("Colour"));
54 return list;
55 }
56
57 Layer::PropertyType
58 TimeInstantLayer::getPropertyType(const PropertyName &name) const
59 {
60 return ValueProperty;
61 }
62
63 int
64 TimeInstantLayer::getPropertyRangeAndValue(const PropertyName &name,
65 int *min, int *max) const
66 {
67 int deft = 0;
68
69 if (name == tr("Colour")) {
70
71 *min = 0;
72 *max = 5;
73
74 if (m_colour == Qt::black) deft = 0;
75 else if (m_colour == Qt::darkRed) deft = 1;
76 else if (m_colour == Qt::darkBlue) deft = 2;
77 else if (m_colour == Qt::darkGreen) deft = 3;
78 else if (m_colour == QColor(200, 50, 255)) deft = 4;
79 else if (m_colour == QColor(255, 150, 50)) deft = 5;
80
81 } else {
82
83 deft = Layer::getPropertyRangeAndValue(name, min, max);
84 }
85
86 return deft;
87 }
88
89 QString
90 TimeInstantLayer::getPropertyValueLabel(const PropertyName &name,
91 int value) const
92 {
93 if (name == tr("Colour")) {
94 switch (value) {
95 default:
96 case 0: return tr("Black");
97 case 1: return tr("Red");
98 case 2: return tr("Blue");
99 case 3: return tr("Green");
100 case 4: return tr("Purple");
101 case 5: return tr("Orange");
102 }
103 }
104 return tr("<unknown>");
105 }
106
107 void
108 TimeInstantLayer::setProperty(const PropertyName &name, int value)
109 {
110 if (name == tr("Colour")) {
111 switch (value) {
112 default:
113 case 0: setBaseColour(Qt::black); break;
114 case 1: setBaseColour(Qt::darkRed); break;
115 case 2: setBaseColour(Qt::darkBlue); break;
116 case 3: setBaseColour(Qt::darkGreen); break;
117 case 4: setBaseColour(QColor(200, 50, 255)); break;
118 case 5: setBaseColour(QColor(255, 150, 50)); break;
119 }
120 }
121 }
122
123 void
124 TimeInstantLayer::setBaseColour(QColor colour)
125 {
126 if (m_colour == colour) return;
127 m_colour = colour;
128 emit layerParametersChanged();
129 }
130
131 bool
132 TimeInstantLayer::isLayerScrollable() const
133 {
134 QPoint discard;
135 return !m_view->shouldIlluminateLocalFeatures(this, discard);
136 }
137
138 QRect
139 TimeInstantLayer::getFeatureDescriptionRect(QPainter &paint, QPoint pos) const
140 {
141 return QRect(0, 0,
142 std::max(100, paint.fontMetrics().width(tr("No local points"))),
143 50); //!!! cruddy
144 }
145
146 SparseOneDimensionalModel::PointList
147 TimeInstantLayer::getLocalPoints(int x) const
148 {
149 if (!m_model) return SparseOneDimensionalModel::PointList();
150
151 long startFrame = m_view->getStartFrame();
152 long endFrame = m_view->getEndFrame();
153 int zoomLevel = m_view->getZoomLevel();
154 long frame = startFrame + x * zoomLevel;
155
156 SparseOneDimensionalModel::PointList onPoints =
157 m_model->getPoints(frame);
158
159 if (!onPoints.empty()) {
160 return onPoints;
161 }
162
163 SparseOneDimensionalModel::PointList prevPoints =
164 m_model->getPreviousPoints(frame);
165 SparseOneDimensionalModel::PointList nextPoints =
166 m_model->getNextPoints(frame);
167
168 SparseOneDimensionalModel::PointList usePoints = prevPoints;
169
170 if (prevPoints.empty()) {
171 usePoints = nextPoints;
172 } else if (prevPoints.begin()->frame < startFrame &&
173 !(nextPoints.begin()->frame > endFrame)) {
174 usePoints = nextPoints;
175 } else if (nextPoints.begin()->frame - frame <
176 frame - prevPoints.begin()->frame) {
177 usePoints = nextPoints;
178 }
179
180 return usePoints;
181 }
182
183 void
184 TimeInstantLayer::paintLocalFeatureDescription(QPainter &paint, QRect rect,
185 QPoint pos) const
186 {
187 //!!! bleagh
188
189 int x = pos.x();
190
191 if (!m_model || !m_model->getSampleRate()) return;
192
193 SparseOneDimensionalModel::PointList points = getLocalPoints(x);
194
195 QFontMetrics metrics = paint.fontMetrics();
196 int xbase = rect.x() + 5;
197 int ybase = rect.y() + 5;
198
199 if (points.empty()) {
200 QString label = tr("No local points");
201 if (!m_model->isReady()) {
202 label = tr("In progress");
203 }
204 paint.drawText(xbase + 5, ybase + 5 + metrics.ascent(), label);
205 return;
206 }
207
208 long useFrame = points.begin()->frame;
209
210 RealTime rt = RealTime::frame2RealTime(useFrame, m_model->getSampleRate());
211 QString timeText = QString("%1").arg(rt.toText(true).c_str());
212
213 int timewidth = metrics.width(timeText);
214 int labelwidth = metrics.width(points.begin()->label);
215
216 int boxheight = metrics.height() * 2 + 3;
217 int boxwidth = std::max(timewidth, labelwidth);
218
219 paint.drawRect(xbase, ybase, boxwidth + 10,
220 boxheight + 10 - metrics.descent() + 1);
221
222 paint.drawText(xbase + 5, ybase + 5 + metrics.ascent(), timeText);
223 paint.drawText(xbase + 5, ybase + 7 + metrics.ascent() + metrics.height(),
224 points.begin()->label);
225 }
226
227 void
228 TimeInstantLayer::paint(QPainter &paint, QRect rect) const
229 {
230 if (!m_model || !m_model->isOK()) return;
231
232 // Profiler profiler("TimeInstantLayer::paint", true);
233
234 long startFrame = m_view->getStartFrame();
235 int zoomLevel = m_view->getZoomLevel();
236
237 int x0 = rect.left(), x1 = rect.right();
238 long frame0 = startFrame + x0 * zoomLevel;
239 long frame1 = startFrame + x1 * zoomLevel;
240
241 SparseOneDimensionalModel::PointList points(m_model->getPoints
242 (frame0, frame1));
243
244 paint.setPen(m_colour);
245
246 QColor brushColour(m_colour);
247 brushColour.setAlpha(100);
248 paint.setBrush(brushColour);
249
250 // std::cerr << "TimeInstantLayer::paint: resolution is "
251 // << m_model->getResolution() << " frames" << std::endl;
252
253 QPoint localPos;
254 long illuminateFrame = -1;
255
256 if (m_view->shouldIlluminateLocalFeatures(this, localPos)) {
257 SparseOneDimensionalModel::PointList localPoints =
258 getLocalPoints(localPos.x());
259 if (!localPoints.empty()) illuminateFrame = localPoints.begin()->frame;
260 }
261
262 for (SparseOneDimensionalModel::PointList::const_iterator i = points.begin();
263 i != points.end(); ++i) {
264
265 const SparseOneDimensionalModel::Point &p(*i);
266
267 int x = (p.frame - startFrame) / zoomLevel;
268 int w = m_model->getResolution() / zoomLevel;
269
270 if (w < 1) w = 1;
271 if (p.frame == illuminateFrame) {
272 paint.setPen(Qt::black); //!!!
273 } else {
274 paint.setPen(brushColour);
275 }
276 paint.drawRect(x, 0, w - 1, m_view->height() - 1);
277 paint.setPen(m_colour);
278
279 if (p.label != "") {
280
281 // only draw if there's enough room from here to the next point
282
283 int lw = paint.fontMetrics().width(p.label);
284 bool good = true;
285
286 SparseOneDimensionalModel::PointList::const_iterator j = i;
287 if (++j != points.end()) {
288 int nx = (j->frame - startFrame) / zoomLevel;
289 if (nx >= x && nx - x - w - 3 <= lw) good = false;
290 }
291
292 if (good) {
293 paint.drawText(x + w + 2,
294 m_view->height() - paint.fontMetrics().height(),
295 p.label);
296 }
297 }
298 }
299 }
300
301
302 #ifdef INCLUDE_MOCFILES
303 #include "TimeInstantLayer.moc.cpp"
304 #endif
305