comparison layer/TimeValueLayer.cpp @ 101:0f36cdf407a6 sv1-v0.9rc1

* Make vertical scale alignment modes work in note layer as well as time-value layer, and several significant fixes to it * Make it possible to draw notes properly on the note layer * Show units (and frequencies etc in note layer's case) in the time-value and note layer description boxes * Minor fix to item edit dialog layout * Some minor menu rearrangement * Comment out a lot of debug output * Add SV website and reference URLs to Help menu, and add code to (attempt to) open them in the user's preferred browser
author Chris Cannam
date Fri, 12 May 2006 14:40:43 +0000
parents 0db5e7492ce8
children 999ae0f7d10c
comparison
equal deleted inserted replaced
100:0db5e7492ce8 101:0f36cdf407a6
40 m_originalPoint(0, 0.0, tr("New Point")), 40 m_originalPoint(0, 0.0, tr("New Point")),
41 m_editingPoint(0, 0.0, tr("New Point")), 41 m_editingPoint(0, 0.0, tr("New Point")),
42 m_editingCommand(0), 42 m_editingCommand(0),
43 m_colour(Qt::darkGreen), 43 m_colour(Qt::darkGreen),
44 m_plotStyle(PlotConnectedPoints), 44 m_plotStyle(PlotConnectedPoints),
45 m_verticalScale(LinearScale) 45 m_verticalScale(AutoAlignScale)
46 { 46 {
47 47
48 } 48 }
49 49
50 void 50 void
58 this, SIGNAL(modelChanged(size_t, size_t))); 58 this, SIGNAL(modelChanged(size_t, size_t)));
59 59
60 connect(m_model, SIGNAL(completionChanged()), 60 connect(m_model, SIGNAL(completionChanged()),
61 this, SIGNAL(modelCompletionChanged())); 61 this, SIGNAL(modelCompletionChanged()));
62 62
63 std::cerr << "TimeValueLayer::setModel(" << model << ")" << std::endl; 63 // std::cerr << "TimeValueLayer::setModel(" << model << ")" << std::endl;
64 64
65 emit modelReplaced(); 65 emit modelReplaced();
66 } 66 }
67 67
68 Layer::PropertyList 68 Layer::PropertyList
167 case 5: return tr("Segmentation"); 167 case 5: return tr("Segmentation");
168 } 168 }
169 } else if (name == "Vertical Scale") { 169 } else if (name == "Vertical Scale") {
170 switch (value) { 170 switch (value) {
171 default: 171 default:
172 case 0: return tr("Linear Scale"); 172 case 0: return tr("Auto-Align");
173 case 1: return tr("Log Scale"); 173 case 1: return tr("Linear Scale");
174 case 2: return tr("+/-1 Scale"); 174 case 2: return tr("Log Scale");
175 case 3: return tr("Frequency Scale"); 175 case 3: return tr("+/-1 Scale");
176 } 176 }
177 } 177 }
178 return tr("<unknown>"); 178 return tr("<unknown>");
179 } 179 }
180 180
240 QPoint discard; 240 QPoint discard;
241 return !v->shouldIlluminateLocalFeatures(this, discard); 241 return !v->shouldIlluminateLocalFeatures(this, discard);
242 } 242 }
243 243
244 bool 244 bool
245 TimeValueLayer::getValueExtents(float &min, float &max, QString &unit) const 245 TimeValueLayer::getValueExtents(float &min, float &max,
246 { 246 bool &logarithmic, QString &unit) const
247 {
248 if (!m_model) return false;
247 min = m_model->getValueMinimum(); 249 min = m_model->getValueMinimum();
248 max = m_model->getValueMaximum(); 250 max = m_model->getValueMaximum();
251 logarithmic = (m_verticalScale == LogScale);
249 unit = m_model->getScaleUnits(); 252 unit = m_model->getScaleUnits();
253 return true;
254 }
255
256 bool
257 TimeValueLayer::getDisplayExtents(float &min, float &max) const
258 {
259 if (!m_model || m_verticalScale == AutoAlignScale) return false;
260
261 min = m_model->getValueMinimum();
262 max = m_model->getValueMaximum();
250 return true; 263 return true;
251 } 264 }
252 265
253 SparseTimeValueModel::PointList 266 SparseTimeValueModel::PointList
254 TimeValueLayer::getLocalPoints(View *v, int x) const 267 TimeValueLayer::getLocalPoints(View *v, int x) const
313 long useFrame = points.begin()->frame; 326 long useFrame = points.begin()->frame;
314 327
315 RealTime rt = RealTime::frame2RealTime(useFrame, m_model->getSampleRate()); 328 RealTime rt = RealTime::frame2RealTime(useFrame, m_model->getSampleRate());
316 329
317 QString text; 330 QString text;
331 QString unit = m_model->getScaleUnits();
332 if (unit != "") unit = " " + unit;
318 333
319 if (points.begin()->label == "") { 334 if (points.begin()->label == "") {
320 text = QString(tr("Time:\t%1\nValue:\t%2\nNo label")) 335 text = QString(tr("Time:\t%1\nValue:\t%2%3\nNo label"))
321 .arg(rt.toText(true).c_str())
322 .arg(points.begin()->value);
323 } else {
324 text = QString(tr("Time:\t%1\nValue:\t%2\nLabel:\t%3"))
325 .arg(rt.toText(true).c_str()) 336 .arg(rt.toText(true).c_str())
326 .arg(points.begin()->value) 337 .arg(points.begin()->value)
338 .arg(unit);
339 } else {
340 text = QString(tr("Time:\t%1\nValue:\t%2%3\nLabel:\t%4"))
341 .arg(rt.toText(true).c_str())
342 .arg(points.begin()->value)
343 .arg(unit)
327 .arg(points.begin()->label); 344 .arg(points.begin()->label);
328 } 345 }
329 346
330 pos = QPoint(v->getXForFrame(useFrame), 347 pos = QPoint(v->getXForFrame(useFrame),
331 getYForValue(v, points.begin()->value)); 348 getYForValue(v, points.begin()->value));
402 419
403 frame = snapped; 420 frame = snapped;
404 return found; 421 return found;
405 } 422 }
406 423
424 void
425 TimeValueLayer::getScaleExtents(View *v, float &min, float &max, bool &log) const
426 {
427 min = 0.0;
428 max = 0.0;
429 log = false;
430
431 if (m_verticalScale == AutoAlignScale) {
432
433 if (!v->getValueExtents(m_model->getScaleUnits(), min, max, log)) {
434 min = m_model->getValueMinimum();
435 max = m_model->getValueMaximum();
436 } else if (log) {
437 min = (min < 0.0) ? -log10(-min) : (min == 0.0) ? 0.0 : log10(min);
438 max = (max < 0.0) ? -log10(-max) : (max == 0.0) ? 0.0 : log10(max);
439 }
440
441 } else if (m_verticalScale == PlusMinusOneScale) {
442
443 min = -1.0;
444 max = 1.0;
445
446 } else {
447
448 min = m_model->getValueMinimum();
449 max = m_model->getValueMaximum();
450
451 if (m_verticalScale == LogScale) {
452 min = (min < 0.0) ? -log10(-min) : (min == 0.0) ? 0.0 : log10(min);
453 max = (max < 0.0) ? -log10(-max) : (max == 0.0) ? 0.0 : log10(max);
454 log = true;
455 }
456 }
457
458 if (max == min) max = min + 1.0;
459 }
460
407 int 461 int
408 TimeValueLayer::getYForValue(View *v, float val) const 462 TimeValueLayer::getYForValue(View *v, float val) const
409 { 463 {
410 float min = 0.0, max = 0.0; 464 float min = 0.0, max = 0.0;
465 bool logarithmic = false;
411 int h = v->height(); 466 int h = v->height();
412 467
413 if (!v->getValueExtents(m_model->getScaleUnits(), min, max)) { 468 getScaleExtents(v, min, max, logarithmic);
414 min = m_model->getValueMinimum(); 469
415 max = m_model->getValueMaximum(); 470 // std::cerr << "getYForValue(" << val << "): min " << min << ", max "
416 } 471 // << max << ", log " << logarithmic << std::endl;
417 472
418 if (max == min) max = min + 1.0; 473 if (logarithmic) {
419
420 /*!!!
421 float min = m_model->getValueMinimum();
422 float max = m_model->getValueMaximum();
423 if (max == min) max = min + 1.0;
424
425 int h = v->height();
426
427 if (m_verticalScale == FrequencyScale || m_verticalScale == LogScale) {
428
429 if (m_verticalScale == FrequencyScale) {
430 // If we have a spectrogram layer on the same view as us, align
431 // ourselves with it...
432 for (int i = 0; i < v->getLayerCount(); ++i) {
433 SpectrogramLayer *spectrogram = dynamic_cast<SpectrogramLayer *>
434 (v->getLayer(i));
435 if (spectrogram) {
436 return spectrogram->getYForFrequency(v, val);
437 }
438 }
439 }
440
441 min = (min < 0.0) ? -log10(-min) : (min == 0.0) ? 0.0 : log10(min);
442 max = (max < 0.0) ? -log10(-max) : (max == 0.0) ? 0.0 : log10(max);
443 val = (val < 0.0) ? -log10(-val) : (val == 0.0) ? 0.0 : log10(val); 474 val = (val < 0.0) ? -log10(-val) : (val == 0.0) ? 0.0 : log10(val);
444 475 }
445 } else if (m_verticalScale == PlusMinusOneScale) {
446 min = -1.0;
447 max = 1.0;
448 }
449 */
450 476
451 return int(h - ((val - min) * h) / (max - min)); 477 return int(h - ((val - min) * h) / (max - min));
452 } 478 }
453 479
454 float 480 float
455 TimeValueLayer::getValueForY(View *v, int y) const 481 TimeValueLayer::getValueForY(View *v, int y) const
456 { 482 {
457 //!!! 483 float min = 0.0, max = 0.0;
458 484 bool logarithmic = false;
459 float min = m_model->getValueMinimum();
460 float max = m_model->getValueMaximum();
461 if (max == min) max = min + 1.0;
462
463 int h = v->height(); 485 int h = v->height();
464 486
465 return min + (float(h - y) * float(max - min)) / h; 487 getScaleExtents(v, min, max, logarithmic);
488
489 float val = min + (float(h - y) * float(max - min)) / h;
490
491 if (logarithmic) {
492 val = pow(10, val);
493 }
494
495 return val;
466 } 496 }
467 497
468 QColor 498 QColor
469 TimeValueLayer::getColourForValue(float val) const 499 TimeValueLayer::getColourForValue(View *v, float val) const
470 { 500 {
471 float min = m_model->getValueMinimum(); 501 float min, max;
472 float max = m_model->getValueMaximum(); 502 bool log;
473 if (max == min) max = min + 1.0; 503 getScaleExtents(v, min, max, log);
474 504
475 if (m_verticalScale == FrequencyScale || m_verticalScale == LogScale) { 505 if (log) {
476 min = (min < 0.0) ? -log10(-min) : (min == 0.0) ? 0.0 : log10(min);
477 max = (max < 0.0) ? -log10(-max) : (max == 0.0) ? 0.0 : log10(max);
478 val = (val < 0.0) ? -log10(-val) : (val == 0.0) ? 0.0 : log10(val); 506 val = (val < 0.0) ? -log10(-val) : (val == 0.0) ? 0.0 : log10(val);
479 } else if (m_verticalScale == PlusMinusOneScale) {
480 min = -1.0;
481 max = 1.0;
482 } 507 }
483 508
484 int iv = ((val - min) / (max - min)) * 255.999; 509 int iv = ((val - min) / (max - min)) * 255.999;
485 510
486 QColor colour = QColor::fromHsv(256 - iv, iv / 2 + 128, iv); 511 QColor colour = QColor::fromHsv(256 - iv, iv / 2 + 128, iv);
579 604
580 if (w < 1) w = 1; 605 if (w < 1) w = 1;
581 paint.setPen(m_colour); 606 paint.setPen(m_colour);
582 607
583 if (m_plotStyle == PlotSegmentation) { 608 if (m_plotStyle == PlotSegmentation) {
584 paint.setBrush(getColourForValue(p.value)); 609 paint.setBrush(getColourForValue(v, p.value));
585 labelY = v->height(); 610 labelY = v->height();
586 } else if (m_plotStyle == PlotLines || 611 } else if (m_plotStyle == PlotLines ||
587 m_plotStyle == PlotCurve) { 612 m_plotStyle == PlotCurve) {
588 paint.setBrush(Qt::NoBrush); 613 paint.setBrush(Qt::NoBrush);
589 } else { 614 } else {
742 767
743 if (m_plotStyle == PlotSegmentation) { 768 if (m_plotStyle == PlotSegmentation) {
744 paint.save(); 769 paint.save();
745 for (int y = 0; y < boxh; ++y) { 770 for (int y = 0; y < boxh; ++y) {
746 float val = ((boxh - y) * (max - min)) / boxh + min; 771 float val = ((boxh - y) * (max - min)) / boxh + min;
747 paint.setPen(getColourForValue(val)); 772 paint.setPen(getColourForValue(v, val));
748 paint.drawLine(boxx + 1, y + boxy + 1, boxx + boxw, y + boxy + 1); 773 paint.drawLine(boxx + 1, y + boxy + 1, boxx + boxw, y + boxy + 1);
749 } 774 }
750 paint.restore(); 775 paint.restore();
751 } 776 }
752 777
787 } 812 }
788 813
789 void 814 void
790 TimeValueLayer::drawStart(View *v, QMouseEvent *e) 815 TimeValueLayer::drawStart(View *v, QMouseEvent *e)
791 { 816 {
792 std::cerr << "TimeValueLayer::drawStart(" << e->x() << "," << e->y() << ")" << std::endl; 817 // std::cerr << "TimeValueLayer::drawStart(" << e->x() << "," << e->y() << ")" << std::endl;
793 818
794 if (!m_model) return; 819 if (!m_model) return;
795 820
796 long frame = v->getFrameForX(e->x()); 821 long frame = v->getFrameForX(e->x());
797 long resolution = m_model->getResolution(); 822 long resolution = m_model->getResolution();
805 SparseTimeValueModel::PointList points = getLocalPoints(v, e->x()); 830 SparseTimeValueModel::PointList points = getLocalPoints(v, e->x());
806 if (!points.empty()) { 831 if (!points.empty()) {
807 for (SparseTimeValueModel::PointList::iterator i = points.begin(); 832 for (SparseTimeValueModel::PointList::iterator i = points.begin();
808 i != points.end(); ++i) { 833 i != points.end(); ++i) {
809 if (((i->frame / resolution) * resolution) != frame) { 834 if (((i->frame / resolution) * resolution) != frame) {
810 std::cerr << "ignoring out-of-range frame at " << i->frame << std::endl; 835 // std::cerr << "ignoring out-of-range frame at " << i->frame << std::endl;
811 continue; 836 continue;
812 } 837 }
813 m_editingPoint = *i; 838 m_editingPoint = *i;
814 havePoint = true; 839 havePoint = true;
815 } 840 }
833 } 858 }
834 859
835 void 860 void
836 TimeValueLayer::drawDrag(View *v, QMouseEvent *e) 861 TimeValueLayer::drawDrag(View *v, QMouseEvent *e)
837 { 862 {
838 std::cerr << "TimeValueLayer::drawDrag(" << e->x() << "," << e->y() << ")" << std::endl; 863 // std::cerr << "TimeValueLayer::drawDrag(" << e->x() << "," << e->y() << ")" << std::endl;
839 864
840 if (!m_model || !m_editing) return; 865 if (!m_model || !m_editing) return;
841 866
842 long frame = v->getFrameForX(e->x()); 867 long frame = v->getFrameForX(e->x());
843 long resolution = m_model->getResolution(); 868 long resolution = m_model->getResolution();
846 871
847 float value = getValueForY(v, e->y()); 872 float value = getValueForY(v, e->y());
848 873
849 SparseTimeValueModel::PointList points = getLocalPoints(v, e->x()); 874 SparseTimeValueModel::PointList points = getLocalPoints(v, e->x());
850 875
851 std::cerr << points.size() << " points" << std::endl; 876 // std::cerr << points.size() << " points" << std::endl;
852 877
853 bool havePoint = false; 878 bool havePoint = false;
854 879
855 if (!points.empty()) { 880 if (!points.empty()) {
856 for (SparseTimeValueModel::PointList::iterator i = points.begin(); 881 for (SparseTimeValueModel::PointList::iterator i = points.begin();
857 i != points.end(); ++i) { 882 i != points.end(); ++i) {
858 if (i->frame == m_editingPoint.frame && 883 if (i->frame == m_editingPoint.frame &&
859 i->value == m_editingPoint.value) { 884 i->value == m_editingPoint.value) {
860 std::cerr << "ignoring current editing point at " << i->frame << ", " << i->value << std::endl; 885 // std::cerr << "ignoring current editing point at " << i->frame << ", " << i->value << std::endl;
861 continue; 886 continue;
862 } 887 }
863 if (((i->frame / resolution) * resolution) != frame) { 888 if (((i->frame / resolution) * resolution) != frame) {
864 std::cerr << "ignoring out-of-range frame at " << i->frame << std::endl; 889 // std::cerr << "ignoring out-of-range frame at " << i->frame << std::endl;
865 continue; 890 continue;
866 } 891 }
867 std::cerr << "adjusting to new point at " << i->frame << ", " << i->value << std::endl; 892 // std::cerr << "adjusting to new point at " << i->frame << ", " << i->value << std::endl;
868 m_editingPoint = *i; 893 m_editingPoint = *i;
869 m_originalPoint = m_editingPoint; 894 m_originalPoint = m_editingPoint;
870 m_editingCommand->deletePoint(m_editingPoint); 895 m_editingCommand->deletePoint(m_editingPoint);
871 havePoint = true; 896 havePoint = true;
872 } 897 }
885 } 910 }
886 911
887 void 912 void
888 TimeValueLayer::drawEnd(View *v, QMouseEvent *e) 913 TimeValueLayer::drawEnd(View *v, QMouseEvent *e)
889 { 914 {
890 std::cerr << "TimeValueLayer::drawEnd(" << e->x() << "," << e->y() << ")" << std::endl; 915 // std::cerr << "TimeValueLayer::drawEnd(" << e->x() << "," << e->y() << ")" << std::endl;
891 if (!m_model || !m_editing) return; 916 if (!m_model || !m_editing) return;
892 m_editingCommand->finish(); 917 m_editingCommand->finish();
893 m_editingCommand = 0; 918 m_editingCommand = 0;
894 m_editing = false; 919 m_editing = false;
895 } 920 }
896 921
897 void 922 void
898 TimeValueLayer::editStart(View *v, QMouseEvent *e) 923 TimeValueLayer::editStart(View *v, QMouseEvent *e)
899 { 924 {
900 std::cerr << "TimeValueLayer::editStart(" << e->x() << "," << e->y() << ")" << std::endl; 925 // std::cerr << "TimeValueLayer::editStart(" << e->x() << "," << e->y() << ")" << std::endl;
901 926
902 if (!m_model) return; 927 if (!m_model) return;
903 928
904 SparseTimeValueModel::PointList points = getLocalPoints(v, e->x()); 929 SparseTimeValueModel::PointList points = getLocalPoints(v, e->x());
905 if (points.empty()) return; 930 if (points.empty()) return;
916 } 941 }
917 942
918 void 943 void
919 TimeValueLayer::editDrag(View *v, QMouseEvent *e) 944 TimeValueLayer::editDrag(View *v, QMouseEvent *e)
920 { 945 {
921 std::cerr << "TimeValueLayer::editDrag(" << e->x() << "," << e->y() << ")" << std::endl; 946 // std::cerr << "TimeValueLayer::editDrag(" << e->x() << "," << e->y() << ")" << std::endl;
922 947
923 if (!m_model || !m_editing) return; 948 if (!m_model || !m_editing) return;
924 949
925 long frame = v->getFrameForX(e->x()); 950 long frame = v->getFrameForX(e->x());
926 if (frame < 0) frame = 0; 951 if (frame < 0) frame = 0;
940 } 965 }
941 966
942 void 967 void
943 TimeValueLayer::editEnd(View *v, QMouseEvent *e) 968 TimeValueLayer::editEnd(View *v, QMouseEvent *e)
944 { 969 {
945 std::cerr << "TimeValueLayer::editEnd(" << e->x() << "," << e->y() << ")" << std::endl; 970 // std::cerr << "TimeValueLayer::editEnd(" << e->x() << "," << e->y() << ")" << std::endl;
946 if (!m_model || !m_editing) return; 971 if (!m_model || !m_editing) return;
947 972
948 if (m_editingCommand) { 973 if (m_editingCommand) {
949 974
950 QString newName = m_editingCommand->getName(); 975 QString newName = m_editingCommand->getName();