Mercurial > hg > svgui
comparison layer/TimeInstantLayer.cpp @ 44:ad214997dddb
* Refactor Layer classes so as no longer to store a single View pointer;
instead they need to be able to draw themselves on any View on demand.
Layers with caches (e.g. spectrogram) will need to be further refactored
so as to maintain a per-View cache
* Begin refactoring MainWindow by pulling out the document stuff (set of
layers, models etc) into a Document class. Not yet in use.
This revision is fairly unstable.
author | Chris Cannam |
---|---|
date | Thu, 02 Mar 2006 16:58:49 +0000 |
parents | 78515b1e29eb |
children | 2152e19d7db9 |
comparison
equal
deleted
inserted
replaced
43:78515b1e29eb | 44:ad214997dddb |
---|---|
19 #include <QPainter> | 19 #include <QPainter> |
20 #include <QMouseEvent> | 20 #include <QMouseEvent> |
21 | 21 |
22 #include <iostream> | 22 #include <iostream> |
23 | 23 |
24 TimeInstantLayer::TimeInstantLayer(View *w) : | 24 TimeInstantLayer::TimeInstantLayer() : |
25 Layer(w), | 25 Layer(), |
26 m_model(0), | 26 m_model(0), |
27 m_editing(false), | 27 m_editing(false), |
28 m_editingPoint(0, tr("New Point")), | 28 m_editingPoint(0, tr("New Point")), |
29 m_editingCommand(0), | 29 m_editingCommand(0), |
30 m_colour(QColor(200, 50, 255)), | 30 m_colour(QColor(200, 50, 255)), |
31 m_plotStyle(PlotInstants) | 31 m_plotStyle(PlotInstants) |
32 { | 32 { |
33 m_view->addLayer(this); | 33 |
34 } | 34 } |
35 | 35 |
36 void | 36 void |
37 TimeInstantLayer::setModel(SparseOneDimensionalModel *model) | 37 TimeInstantLayer::setModel(SparseOneDimensionalModel *model) |
38 { | 38 { |
156 m_plotStyle = style; | 156 m_plotStyle = style; |
157 emit layerParametersChanged(); | 157 emit layerParametersChanged(); |
158 } | 158 } |
159 | 159 |
160 bool | 160 bool |
161 TimeInstantLayer::isLayerScrollable() const | 161 TimeInstantLayer::isLayerScrollable(const View *v) const |
162 { | 162 { |
163 QPoint discard; | 163 QPoint discard; |
164 return !m_view->shouldIlluminateLocalFeatures(this, discard); | 164 return !v->shouldIlluminateLocalFeatures(this, discard); |
165 } | 165 } |
166 | 166 |
167 SparseOneDimensionalModel::PointList | 167 SparseOneDimensionalModel::PointList |
168 TimeInstantLayer::getLocalPoints(int x) const | 168 TimeInstantLayer::getLocalPoints(View *v, int x) const |
169 { | 169 { |
170 // Return a set of points that all have the same frame number, the | 170 // Return a set of points that all have the same frame number, the |
171 // nearest to the given x coordinate, and that are within a | 171 // nearest to the given x coordinate, and that are within a |
172 // certain fuzz distance of that x coordinate. | 172 // certain fuzz distance of that x coordinate. |
173 | 173 |
174 if (!m_model) return SparseOneDimensionalModel::PointList(); | 174 if (!m_model) return SparseOneDimensionalModel::PointList(); |
175 | 175 |
176 long frame = getFrameForX(x); | 176 long frame = v->getFrameForX(x); |
177 | 177 |
178 SparseOneDimensionalModel::PointList onPoints = | 178 SparseOneDimensionalModel::PointList onPoints = |
179 m_model->getPoints(frame); | 179 m_model->getPoints(frame); |
180 | 180 |
181 if (!onPoints.empty()) { | 181 if (!onPoints.empty()) { |
189 | 189 |
190 SparseOneDimensionalModel::PointList usePoints = prevPoints; | 190 SparseOneDimensionalModel::PointList usePoints = prevPoints; |
191 | 191 |
192 if (prevPoints.empty()) { | 192 if (prevPoints.empty()) { |
193 usePoints = nextPoints; | 193 usePoints = nextPoints; |
194 } else if (prevPoints.begin()->frame < m_view->getStartFrame() && | 194 } else if (prevPoints.begin()->frame < v->getStartFrame() && |
195 !(nextPoints.begin()->frame > m_view->getEndFrame())) { | 195 !(nextPoints.begin()->frame > v->getEndFrame())) { |
196 usePoints = nextPoints; | 196 usePoints = nextPoints; |
197 } else if (nextPoints.begin()->frame - frame < | 197 } else if (nextPoints.begin()->frame - frame < |
198 frame - prevPoints.begin()->frame) { | 198 frame - prevPoints.begin()->frame) { |
199 usePoints = nextPoints; | 199 usePoints = nextPoints; |
200 } | 200 } |
201 | 201 |
202 if (!usePoints.empty()) { | 202 if (!usePoints.empty()) { |
203 int fuzz = 2; | 203 int fuzz = 2; |
204 int px = getXForFrame(usePoints.begin()->frame); | 204 int px = v->getXForFrame(usePoints.begin()->frame); |
205 if ((px > x && px - x > fuzz) || | 205 if ((px > x && px - x > fuzz) || |
206 (px < x && x - px > fuzz + 1)) { | 206 (px < x && x - px > fuzz + 1)) { |
207 usePoints.clear(); | 207 usePoints.clear(); |
208 } | 208 } |
209 } | 209 } |
210 | 210 |
211 return usePoints; | 211 return usePoints; |
212 } | 212 } |
213 | 213 |
214 QString | 214 QString |
215 TimeInstantLayer::getFeatureDescription(QPoint &pos) const | 215 TimeInstantLayer::getFeatureDescription(View *v, QPoint &pos) const |
216 { | 216 { |
217 int x = pos.x(); | 217 int x = pos.x(); |
218 | 218 |
219 if (!m_model || !m_model->getSampleRate()) return ""; | 219 if (!m_model || !m_model->getSampleRate()) return ""; |
220 | 220 |
221 SparseOneDimensionalModel::PointList points = getLocalPoints(x); | 221 SparseOneDimensionalModel::PointList points = getLocalPoints(v, x); |
222 | 222 |
223 if (points.empty()) { | 223 if (points.empty()) { |
224 if (!m_model->isReady()) { | 224 if (!m_model->isReady()) { |
225 return tr("In progress"); | 225 return tr("In progress"); |
226 } else { | 226 } else { |
241 text = QString(tr("Time:\t%1\nLabel:\t%2")) | 241 text = QString(tr("Time:\t%1\nLabel:\t%2")) |
242 .arg(rt.toText(true).c_str()) | 242 .arg(rt.toText(true).c_str()) |
243 .arg(points.begin()->label); | 243 .arg(points.begin()->label); |
244 } | 244 } |
245 | 245 |
246 pos = QPoint(getXForFrame(useFrame), pos.y()); | 246 pos = QPoint(v->getXForFrame(useFrame), pos.y()); |
247 return text; | 247 return text; |
248 } | 248 } |
249 | 249 |
250 bool | 250 bool |
251 TimeInstantLayer::snapToFeatureFrame(int &frame, | 251 TimeInstantLayer::snapToFeatureFrame(View *v, int &frame, |
252 size_t &resolution, | 252 size_t &resolution, |
253 SnapType snap) const | 253 SnapType snap) const |
254 { | 254 { |
255 if (!m_model) { | 255 if (!m_model) { |
256 return Layer::snapToFeatureFrame(frame, resolution, snap); | 256 return Layer::snapToFeatureFrame(v, frame, resolution, snap); |
257 } | 257 } |
258 | 258 |
259 resolution = m_model->getResolution(); | 259 resolution = m_model->getResolution(); |
260 SparseOneDimensionalModel::PointList points; | 260 SparseOneDimensionalModel::PointList points; |
261 | 261 |
262 if (snap == SnapNeighbouring) { | 262 if (snap == SnapNeighbouring) { |
263 | 263 |
264 points = getLocalPoints(getXForFrame(frame)); | 264 points = getLocalPoints(v, v->getXForFrame(frame)); |
265 if (points.empty()) return false; | 265 if (points.empty()) return false; |
266 frame = points.begin()->frame; | 266 frame = points.begin()->frame; |
267 return true; | 267 return true; |
268 } | 268 } |
269 | 269 |
318 frame = snapped; | 318 frame = snapped; |
319 return found; | 319 return found; |
320 } | 320 } |
321 | 321 |
322 void | 322 void |
323 TimeInstantLayer::paint(QPainter &paint, QRect rect) const | 323 TimeInstantLayer::paint(View *v, QPainter &paint, QRect rect) const |
324 { | 324 { |
325 if (!m_model || !m_model->isOK()) return; | 325 if (!m_model || !m_model->isOK()) return; |
326 | 326 |
327 // Profiler profiler("TimeInstantLayer::paint", true); | 327 // Profiler profiler("TimeInstantLayer::paint", true); |
328 | 328 |
329 int x0 = rect.left(), x1 = rect.right(); | 329 int x0 = rect.left(), x1 = rect.right(); |
330 | 330 |
331 long frame0 = getFrameForX(x0); | 331 long frame0 = v->getFrameForX(x0); |
332 long frame1 = getFrameForX(x1); | 332 long frame1 = v->getFrameForX(x1); |
333 | 333 |
334 SparseOneDimensionalModel::PointList points(m_model->getPoints | 334 SparseOneDimensionalModel::PointList points(m_model->getPoints |
335 (frame0, frame1)); | 335 (frame0, frame1)); |
336 | 336 |
337 bool odd = false; | 337 bool odd = false; |
366 // << m_model->getResolution() << " frames" << std::endl; | 366 // << m_model->getResolution() << " frames" << std::endl; |
367 | 367 |
368 QPoint localPos; | 368 QPoint localPos; |
369 long illuminateFrame = -1; | 369 long illuminateFrame = -1; |
370 | 370 |
371 if (m_view->shouldIlluminateLocalFeatures(this, localPos)) { | 371 if (v->shouldIlluminateLocalFeatures(this, localPos)) { |
372 SparseOneDimensionalModel::PointList localPoints = | 372 SparseOneDimensionalModel::PointList localPoints = |
373 getLocalPoints(localPos.x()); | 373 getLocalPoints(v, localPos.x()); |
374 if (!localPoints.empty()) illuminateFrame = localPoints.begin()->frame; | 374 if (!localPoints.empty()) illuminateFrame = localPoints.begin()->frame; |
375 } | 375 } |
376 | 376 |
377 int prevX = -1; | 377 int prevX = -1; |
378 | 378 |
381 | 381 |
382 const SparseOneDimensionalModel::Point &p(*i); | 382 const SparseOneDimensionalModel::Point &p(*i); |
383 SparseOneDimensionalModel::PointList::const_iterator j = i; | 383 SparseOneDimensionalModel::PointList::const_iterator j = i; |
384 ++j; | 384 ++j; |
385 | 385 |
386 int x = getXForFrame(p.frame); | 386 int x = v->getXForFrame(p.frame); |
387 if (x == prevX && p.frame != illuminateFrame) continue; | 387 if (x == prevX && p.frame != illuminateFrame) continue; |
388 | 388 |
389 int iw = getXForFrame(p.frame + m_model->getResolution()) - x; | 389 int iw = v->getXForFrame(p.frame + m_model->getResolution()) - x; |
390 if (iw < 2) { | 390 if (iw < 2) { |
391 if (iw < 1) { | 391 if (iw < 1) { |
392 iw = 2; | 392 iw = 2; |
393 if (j != points.end()) { | 393 if (j != points.end()) { |
394 int nx = getXForFrame(j->frame); | 394 int nx = v->getXForFrame(j->frame); |
395 if (nx < x + 3) iw = 1; | 395 if (nx < x + 3) iw = 1; |
396 } | 396 } |
397 } else { | 397 } else { |
398 iw = 2; | 398 iw = 2; |
399 } | 399 } |
405 paint.setPen(brushColour); | 405 paint.setPen(brushColour); |
406 } | 406 } |
407 | 407 |
408 if (m_plotStyle == PlotInstants) { | 408 if (m_plotStyle == PlotInstants) { |
409 if (iw > 1) { | 409 if (iw > 1) { |
410 paint.drawRect(x, 0, iw - 1, m_view->height() - 1); | 410 paint.drawRect(x, 0, iw - 1, v->height() - 1); |
411 } else { | 411 } else { |
412 paint.drawLine(x, 0, x, m_view->height() - 1); | 412 paint.drawLine(x, 0, x, v->height() - 1); |
413 } | 413 } |
414 } else { | 414 } else { |
415 | 415 |
416 if (odd) paint.setBrush(oddBrushColour); | 416 if (odd) paint.setBrush(oddBrushColour); |
417 else paint.setBrush(brushColour); | 417 else paint.setBrush(brushColour); |
418 | 418 |
419 int nx; | 419 int nx; |
420 | 420 |
421 if (j != points.end()) { | 421 if (j != points.end()) { |
422 const SparseOneDimensionalModel::Point &q(*j); | 422 const SparseOneDimensionalModel::Point &q(*j); |
423 nx = getXForFrame(q.frame); | 423 nx = v->getXForFrame(q.frame); |
424 } else { | 424 } else { |
425 nx = getXForFrame(m_model->getEndFrame()); | 425 nx = v->getXForFrame(m_model->getEndFrame()); |
426 } | 426 } |
427 | 427 |
428 if (nx >= x) { | 428 if (nx >= x) { |
429 | 429 |
430 if (illuminateFrame != p.frame && | 430 if (illuminateFrame != p.frame && |
431 (nx < x + 5 || x >= m_view->width() - 1)) { | 431 (nx < x + 5 || x >= v->width() - 1)) { |
432 paint.setPen(Qt::NoPen); | 432 paint.setPen(Qt::NoPen); |
433 } | 433 } |
434 | 434 |
435 paint.drawRect(x, -1, nx - x, m_view->height() + 1); | 435 paint.drawRect(x, -1, nx - x, v->height() + 1); |
436 } | 436 } |
437 | 437 |
438 odd = !odd; | 438 odd = !odd; |
439 } | 439 } |
440 | 440 |
446 | 446 |
447 int lw = paint.fontMetrics().width(p.label); | 447 int lw = paint.fontMetrics().width(p.label); |
448 bool good = true; | 448 bool good = true; |
449 | 449 |
450 if (j != points.end()) { | 450 if (j != points.end()) { |
451 int nx = getXForFrame(j->frame); | 451 int nx = v->getXForFrame(j->frame); |
452 if (nx >= x && nx - x - iw - 3 <= lw) good = false; | 452 if (nx >= x && nx - x - iw - 3 <= lw) good = false; |
453 } | 453 } |
454 | 454 |
455 if (good) { | 455 if (good) { |
456 paint.drawText(x + iw + 2, | 456 paint.drawText(x + iw + 2, |
457 m_view->height() - paint.fontMetrics().height(), | 457 v->height() - paint.fontMetrics().height(), |
458 p.label); | 458 p.label); |
459 } | 459 } |
460 } | 460 } |
461 | 461 |
462 prevX = x; | 462 prevX = x; |
463 } | 463 } |
464 } | 464 } |
465 | 465 |
466 void | 466 void |
467 TimeInstantLayer::drawStart(QMouseEvent *e) | 467 TimeInstantLayer::drawStart(View *v, QMouseEvent *e) |
468 { | 468 { |
469 std::cerr << "TimeInstantLayer::drawStart(" << e->x() << ")" << std::endl; | 469 std::cerr << "TimeInstantLayer::drawStart(" << e->x() << ")" << std::endl; |
470 | 470 |
471 if (!m_model) return; | 471 if (!m_model) return; |
472 | 472 |
473 long frame = getFrameForX(e->x()); | 473 long frame = v->getFrameForX(e->x()); |
474 if (frame < 0) frame = 0; | 474 if (frame < 0) frame = 0; |
475 frame = frame / m_model->getResolution() * m_model->getResolution(); | 475 frame = frame / m_model->getResolution() * m_model->getResolution(); |
476 | 476 |
477 m_editingPoint = SparseOneDimensionalModel::Point(frame, tr("New Point")); | 477 m_editingPoint = SparseOneDimensionalModel::Point(frame, tr("New Point")); |
478 | 478 |
483 | 483 |
484 m_editing = true; | 484 m_editing = true; |
485 } | 485 } |
486 | 486 |
487 void | 487 void |
488 TimeInstantLayer::drawDrag(QMouseEvent *e) | 488 TimeInstantLayer::drawDrag(View *v, QMouseEvent *e) |
489 { | 489 { |
490 std::cerr << "TimeInstantLayer::drawDrag(" << e->x() << ")" << std::endl; | 490 std::cerr << "TimeInstantLayer::drawDrag(" << e->x() << ")" << std::endl; |
491 | 491 |
492 if (!m_model || !m_editing) return; | 492 if (!m_model || !m_editing) return; |
493 | 493 |
494 long frame = getFrameForX(e->x()); | 494 long frame = v->getFrameForX(e->x()); |
495 if (frame < 0) frame = 0; | 495 if (frame < 0) frame = 0; |
496 frame = frame / m_model->getResolution() * m_model->getResolution(); | 496 frame = frame / m_model->getResolution() * m_model->getResolution(); |
497 m_editingCommand->deletePoint(m_editingPoint); | 497 m_editingCommand->deletePoint(m_editingPoint); |
498 m_editingPoint.frame = frame; | 498 m_editingPoint.frame = frame; |
499 m_editingCommand->addPoint(m_editingPoint); | 499 m_editingCommand->addPoint(m_editingPoint); |
500 } | 500 } |
501 | 501 |
502 void | 502 void |
503 TimeInstantLayer::drawEnd(QMouseEvent *e) | 503 TimeInstantLayer::drawEnd(View *v, QMouseEvent *e) |
504 { | 504 { |
505 std::cerr << "TimeInstantLayer::drawEnd(" << e->x() << ")" << std::endl; | 505 std::cerr << "TimeInstantLayer::drawEnd(" << e->x() << ")" << std::endl; |
506 if (!m_model || !m_editing) return; | 506 if (!m_model || !m_editing) return; |
507 QString newName = tr("Add Point at %1 s") | 507 QString newName = tr("Add Point at %1 s") |
508 .arg(RealTime::frame2RealTime(m_editingPoint.frame, | 508 .arg(RealTime::frame2RealTime(m_editingPoint.frame, |
513 m_editingCommand = 0; | 513 m_editingCommand = 0; |
514 m_editing = false; | 514 m_editing = false; |
515 } | 515 } |
516 | 516 |
517 void | 517 void |
518 TimeInstantLayer::editStart(QMouseEvent *e) | 518 TimeInstantLayer::editStart(View *v, QMouseEvent *e) |
519 { | 519 { |
520 std::cerr << "TimeInstantLayer::editStart(" << e->x() << ")" << std::endl; | 520 std::cerr << "TimeInstantLayer::editStart(" << e->x() << ")" << std::endl; |
521 | 521 |
522 if (!m_model) return; | 522 if (!m_model) return; |
523 | 523 |
524 SparseOneDimensionalModel::PointList points = getLocalPoints(e->x()); | 524 SparseOneDimensionalModel::PointList points = getLocalPoints(v, e->x()); |
525 if (points.empty()) return; | 525 if (points.empty()) return; |
526 | 526 |
527 m_editingPoint = *points.begin(); | 527 m_editingPoint = *points.begin(); |
528 | 528 |
529 if (m_editingCommand) { | 529 if (m_editingCommand) { |
533 | 533 |
534 m_editing = true; | 534 m_editing = true; |
535 } | 535 } |
536 | 536 |
537 void | 537 void |
538 TimeInstantLayer::editDrag(QMouseEvent *e) | 538 TimeInstantLayer::editDrag(View *v, QMouseEvent *e) |
539 { | 539 { |
540 std::cerr << "TimeInstantLayer::editDrag(" << e->x() << ")" << std::endl; | 540 std::cerr << "TimeInstantLayer::editDrag(" << e->x() << ")" << std::endl; |
541 | 541 |
542 if (!m_model || !m_editing) return; | 542 if (!m_model || !m_editing) return; |
543 | 543 |
544 long frame = getFrameForX(e->x()); | 544 long frame = v->getFrameForX(e->x()); |
545 if (frame < 0) frame = 0; | 545 if (frame < 0) frame = 0; |
546 frame = frame / m_model->getResolution() * m_model->getResolution(); | 546 frame = frame / m_model->getResolution() * m_model->getResolution(); |
547 | 547 |
548 if (!m_editingCommand) { | 548 if (!m_editingCommand) { |
549 m_editingCommand = new SparseOneDimensionalModel::EditCommand(m_model, | 549 m_editingCommand = new SparseOneDimensionalModel::EditCommand(m_model, |
554 m_editingPoint.frame = frame; | 554 m_editingPoint.frame = frame; |
555 m_editingCommand->addPoint(m_editingPoint); | 555 m_editingCommand->addPoint(m_editingPoint); |
556 } | 556 } |
557 | 557 |
558 void | 558 void |
559 TimeInstantLayer::editEnd(QMouseEvent *e) | 559 TimeInstantLayer::editEnd(View *v, QMouseEvent *e) |
560 { | 560 { |
561 std::cerr << "TimeInstantLayer::editEnd(" << e->x() << ")" << std::endl; | 561 std::cerr << "TimeInstantLayer::editEnd(" << e->x() << ")" << std::endl; |
562 if (!m_model || !m_editing) return; | 562 if (!m_model || !m_editing) return; |
563 if (m_editingCommand) { | 563 if (m_editingCommand) { |
564 QString newName = tr("Move Point to %1 s") | 564 QString newName = tr("Move Point to %1 s") |