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")