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 |
