Mercurial > hg > svgui
comparison layer/TimeFrequencyBoxLayer.cpp @ 1514:e453053a44dc time-frequency-boxes
Fixes to drag and paint in time-freq box layer
author | Chris Cannam |
---|---|
date | Fri, 20 Sep 2019 11:25:47 +0100 |
parents | a473b73fb045 |
children | 0fa49a6ce64f |
comparison
equal
deleted
inserted
replaced
1513:0586e6492785 | 1514:e453053a44dc |
---|---|
522 wholeFrame1 - wholeFrame0)); | 522 wholeFrame1 - wholeFrame0)); |
523 if (points.empty()) return; | 523 if (points.empty()) return; |
524 | 524 |
525 paint.setPen(getBaseQColor()); | 525 paint.setPen(getBaseQColor()); |
526 | 526 |
527 QColor brushColour(getBaseQColor()); | |
528 brushColour.setAlpha(80); | |
529 | |
530 // SVDEBUG << "TimeFrequencyBoxLayer::paint: resolution is " | 527 // SVDEBUG << "TimeFrequencyBoxLayer::paint: resolution is " |
531 // << model->getResolution() << " frames" << endl; | 528 // << model->getResolution() << " frames" << endl; |
532 | 529 |
533 double min = model->getFrequencyMinimum(); | 530 double min = model->getFrequencyMinimum(); |
534 double max = model->getFrequencyMaximum(); | 531 double max = model->getFrequencyMaximum(); |
544 } | 541 } |
545 | 542 |
546 paint.save(); | 543 paint.save(); |
547 paint.setRenderHint(QPainter::Antialiasing, false); | 544 paint.setRenderHint(QPainter::Antialiasing, false); |
548 | 545 |
546 QFontMetrics fm = paint.fontMetrics(); | |
547 | |
549 for (EventVector::const_iterator i = points.begin(); | 548 for (EventVector::const_iterator i = points.begin(); |
550 i != points.end(); ++i) { | 549 i != points.end(); ++i) { |
551 | 550 |
552 const Event &p(*i); | 551 const Event &p(*i); |
553 | 552 |
554 int x = v->getXForFrame(p.getFrame()); | 553 int x = v->getXForFrame(p.getFrame()); |
555 int w = v->getXForFrame(p.getFrame() + p.getDuration()) - x; | 554 int w = v->getXForFrame(p.getFrame() + p.getDuration()) - x; |
556 int y = getYForValue(v, p.getValue()); | 555 int y = getYForValue(v, p.getValue()); |
557 int h = getYForValue(v, p.getValue() + fabsf(p.getLevel())); | 556 int h = getYForValue(v, p.getValue() + fabsf(p.getLevel())) - y; |
558 int ex = x + w; | 557 int ex = x + w; |
559 | |
560 int gap = v->scalePixelSize(2); | 558 int gap = v->scalePixelSize(2); |
561 | 559 |
562 EventVector::const_iterator j = i; | 560 EventVector::const_iterator j = i; |
563 ++j; | 561 ++j; |
564 | 562 |
565 if (j != points.end()) { | 563 if (j != points.end()) { |
566 const Event &q(*j); | 564 const Event &q(*j); |
567 int nx = v->getXForFrame(q.getFrame()); | 565 int nx = v->getXForFrame(q.getFrame()); |
568 if (nx < ex) ex = nx; | 566 if (nx < ex) ex = nx; |
569 } | 567 } |
570 | 568 |
571 if (w < 1) w = 1; | 569 if (w < 1) w = 1; |
572 if (h < 1) h = 1; | |
573 | 570 |
574 paint.setPen(getBaseQColor()); | 571 paint.setPen(getBaseQColor()); |
575 paint.setBrush(brushColour); | 572 paint.setBrush(Qt::NoBrush); |
576 | 573 |
577 if (shouldIlluminate && illuminatePoint == p) { | 574 if ((shouldIlluminate && illuminatePoint == p) || |
578 | 575 (m_editing && m_editingPoint == p)) { |
579 paint.setPen(v->getForeground()); | 576 |
580 paint.setBrush(v->getForeground()); | 577 paint.setPen(QPen(getBaseQColor(), v->scalePixelSize(2))); |
581 | 578 |
582 // Qt 5.13 deprecates QFontMetrics::width(), but its suggested | 579 // Qt 5.13 deprecates QFontMetrics::width(), but its suggested |
583 // replacement (horizontalAdvance) was only added in Qt 5.11 | 580 // replacement (horizontalAdvance) was only added in Qt 5.11 |
584 // which is too new for us | 581 // which is too new for us |
585 #pragma GCC diagnostic ignored "-Wdeprecated-declarations" | 582 #pragma GCC diagnostic ignored "-Wdeprecated-declarations" |
586 | 583 |
587 QString vlabel = | 584 if (abs(h) > 2 * fm.height()) { |
588 QString("%1%2 - %3%4") | 585 |
589 .arg(p.getValue()).arg(getScaleUnits()) | 586 QString y0label = QString("%1 %2") |
590 .arg(p.getValue() + fabsf(p.getLevel())).arg(getScaleUnits()); | 587 .arg(p.getValue()) |
588 .arg(getScaleUnits()); | |
589 | |
590 QString y1label = QString("%1 %2") | |
591 .arg(p.getValue() + fabsf(p.getLevel())) | |
592 .arg(getScaleUnits()); | |
593 | |
594 PaintAssistant::drawVisibleText | |
595 (v, paint, | |
596 x - fm.width(y0label) - gap, | |
597 y - fm.descent(), | |
598 y0label, PaintAssistant::OutlinedText); | |
599 | |
600 PaintAssistant::drawVisibleText | |
601 (v, paint, | |
602 x - fm.width(y1label) - gap, | |
603 y + h + fm.ascent(), | |
604 y1label, PaintAssistant::OutlinedText); | |
605 | |
606 } else { | |
607 | |
608 QString ylabel = QString("%1 %2 - %3 %4") | |
609 .arg(p.getValue()) | |
610 .arg(getScaleUnits()) | |
611 .arg(p.getValue() + fabsf(p.getLevel())) | |
612 .arg(getScaleUnits()); | |
613 | |
614 PaintAssistant::drawVisibleText | |
615 (v, paint, | |
616 x - fm.width(ylabel) - gap, | |
617 y - fm.descent(), | |
618 ylabel, PaintAssistant::OutlinedText); | |
619 } | |
620 | |
621 QString t0label = RealTime::frame2RealTime | |
622 (p.getFrame(), model->getSampleRate()).toText(true).c_str(); | |
623 | |
624 QString t1label = RealTime::frame2RealTime | |
625 (p.getFrame() + p.getDuration(), model->getSampleRate()) | |
626 .toText(true).c_str(); | |
627 | |
591 PaintAssistant::drawVisibleText | 628 PaintAssistant::drawVisibleText |
592 (v, paint, | 629 (v, paint, x, y + fm.ascent() + gap, |
593 x - paint.fontMetrics().width(vlabel) - gap, | 630 t0label, PaintAssistant::OutlinedText); |
594 y + paint.fontMetrics().height()/2 | 631 |
595 - paint.fontMetrics().descent(), | 632 if (w > fm.width(t0label) + fm.width(t1label) + gap * 3) { |
596 vlabel, PaintAssistant::OutlinedText); | 633 |
597 | 634 PaintAssistant::drawVisibleText |
598 QString hlabel = RealTime::frame2RealTime | 635 (v, paint, |
599 (p.getFrame(), model->getSampleRate()).toText(true).c_str(); | 636 x + w - fm.width(t1label), |
600 PaintAssistant::drawVisibleText | 637 y + fm.ascent() + gap, |
601 (v, paint, | 638 t1label, PaintAssistant::OutlinedText); |
602 x, | 639 |
603 y - h/2 - paint.fontMetrics().descent() - gap, | 640 } else { |
604 hlabel, PaintAssistant::OutlinedText); | 641 |
642 PaintAssistant::drawVisibleText | |
643 (v, paint, | |
644 x + w - fm.width(t1label), | |
645 y + fm.ascent() + fm.height() + gap, | |
646 t1label, PaintAssistant::OutlinedText); | |
647 } | |
605 } | 648 } |
606 | 649 |
607 paint.drawRect(x, y, w, h); | 650 paint.drawRect(x, y, w, h); |
608 } | 651 } |
609 | 652 |
610 for (EventVector::const_iterator i = points.begin(); | 653 for (EventVector::const_iterator i = points.begin(); |
611 i != points.end(); ++i) { | 654 i != points.end(); ++i) { |
612 | 655 |
613 const Event &p(*i); | 656 const Event &p(*i); |
614 | 657 |
658 QString label = p.getLabel(); | |
659 if (label == "") continue; | |
660 | |
661 if (shouldIlluminate && illuminatePoint == p) { | |
662 continue; // already handled this in illumination special case | |
663 } | |
664 | |
615 int x = v->getXForFrame(p.getFrame()); | 665 int x = v->getXForFrame(p.getFrame()); |
616 int w = v->getXForFrame(p.getFrame() + p.getDuration()) - x; | 666 int w = v->getXForFrame(p.getFrame() + p.getDuration()) - x; |
617 int y = getYForValue(v, p.getValue()); | 667 int y = getYForValue(v, p.getValue()); |
618 | 668 |
619 QString label = p.getLabel(); | 669 int labelWidth = fm.width(label); |
620 if (label == "") { | |
621 label = | |
622 QString("%1%2 - %3%4") | |
623 .arg(p.getValue()).arg(getScaleUnits()) | |
624 .arg(p.getValue() + fabsf(p.getLevel())).arg(getScaleUnits()); | |
625 } | |
626 int labelWidth = paint.fontMetrics().width(label); | |
627 | 670 |
628 int gap = v->scalePixelSize(2); | 671 int gap = v->scalePixelSize(2); |
629 | 672 |
630 if (x + w < x0 || x - labelWidth - gap > x1) { | 673 if (x + w < x0 || x - labelWidth - gap > x1) { |
631 continue; | 674 continue; |
632 } | 675 } |
633 | 676 |
634 bool illuminated = false; | 677 int labelX, labelY; |
635 | 678 |
636 if (shouldIlluminate && illuminatePoint == p) { | 679 labelX = x - labelWidth - gap; |
637 illuminated = true; | 680 labelY = y - fm.descent(); |
638 } | 681 |
639 | 682 PaintAssistant::drawVisibleText(v, paint, labelX, labelY, label, |
640 if (!illuminated) { | 683 PaintAssistant::OutlinedText); |
641 | |
642 int labelX, labelY; | |
643 | |
644 labelX = x - labelWidth - gap; | |
645 labelY = y + paint.fontMetrics().height()/2 | |
646 - paint.fontMetrics().descent(); | |
647 | |
648 PaintAssistant::drawVisibleText(v, paint, labelX, labelY, label, | |
649 PaintAssistant::OutlinedText); | |
650 } | |
651 } | 684 } |
652 | 685 |
653 paint.restore(); | 686 paint.restore(); |
654 } | 687 } |
655 | 688 |
698 paint.fontMetrics(), | 731 paint.fontMetrics(), |
699 mw)); | 732 mw)); |
700 } | 733 } |
701 } | 734 } |
702 | 735 |
703 //!!! All of the editing operations still need to be updated for | |
704 //!!! vertical frequency range instead of just value | |
705 | |
706 void | 736 void |
707 TimeFrequencyBoxLayer::drawStart(LayerGeometryProvider *v, QMouseEvent *e) | 737 TimeFrequencyBoxLayer::drawStart(LayerGeometryProvider *v, QMouseEvent *e) |
708 { | 738 { |
709 auto model = ModelById::getAs<TimeFrequencyBoxModel>(m_model); | 739 auto model = ModelById::getAs<TimeFrequencyBoxModel>(m_model); |
710 if (!model) return; | 740 if (!model) return; |
711 | 741 |
712 sv_frame_t frame = v->getFrameForX(e->x()); | 742 sv_frame_t frame = v->getFrameForX(e->x()); |
713 if (frame < 0) frame = 0; | 743 if (frame < 0) frame = 0; |
714 frame = frame / model->getResolution() * model->getResolution(); | 744 frame = frame / model->getResolution() * model->getResolution(); |
715 | 745 |
716 double value = getValueForY(v, e->y()); | 746 double frequency = getValueForY(v, e->y()); |
717 | 747 |
718 m_editingPoint = Event(frame, float(value), 0, ""); | 748 m_editingPoint = Event(frame, float(frequency), 0, ""); |
719 m_originalPoint = m_editingPoint; | 749 m_originalPoint = m_editingPoint; |
720 | 750 |
721 if (m_editingCommand) finish(m_editingCommand); | 751 if (m_editingCommand) finish(m_editingCommand); |
722 m_editingCommand = new ChangeEventsCommand(m_model.untyped, | 752 m_editingCommand = new ChangeEventsCommand(m_model.untyped, |
723 tr("Draw Time-Frequency Box")); | 753 tr("Draw Time-Frequency Box")); |
730 TimeFrequencyBoxLayer::drawDrag(LayerGeometryProvider *v, QMouseEvent *e) | 760 TimeFrequencyBoxLayer::drawDrag(LayerGeometryProvider *v, QMouseEvent *e) |
731 { | 761 { |
732 auto model = ModelById::getAs<TimeFrequencyBoxModel>(m_model); | 762 auto model = ModelById::getAs<TimeFrequencyBoxModel>(m_model); |
733 if (!model || !m_editing) return; | 763 if (!model || !m_editing) return; |
734 | 764 |
735 sv_frame_t frame = v->getFrameForX(e->x()); | 765 sv_frame_t dragFrame = v->getFrameForX(e->x()); |
736 if (frame < 0) frame = 0; | 766 if (dragFrame < 0) dragFrame = 0; |
737 frame = frame / model->getResolution() * model->getResolution(); | 767 dragFrame = dragFrame / model->getResolution() * model->getResolution(); |
738 | 768 |
739 double newValue = getValueForY(v, e->y()); | 769 sv_frame_t eventFrame = m_originalPoint.getFrame(); |
740 | 770 sv_frame_t eventDuration = dragFrame - eventFrame; |
741 sv_frame_t newFrame = m_editingPoint.getFrame(); | 771 if (eventDuration < 0) { |
742 sv_frame_t newDuration = frame - newFrame; | 772 eventFrame = eventFrame + eventDuration; |
743 if (newDuration < 0) { | 773 eventDuration = -eventDuration; |
744 newFrame = frame; | 774 } else if (eventDuration == 0) { |
745 newDuration = -newDuration; | 775 eventDuration = model->getResolution(); |
746 } else if (newDuration == 0) { | 776 } |
747 newDuration = 1; | 777 |
778 double dragFrequency = getValueForY(v, e->y()); | |
779 | |
780 double eventFrequency = m_originalPoint.getValue(); | |
781 double eventFreqDiff = dragFrequency - eventFrequency; | |
782 if (eventFreqDiff < 0) { | |
783 eventFrequency = eventFrequency + eventFreqDiff; | |
784 eventFreqDiff = -eventFreqDiff; | |
748 } | 785 } |
749 | 786 |
750 m_editingCommand->remove(m_editingPoint); | 787 m_editingCommand->remove(m_editingPoint); |
751 m_editingPoint = m_editingPoint | 788 m_editingPoint = m_editingPoint |
752 .withFrame(newFrame) | 789 .withFrame(eventFrame) |
753 .withValue(float(newValue)) | 790 .withDuration(eventDuration) |
754 .withDuration(newDuration); | 791 .withValue(float(eventFrequency)) |
792 .withLevel(float(eventFreqDiff)); | |
755 m_editingCommand->add(m_editingPoint); | 793 m_editingCommand->add(m_editingPoint); |
756 } | 794 } |
757 | 795 |
758 void | 796 void |
759 TimeFrequencyBoxLayer::drawEnd(LayerGeometryProvider *, QMouseEvent *) | 797 TimeFrequencyBoxLayer::drawEnd(LayerGeometryProvider *, QMouseEvent *) |