Mercurial > hg > easaier-soundaccess
comparison layer/TimeRulerLayer.cpp @ 0:fc9323a41f5a
start base : Sonic Visualiser sv1-1.0rc1
author | lbajardsilogic |
---|---|
date | Fri, 11 May 2007 09:08:14 +0000 |
parents | |
children | d8e6709e9075 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:fc9323a41f5a |
---|---|
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 Chris Cannam. | |
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 #include "TimeRulerLayer.h" | |
17 | |
18 #include "data/model/Model.h" | |
19 #include "base/RealTime.h" | |
20 #include "view/View.h" | |
21 | |
22 #include <QPainter> | |
23 | |
24 #include <iostream> | |
25 | |
26 using std::cerr; | |
27 using std::endl; | |
28 | |
29 TimeRulerLayer::TimeRulerLayer() : | |
30 Layer(), | |
31 m_model(0), | |
32 m_colour(Qt::black), | |
33 m_labelHeight(LabelTop) | |
34 { | |
35 | |
36 } | |
37 | |
38 void | |
39 TimeRulerLayer::setModel(Model *model) | |
40 { | |
41 if (m_model == model) return; | |
42 m_model = model; | |
43 emit modelReplaced(); | |
44 } | |
45 | |
46 void | |
47 TimeRulerLayer::setBaseColour(QColor colour) | |
48 { | |
49 if (m_colour == colour) return; | |
50 m_colour = colour; | |
51 emit layerParametersChanged(); | |
52 } | |
53 | |
54 Layer::PropertyList | |
55 TimeRulerLayer::getProperties() const | |
56 { | |
57 PropertyList list; | |
58 list.push_back("Colour"); | |
59 return list; | |
60 } | |
61 | |
62 QString | |
63 TimeRulerLayer::getPropertyLabel(const PropertyName &name) const | |
64 { | |
65 if (name == "Colour") return tr("Colour"); | |
66 return ""; | |
67 } | |
68 | |
69 Layer::PropertyType | |
70 TimeRulerLayer::getPropertyType(const PropertyName &) const | |
71 { | |
72 return ValueProperty; | |
73 } | |
74 | |
75 int | |
76 TimeRulerLayer::getPropertyRangeAndValue(const PropertyName &name, | |
77 int *min, int *max, int *deflt) const | |
78 { | |
79 int val = 0; | |
80 | |
81 if (name == "Colour") { | |
82 | |
83 if (min) *min = 0; | |
84 if (max) *max = 5; | |
85 if (deflt) *deflt = 0; | |
86 | |
87 if (m_colour == Qt::black) val = 0; | |
88 else if (m_colour == Qt::darkRed) val = 1; | |
89 else if (m_colour == Qt::darkBlue) val = 2; | |
90 else if (m_colour == Qt::darkGreen) val = 3; | |
91 else if (m_colour == QColor(200, 50, 255)) val = 4; | |
92 else if (m_colour == QColor(255, 150, 50)) val = 5; | |
93 | |
94 } else { | |
95 | |
96 val = Layer::getPropertyRangeAndValue(name, min, max, deflt); | |
97 } | |
98 | |
99 return val; | |
100 } | |
101 | |
102 QString | |
103 TimeRulerLayer::getPropertyValueLabel(const PropertyName &name, | |
104 int value) const | |
105 { | |
106 if (name == "Colour") { | |
107 switch (value) { | |
108 default: | |
109 case 0: return tr("Black"); | |
110 case 1: return tr("Red"); | |
111 case 2: return tr("Blue"); | |
112 case 3: return tr("Green"); | |
113 case 4: return tr("Purple"); | |
114 case 5: return tr("Orange"); | |
115 } | |
116 } | |
117 return tr("<unknown>"); | |
118 } | |
119 | |
120 void | |
121 TimeRulerLayer::setProperty(const PropertyName &name, int value) | |
122 { | |
123 if (name == "Colour") { | |
124 switch (value) { | |
125 default: | |
126 case 0: setBaseColour(Qt::black); break; | |
127 case 1: setBaseColour(Qt::darkRed); break; | |
128 case 2: setBaseColour(Qt::darkBlue); break; | |
129 case 3: setBaseColour(Qt::darkGreen); break; | |
130 case 4: setBaseColour(QColor(200, 50, 255)); break; | |
131 case 5: setBaseColour(QColor(255, 150, 50)); break; | |
132 } | |
133 } | |
134 } | |
135 | |
136 void | |
137 TimeRulerLayer::paint(View *v, QPainter &paint, QRect rect) const | |
138 { | |
139 // std::cerr << "TimeRulerLayer::paint (" << rect.x() << "," << rect.y() | |
140 // << ") [" << rect.width() << "x" << rect.height() << "]" << std::endl; | |
141 | |
142 if (!m_model || !m_model->isOK()) return; | |
143 | |
144 int sampleRate = m_model->getSampleRate(); | |
145 if (!sampleRate) return; | |
146 | |
147 long startFrame = v->getStartFrame(); | |
148 long endFrame = v->getEndFrame(); | |
149 | |
150 int zoomLevel = v->getZoomLevel(); | |
151 | |
152 long rectStart = startFrame + (rect.x() - 100) * zoomLevel; | |
153 long rectEnd = startFrame + (rect.x() + rect.width() + 100) * zoomLevel; | |
154 // if (rectStart < startFrame) rectStart = startFrame; | |
155 // if (rectEnd > endFrame) rectEnd = endFrame; | |
156 | |
157 // std::cerr << "TimeRulerLayer::paint: calling paint.save()" << std::endl; | |
158 paint.save(); | |
159 //!!! paint.setClipRect(v->rect()); | |
160 | |
161 int minPixelSpacing = 50; | |
162 | |
163 RealTime rtStart = RealTime::frame2RealTime(startFrame, sampleRate); | |
164 RealTime rtEnd = RealTime::frame2RealTime(endFrame, sampleRate); | |
165 // cerr << "startFrame " << startFrame << ", endFrame " << v->getEndFrame() << ", rtStart " << rtStart << ", rtEnd " << rtEnd << endl; | |
166 int count = v->width() / minPixelSpacing; | |
167 if (count < 1) count = 1; | |
168 RealTime rtGap = (rtEnd - rtStart) / count; | |
169 // cerr << "rtGap is " << rtGap << endl; | |
170 | |
171 int incms; | |
172 bool quarter = false; | |
173 | |
174 if (rtGap.sec > 0) { | |
175 incms = 1000; | |
176 int s = rtGap.sec; | |
177 if (s > 0) { incms *= 5; s /= 5; } | |
178 if (s > 0) { incms *= 2; s /= 2; } | |
179 if (s > 0) { incms *= 6; s /= 6; quarter = true; } | |
180 if (s > 0) { incms *= 5; s /= 5; quarter = false; } | |
181 if (s > 0) { incms *= 2; s /= 2; } | |
182 if (s > 0) { incms *= 6; s /= 6; quarter = true; } | |
183 while (s > 0) { | |
184 incms *= 10; | |
185 s /= 10; | |
186 quarter = false; | |
187 } | |
188 } else { | |
189 incms = 1; | |
190 int ms = rtGap.msec(); | |
191 if (ms > 0) { incms *= 10; ms /= 10; } | |
192 if (ms > 0) { incms *= 10; ms /= 10; } | |
193 if (ms > 0) { incms *= 5; ms /= 5; } | |
194 if (ms > 0) { incms *= 2; ms /= 2; } | |
195 } | |
196 // cerr << "incms is " << incms << endl; | |
197 | |
198 RealTime rt = RealTime::frame2RealTime(rectStart, sampleRate); | |
199 long ms = rt.sec * 1000 + rt.msec(); | |
200 ms = (ms / incms) * incms - incms; | |
201 | |
202 RealTime incRt = RealTime::fromMilliseconds(incms); | |
203 long incFrame = RealTime::realTime2Frame(incRt, sampleRate); | |
204 int incX = incFrame / zoomLevel; | |
205 int ticks = 10; | |
206 if (incX < minPixelSpacing * 2) { | |
207 ticks = quarter ? 4 : 5; | |
208 } | |
209 | |
210 QRect oldClipRect = rect; | |
211 QRect newClipRect(oldClipRect.x() - 25, oldClipRect.y(), | |
212 oldClipRect.width() + 50, oldClipRect.height()); | |
213 paint.setClipRect(newClipRect); | |
214 paint.setClipRect(rect); | |
215 | |
216 QColor greyColour(m_colour); | |
217 if (m_colour == Qt::black) { | |
218 greyColour = QColor(200,200,200); | |
219 } else { | |
220 greyColour = m_colour.light(150); | |
221 } | |
222 | |
223 while (1) { | |
224 | |
225 rt = RealTime::fromMilliseconds(ms); | |
226 ms += incms; | |
227 | |
228 long frame = RealTime::realTime2Frame(rt, sampleRate); | |
229 if (frame >= rectEnd) break; | |
230 | |
231 int x = (frame - startFrame) / zoomLevel; | |
232 if (x < rect.x() || x >= rect.x() + rect.width()) continue; | |
233 | |
234 paint.setPen(greyColour); | |
235 paint.drawLine(x, 0, x, v->height()); | |
236 | |
237 paint.setPen(m_colour); | |
238 paint.drawLine(x, 0, x, 5); | |
239 paint.drawLine(x, v->height() - 6, x, v->height() - 1); | |
240 | |
241 QString text(QString::fromStdString(rt.toText())); | |
242 | |
243 int y; | |
244 QFontMetrics metrics = paint.fontMetrics(); | |
245 switch (m_labelHeight) { | |
246 default: | |
247 case LabelTop: | |
248 y = 6 + metrics.ascent(); | |
249 break; | |
250 case LabelMiddle: | |
251 y = v->height() / 2 - metrics.height() / 2 + metrics.ascent(); | |
252 break; | |
253 case LabelBottom: | |
254 y = v->height() - metrics.height() + metrics.ascent() - 6; | |
255 } | |
256 | |
257 int tw = metrics.width(text); | |
258 | |
259 if (v->getViewManager() && v->getViewManager()->getOverlayMode() != | |
260 ViewManager::NoOverlays) { | |
261 | |
262 if (v->getLayer(0) == this) { | |
263 // backmost layer, don't worry about outlining the text | |
264 paint.drawText(x+2 - tw/2, y, text); | |
265 } else { | |
266 v->drawVisibleText(paint, x+2 - tw/2, y, text, View::OutlinedText); | |
267 } | |
268 } | |
269 | |
270 paint.setPen(greyColour); | |
271 | |
272 for (int i = 1; i < ticks; ++i) { | |
273 rt = rt + (incRt / ticks); | |
274 frame = RealTime::realTime2Frame(rt, sampleRate); | |
275 x = (frame - startFrame) / zoomLevel; | |
276 int sz = 5; | |
277 if (ticks == 10) { | |
278 if ((i % 2) == 1) { | |
279 if (i == 5) { | |
280 paint.drawLine(x, 0, x, v->height()); | |
281 } else sz = 3; | |
282 } else { | |
283 sz = 7; | |
284 } | |
285 } | |
286 paint.drawLine(x, 0, x, sz); | |
287 paint.drawLine(x, v->height() - sz - 1, x, v->height() - 1); | |
288 } | |
289 } | |
290 | |
291 paint.restore(); | |
292 } | |
293 | |
294 QString | |
295 TimeRulerLayer::toXmlString(QString indent, QString extraAttributes) const | |
296 { | |
297 return Layer::toXmlString(indent, extraAttributes + | |
298 QString(" colour=\"%1\"").arg(encodeColour(m_colour))); | |
299 } | |
300 | |
301 void | |
302 TimeRulerLayer::setProperties(const QXmlAttributes &attributes) | |
303 { | |
304 QString colourSpec = attributes.value("colour"); | |
305 if (colourSpec != "") { | |
306 QColor colour(colourSpec); | |
307 if (colour.isValid()) { | |
308 setBaseColour(QColor(colourSpec)); | |
309 } | |
310 } | |
311 } | |
312 |