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