Mercurial > hg > svgui
comparison layer/TimeRulerLayer.cpp @ 271:1a49bd0d8375
* Change a number of keyboard shortcuts -- get rid of all the Alt+ shortcuts
and introduce a few more Ctrl+ ones instead, as well as a number of plain
single keypresses
* Add Playback menu
* Add time-ruler support for snap to feature, use it in ffwd/rewind
(rewind still needs fixing)
* restore layer hierarchy window prior to making it work correctly
author | Chris Cannam |
---|---|
date | Thu, 28 Jun 2007 14:50:58 +0000 |
parents | 28c8e8e3c537 |
children | 87e4c880b4c8 |
comparison
equal
deleted
inserted
replaced
270:61a704654497 | 271:1a49bd0d8375 |
---|---|
20 #include "view/View.h" | 20 #include "view/View.h" |
21 | 21 |
22 #include <QPainter> | 22 #include <QPainter> |
23 | 23 |
24 #include <iostream> | 24 #include <iostream> |
25 #include <cmath> | |
25 | 26 |
26 using std::cerr; | 27 using std::cerr; |
27 using std::endl; | 28 using std::endl; |
28 | 29 |
29 TimeRulerLayer::TimeRulerLayer() : | 30 TimeRulerLayer::TimeRulerLayer() : |
131 case 5: setBaseColour(QColor(255, 150, 50)); break; | 132 case 5: setBaseColour(QColor(255, 150, 50)); break; |
132 } | 133 } |
133 } | 134 } |
134 } | 135 } |
135 | 136 |
136 void | 137 bool |
137 TimeRulerLayer::paint(View *v, QPainter &paint, QRect rect) const | 138 TimeRulerLayer::snapToFeatureFrame(View *v, int &frame, |
138 { | 139 size_t &resolution, SnapType snap) const |
139 // std::cerr << "TimeRulerLayer::paint (" << rect.x() << "," << rect.y() | 140 { |
140 // << ") [" << rect.width() << "x" << rect.height() << "]" << std::endl; | 141 if (!m_model) { |
142 resolution = 1; | |
143 return false; | |
144 } | |
145 | |
146 bool q; | |
147 int tick = getMajorTickSpacing(v, q); | |
148 RealTime rtick = RealTime::fromMilliseconds(tick); | |
149 int rate = m_model->getSampleRate(); | |
141 | 150 |
142 if (!m_model || !m_model->isOK()) return; | 151 RealTime rt = RealTime::frame2RealTime(frame, rate); |
152 double ratio = rt / rtick; | |
153 | |
154 int rounded = lrint(ratio); | |
155 RealTime rdrt = rtick * rounded; | |
156 | |
157 int left = RealTime::realTime2Frame(rdrt, rate); | |
158 resolution = RealTime::realTime2Frame(rtick, rate); | |
159 int right = left + resolution; | |
160 | |
161 switch (snap) { | |
162 | |
163 case SnapLeft: | |
164 frame = left; | |
165 break; | |
166 | |
167 case SnapRight: | |
168 frame = right; | |
169 break; | |
170 | |
171 case SnapNearest: | |
172 { | |
173 if (abs(frame - left) > abs(right - frame)) { | |
174 frame = right; | |
175 } else { | |
176 frame = left; | |
177 } | |
178 break; | |
179 } | |
180 | |
181 case SnapNeighbouring: | |
182 { | |
183 int dl = -1, dr = -1; | |
184 int x = v->getXForFrame(frame); | |
185 | |
186 if (left > v->getStartFrame() && | |
187 left < v->getEndFrame()) { | |
188 dl = abs(v->getXForFrame(left) - x); | |
189 } | |
190 | |
191 if (right > v->getStartFrame() && | |
192 right < v->getEndFrame()) { | |
193 dr = abs(v->getXForFrame(right) - x); | |
194 } | |
195 | |
196 int fuzz = 2; | |
197 | |
198 if (dl >= 0 && dr >= 0) { | |
199 if (dl < dr) { | |
200 if (dl <= fuzz) { | |
201 frame = left; | |
202 } | |
203 } else { | |
204 if (dr < fuzz) { | |
205 frame = right; | |
206 } | |
207 } | |
208 } else if (dl >= 0) { | |
209 if (dl <= fuzz) { | |
210 frame = left; | |
211 } | |
212 } else if (dr >= 0) { | |
213 if (dr <= fuzz) { | |
214 frame = right; | |
215 } | |
216 } | |
217 } | |
218 } | |
219 | |
220 return true; | |
221 } | |
222 | |
223 int | |
224 TimeRulerLayer::getMajorTickSpacing(View *v, bool &quarterTicks) const | |
225 { | |
226 // return value is in milliseconds | |
227 | |
228 if (!m_model || !v) return 1000; | |
143 | 229 |
144 int sampleRate = m_model->getSampleRate(); | 230 int sampleRate = m_model->getSampleRate(); |
145 if (!sampleRate) return; | 231 if (!sampleRate) return 1000; |
146 | 232 |
147 long startFrame = v->getStartFrame(); | 233 long startFrame = v->getStartFrame(); |
148 long endFrame = v->getEndFrame(); | 234 long endFrame = v->getEndFrame(); |
149 | 235 |
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; | 236 int minPixelSpacing = 50; |
162 | 237 |
163 RealTime rtStart = RealTime::frame2RealTime(startFrame, sampleRate); | 238 RealTime rtStart = RealTime::frame2RealTime(startFrame, sampleRate); |
164 RealTime rtEnd = RealTime::frame2RealTime(endFrame, sampleRate); | 239 RealTime rtEnd = RealTime::frame2RealTime(endFrame, sampleRate); |
165 // cerr << "startFrame " << startFrame << ", endFrame " << v->getEndFrame() << ", rtStart " << rtStart << ", rtEnd " << rtEnd << endl; | 240 |
166 int count = v->width() / minPixelSpacing; | 241 int count = v->width() / minPixelSpacing; |
167 if (count < 1) count = 1; | 242 if (count < 1) count = 1; |
168 RealTime rtGap = (rtEnd - rtStart) / count; | 243 RealTime rtGap = (rtEnd - rtStart) / count; |
169 // cerr << "rtGap is " << rtGap << endl; | |
170 | 244 |
171 int incms; | 245 int incms; |
172 bool quarter = false; | 246 quarterTicks = false; |
173 | 247 |
174 if (rtGap.sec > 0) { | 248 if (rtGap.sec > 0) { |
175 incms = 1000; | 249 incms = 1000; |
176 int s = rtGap.sec; | 250 int s = rtGap.sec; |
177 if (s > 0) { incms *= 5; s /= 5; } | 251 if (s > 0) { incms *= 5; s /= 5; } |
178 if (s > 0) { incms *= 2; s /= 2; } | 252 if (s > 0) { incms *= 2; s /= 2; } |
179 if (s > 0) { incms *= 6; s /= 6; quarter = true; } | 253 if (s > 0) { incms *= 6; s /= 6; quarterTicks = true; } |
180 if (s > 0) { incms *= 5; s /= 5; quarter = false; } | 254 if (s > 0) { incms *= 5; s /= 5; quarterTicks = false; } |
181 if (s > 0) { incms *= 2; s /= 2; } | 255 if (s > 0) { incms *= 2; s /= 2; } |
182 if (s > 0) { incms *= 6; s /= 6; quarter = true; } | 256 if (s > 0) { incms *= 6; s /= 6; quarterTicks = true; } |
183 while (s > 0) { | 257 while (s > 0) { |
184 incms *= 10; | 258 incms *= 10; |
185 s /= 10; | 259 s /= 10; |
186 quarter = false; | 260 quarterTicks = false; |
187 } | 261 } |
188 } else { | 262 } else { |
189 incms = 1; | 263 incms = 1; |
190 int ms = rtGap.msec(); | 264 int ms = rtGap.msec(); |
191 if (ms > 0) { incms *= 10; ms /= 10; } | 265 if (ms > 0) { incms *= 10; ms /= 10; } |
192 if (ms > 0) { incms *= 10; ms /= 10; } | 266 if (ms > 0) { incms *= 10; ms /= 10; } |
193 if (ms > 0) { incms *= 5; ms /= 5; } | 267 if (ms > 0) { incms *= 5; ms /= 5; } |
194 if (ms > 0) { incms *= 2; ms /= 2; } | 268 if (ms > 0) { incms *= 2; ms /= 2; } |
195 } | 269 } |
196 // cerr << "incms is " << incms << endl; | 270 |
271 return incms; | |
272 } | |
273 | |
274 void | |
275 TimeRulerLayer::paint(View *v, QPainter &paint, QRect rect) const | |
276 { | |
277 // std::cerr << "TimeRulerLayer::paint (" << rect.x() << "," << rect.y() | |
278 // << ") [" << rect.width() << "x" << rect.height() << "]" << std::endl; | |
279 | |
280 if (!m_model || !m_model->isOK()) return; | |
281 | |
282 int sampleRate = m_model->getSampleRate(); | |
283 if (!sampleRate) return; | |
284 | |
285 long startFrame = v->getStartFrame(); | |
286 long endFrame = v->getEndFrame(); | |
287 | |
288 int zoomLevel = v->getZoomLevel(); | |
289 | |
290 long rectStart = startFrame + (rect.x() - 100) * zoomLevel; | |
291 long rectEnd = startFrame + (rect.x() + rect.width() + 100) * zoomLevel; | |
292 | |
293 // std::cerr << "TimeRulerLayer::paint: calling paint.save()" << std::endl; | |
294 paint.save(); | |
295 //!!! paint.setClipRect(v->rect()); | |
296 | |
297 int minPixelSpacing = 50; | |
298 | |
299 bool quarter = false; | |
300 int incms = getMajorTickSpacing(v, quarter); | |
197 | 301 |
198 RealTime rt = RealTime::frame2RealTime(rectStart, sampleRate); | 302 RealTime rt = RealTime::frame2RealTime(rectStart, sampleRate); |
199 long ms = rt.sec * 1000 + rt.msec(); | 303 long ms = rt.sec * 1000 + rt.msec(); |
200 ms = (ms / incms) * incms - incms; | 304 ms = (ms / incms) * incms - incms; |
201 | 305 |