18 #include "data/model/Model.h" 19 #include "base/RealTime.h" 20 #include "base/Profiler.h" 21 #include "base/LogRange.h" 22 #include "base/RangeMapper.h" 23 #include "base/Pitch.h" 26 #include "data/model/SparseTimeValueModel.h" 27 #include "data/model/Labeller.h" 43 #include <QPainterPath> 44 #include <QMouseEvent> 46 #include <QTextStream> 47 #include <QMessageBox> 48 #include <QInputDialog> 58 m_originalPoint(0, 0.0, tr(
"New Point")),
59 m_editingPoint(0, 0.0, tr(
"New Point")),
60 m_editingCommand(nullptr),
62 m_colourInverted(false),
63 m_plotStyle(PlotConnectedPoints),
64 m_verticalScale(AutoAlignScale),
65 m_drawSegmentDivisions(true),
76 auto model = ModelById::get(
m_model);
77 if (model)
return model->getCompletion();
84 auto newModel = ModelById::getAs<SparseTimeValueModel>(modelId);
86 if (!modelId.isNone() && !newModel) {
87 throw std::logic_error(
"Not a SparseTimeValueModel");
100 if (newModel->getRDFTypeURI().endsWith(
"Segment")) {
103 if (newModel->getRDFTypeURI().endsWith(
"Change")) {
115 list.push_back(
"Plot Type");
116 list.push_back(
"Vertical Scale");
117 list.push_back(
"Scale Units");
118 list.push_back(
"Draw Segment Division Lines");
119 list.push_back(
"Show Derivative");
126 if (name ==
"Plot Type")
return tr(
"Plot Type");
127 if (name ==
"Vertical Scale")
return tr(
"Vertical Scale");
128 if (name ==
"Scale Units")
return tr(
"Scale Units");
129 if (name ==
"Draw Segment Division Lines")
return tr(
"Draw Segment Division Lines");
130 if (name ==
"Show Derivative")
return tr(
"Show Derivative");
137 if (name ==
"Draw Segment Division Lines")
return "lines";
138 if (name ==
"Show Derivative")
return "derivative";
145 if (name ==
"Plot Type")
return ValueProperty;
146 if (name ==
"Vertical Scale")
return ValueProperty;
147 if (name ==
"Scale Units")
return UnitsProperty;
149 if (name ==
"Draw Segment Division Lines")
return ToggleProperty;
150 if (name ==
"Show Derivative")
return ToggleProperty;
157 if (name ==
"Vertical Scale" || name ==
"Scale Units") {
160 if (name ==
"Plot Type" || name ==
"Draw Segment Division Lines" ||
161 name ==
"Show Derivative") {
162 return tr(
"Plot Type");
170 auto model = ModelById::getAs<SparseTimeValueModel>(
m_model);
171 if (!model)
return false;
178 auto model = ModelById::getAs<SparseTimeValueModel>(
m_model);
179 if (model)
return model->getScaleUnits();
185 int *min,
int *max,
int *deflt)
const 193 if (deflt) *deflt = 0;
197 }
else if (name ==
"Plot Type") {
205 }
else if (name ==
"Vertical Scale") {
213 }
else if (name ==
"Scale Units") {
215 if (deflt) *deflt = 0;
216 auto model = ModelById::getAs<SparseTimeValueModel>(
m_model);
218 val = UnitDatabase::getInstance()->getUnitId
222 }
else if (name ==
"Draw Segment Division Lines") {
226 if (deflt) *deflt = 1;
229 }
else if (name ==
"Show Derivative") {
233 if (deflt) *deflt = 0;
250 }
else if (name ==
"Plot Type") {
253 case 0:
return tr(
"Points");
254 case 1:
return tr(
"Stems");
255 case 2:
return tr(
"Connected Points");
256 case 3:
return tr(
"Lines");
257 case 4:
return tr(
"Curve");
258 case 5:
return tr(
"Segmentation");
259 case 6:
return tr(
"Discrete Curves");
261 }
else if (name ==
"Vertical Scale") {
264 case 0:
return tr(
"Auto-Align");
265 case 1:
return tr(
"Linear");
266 case 2:
return tr(
"Log");
267 case 3:
return tr(
"+/-1");
278 }
else if (name ==
"Plot Type") {
280 }
else if (name ==
"Vertical Scale") {
282 }
else if (name ==
"Scale Units") {
283 auto model = ModelById::getAs<SparseTimeValueModel>(
m_model);
286 (UnitDatabase::getInstance()->getUnitById(value));
289 }
else if (name ==
"Draw Segment Division Lines") {
291 }
else if (name ==
"Show Derivative") {
313 if (colourTypeChanged) {
359 bool &logarithmic, QString &unit)
const 361 auto model = ModelById::getAs<SparseTimeValueModel>(
m_model);
362 if (!model)
return false;
364 min = model->getValueMinimum();
365 max = model->getValueMaximum();
372 max = std::max(fabs(min), fabs(max));
376 #ifdef DEBUG_TIME_VALUE_LAYER 377 cerr <<
"TimeValueLayer::getValueExtents: min = " << min <<
", max = " << max << endl;
386 double margin = (max - min) / 10.0;
391 #ifdef DEBUG_TIME_VALUE_LAYER 392 cerr <<
"TimeValueLayer::getValueExtents: min = " << min <<
", max = " << max <<
" (after adjustment)" << endl;
402 auto model = ModelById::getAs<SparseTimeValueModel>(
m_model);
415 max = std::max(fabs(min), fabs(max));
419 #ifdef DEBUG_TIME_VALUE_LAYER 420 cerr <<
"TimeValueLayer::getDisplayExtents: min = " << min <<
", max = " << max << endl;
429 auto model = ModelById::getAs<SparseTimeValueModel>(
m_model);
430 if (!model)
return false;
443 #ifdef DEBUG_TIME_VALUE_LAYER 444 cerr <<
"TimeValueLayer::setDisplayExtents: min = " << min <<
", max = " << max << endl;
455 auto model = ModelById::getAs<SparseTimeValueModel>(
m_model);
456 if (!model)
return 0;
466 auto model = ModelById::getAs<SparseTimeValueModel>(
m_model);
467 if (!model)
return 0;
470 if (!mapper)
return 0;
475 int nr = mapper->getPositionForValue(dmax - dmin);
477 #ifdef DEBUG_TIME_VALUE_LAYER 478 cerr <<
"TimeValueLayer::getCurrentVerticalZoomStep: dmin = " << dmin <<
", dmax = " << dmax <<
", nr = " << nr << endl;
490 auto model = ModelById::getAs<SparseTimeValueModel>(
m_model);
504 double newdist = mapper->getValueForPosition(100 - step);
506 double newmin, newmax;
512 newmax = (newdist + sqrt(newdist*newdist + 4*dmin*dmax)) / 2;
513 newmin = newmax - newdist;
515 #ifdef DEBUG_TIME_VALUE_LAYER 516 cerr <<
"newmin = " << newmin <<
", newmax = " << newmax << endl;
520 double dmid = (dmax + dmin) / 2;
521 newmin = dmid - newdist / 2;
522 newmax = dmid + newdist / 2;
526 newmax += (min - newmin);
533 #ifdef DEBUG_TIME_VALUE_LAYER 534 cerr <<
"TimeValueLayer::setVerticalZoomStep: " << step <<
": " << newmin <<
" -> " << newmax <<
" (range " << newdist <<
")" << endl;
543 auto model = ModelById::getAs<SparseTimeValueModel>(
m_model);
544 if (!model)
return nullptr;
553 if (min == max)
return nullptr;
556 mapper =
new LogRangeMapper(0, 100, min, max, unit);
558 mapper =
new LinearRangeMapper(0, 100, min, max, unit);
567 auto model = ModelById::getAs<SparseTimeValueModel>(
m_model);
568 if (!model)
return {};
578 EventVector exact = model->getEventsStartingAt(frame);
579 if (!exact.empty())
return exact;
582 EventVector neighbouring = model->getEventsWithin
583 (frame, model->getResolution(), 1);
586 sv_frame_t suitable = 0;
589 for (Event e: neighbouring) {
590 sv_frame_t f = e.getFrame();
591 if (f < v->getStartFrame() || f > v->
getEndFrame()) {
595 if ((px > x && px - x > fuzz) || (px < x && x - px > fuzz + 3)) {
601 }
else if (llabs(frame - f) < llabs(suitable - f)) {
607 return model->getEventsStartingAt(suitable);
616 auto model = ModelById::getAs<SparseTimeValueModel>(
m_model);
617 if (!model || !model->hasTextLabels())
return "";
620 if (model->getNearestEventMatching
622 [](Event e) { return e.hasLabel() && e.getLabel() !=
""; },
623 EventSeries::Backward,
636 auto model = ModelById::getAs<SparseTimeValueModel>(
m_model);
637 if (!model || !model->getSampleRate())
return "";
641 if (points.empty()) {
642 if (!model->isReady()) {
643 return tr(
"In progress");
645 return tr(
"No local points");
649 sv_frame_t useFrame = points.begin()->getFrame();
651 RealTime rt = RealTime::frame2RealTime(useFrame, model->getSampleRate());
654 float value = points.begin()->getValue();
658 valueText = tr(
"%1 Hz (%2, %3)")
660 .arg(Pitch::getPitchLabelForFrequency(value))
661 .arg(Pitch::getPitchForFrequency(value));
662 }
else if (unit !=
"") {
663 valueText = tr(
"%1 %2").arg(value).arg(unit);
665 valueText = tr(
"%1").arg(value);
670 if (points.begin()->getLabel() ==
"") {
671 text = QString(tr(
"Time:\t%1\nValue:\t%2\nNo label"))
672 .arg(rt.toText(
true).c_str())
675 text = QString(tr(
"Time:\t%1\nValue:\t%2\nLabel:\t%4"))
676 .arg(rt.toText(
true).c_str())
678 .arg(points.begin()->getLabel());
692 auto model = ModelById::getAs<SparseTimeValueModel>(
m_model);
704 resolution = model->getResolution();
708 if (points.empty())
return false;
709 frame = points.begin()->getFrame();
714 if (model->getNearestEventMatching
716 [](Event) { return true; },
717 snap ==
SnapLeft ? EventSeries::Backward : EventSeries::Forward,
719 frame = e.getFrame();
732 auto model = ModelById::getAs<SparseTimeValueModel>(
m_model);
739 resolution = model->getResolution();
746 found = model->getNearestEventMatching
747 (frame, [](Event) {
return true; }, EventSeries::Backward, ref);
753 matchvalue = ref.getValue();
755 found = model->getNearestEventMatching
757 [matchvalue](Event e) {
758 double epsilon = 0.0001;
759 return fabs(e.getValue() - matchvalue) < epsilon;
761 snap ==
SnapLeft ? EventSeries::Backward : EventSeries::Forward,
768 frame = e.getFrame();
779 auto model = ModelById::getAs<SparseTimeValueModel>(
m_model);
785 min = model->getValueMinimum();
786 max = model->getValueMaximum();
788 #ifdef DEBUG_TIME_VALUE_LAYER 789 SVCERR <<
"getScaleExtents: view returned min = " << min
790 <<
", max = " << max <<
", log = " << log << endl;
793 LogRange::mapRange(min, max);
794 #ifdef DEBUG_TIME_VALUE_LAYER 795 SVCERR <<
"getScaleExtents: mapped to min = " << min
796 <<
", max = " << max << endl;
811 LogRange::mapRange(min, max);
816 #ifdef DEBUG_TIME_VALUE_LAYER 817 cerr <<
"TimeValueLayer::getScaleExtents: min = " << min <<
", max = " << max << endl;
824 double min = 0.0, max = 0.0;
825 bool logarithmic =
false;
830 #ifdef DEBUG_TIME_VALUE_LAYER 831 SVCERR <<
"getYForValue(" << val <<
"): min " << min <<
", max " 832 << max <<
", log " << logarithmic << endl;
836 val = LogRange::map(val);
837 #ifdef DEBUG_TIME_VALUE_LAYER 838 SVCERR <<
"-> " << val << endl;
842 return int(h - ((val - min) * h) / (max - min));
848 double min = 0.0, max = 0.0;
849 bool logarithmic =
false;
854 double val = min + (double(h - y) * double(max - min)) / h;
857 val = LogRange::map(val);
877 if (min > max) std::swap(min, max);
878 if (max == min) max = min + 1;
881 val = LogRange::map(val);
884 #ifdef DEBUG_TIME_VALUE_LAYER 885 cerr <<
"TimeValueLayer::getColourForValue: min " << min <<
", max " 886 << max <<
", log " << log <<
", value " << val << endl;
890 return QColor(solid.red(), solid.green(), solid.blue(), 120);
898 (QString(darkbg ?
"Bright Green" :
"Green"));
904 auto model = ModelById::getAs<SparseTimeValueModel>(
m_model);
905 if (!model || !model->isOK())
return;
907 sv_samplerate_t sampleRate = model->getSampleRate();
908 if (!sampleRate)
return;
910 #ifdef DEBUG_TIME_VALUE_LAYER 911 SVCERR <<
"TimeValueLayer[" <<
this <<
", model " <<
getModel() <<
"]::paint in " << v->
getId() << endl;
914 paint.setRenderHint(QPainter::Antialiasing,
false);
918 int x0 = rect.left();
919 int x1 = x0 + rect.width();
924 EventVector points(model->getEventsWithin(frame0, frame1 - frame0, 1));
926 #ifdef DEBUG_TIME_VALUE_LAYER 927 SVCERR <<
"TimeValueLayer[" <<
this <<
"]::paint in " << v->
getId()
928 <<
": pixel extents " << x0 <<
" to " << x1 <<
", frame extents " 929 << frame0 <<
" to " << frame1 <<
" yielding " << points.size()
930 <<
" points (of " << model->getAllEvents().size()
931 <<
" from frames " << model->getStartFrame() <<
" to " 932 << model->getEndFrame() <<
")" << endl;
935 if (points.empty())
return;
940 brushColour.setAlpha(80);
941 paint.setBrush(brushColour);
943 #ifdef DEBUG_TIME_VALUE_LAYER 944 cerr <<
"TimeValueLayer::paint: resolution is " 945 << model->getResolution() <<
" frames" << endl;
948 double min = model->getValueMinimum();
949 double max = model->getValueMaximum();
950 if (max == min) max = min + 1.0;
956 sv_frame_t illuminateFrame = -1;
960 #ifdef DEBUG_TIME_VALUE_LAYER 961 cerr <<
"TimeValueLayer: " << localPoints.size() <<
" local points" << endl;
963 if (!localPoints.empty()) {
964 illuminateFrame = localPoints.begin()->getFrame();
988 if (originY > 0 && originY < v->getPaintHeight()) {
991 paint.drawLine(x0, originY, x1, originY);
996 sv_frame_t prevFrame = 0;
998 for (EventVector::const_iterator i = points.begin();
999 i != points.end(); ++i) {
1005 double value = p.getValue();
1007 EventVector::const_iterator j = i;
1009 value -= j->getValue();
1021 gap = (p.getFrame() > prevFrame &&
1022 (p.getFrame() - prevFrame >= model->getResolution() * 2));
1026 textY = y - paint.fontMetrics().height()
1027 + paint.fontMetrics().ascent() - 1;
1028 if (textY < paint.fontMetrics().ascent() + 1) {
1029 textY = paint.fontMetrics().ascent() + 1;
1033 bool haveNext =
false;
1034 double nvalue = 0.f;
1039 EventVector::const_iterator j = i;
1042 if (j != points.end()) {
1044 nvalue = q.getValue();
1056 QBrush brush(brushColour);
1060 brush = QBrush(Qt::NoBrush);
1066 brush = QBrush(Qt::NoBrush);
1070 paint.setBrush(brush);
1073 if (y < origin - 1) {
1074 paint.drawLine(x + w/2, y + 1, x + w/2, origin);
1075 }
else if (y > origin + 1) {
1076 paint.drawLine(x + w/2, origin, x + w/2, y - 1);
1080 bool illuminate =
false;
1082 if (illuminateFrame == p.getFrame()) {
1105 paint.drawRect(x, y - 1, w, 2);
1122 paint.setPen(v->
scalePen(brushColour));
1123 paint.drawLine(x + w, y, nx, ny);
1128 if (pointCount == 0) {
1129 path.moveTo(x + w/2, y);
1133 path.lineTo(nx + w/2, ny);
1137 double x0 = x + double(w)/2;
1138 double x1 = nx + double(w)/2;
1146 (nf - p.getFrame() >= model->getResolution() * 2);
1153 if (pointCount == 0 || gap) {
1154 path.moveTo((x0 + x1) / 2, (y0 + y1) / 2);
1158 path.cubicTo(x0, y0,
1160 (x0 + x1) / 2, (y0 + y1) / 2);
1166 path.lineTo(x0, y0);
1167 path.lineTo((x0 + x1) / 2, (y0 + y1) / 2);
1175 #ifdef DEBUG_TIME_VALUE_LAYER 1176 cerr <<
"drawing rect" << endl;
1179 if (nx <= x)
continue;
1187 paint.setPen(Qt::NoPen);
1196 QString label = p.getLabel();
1197 bool italic =
false;
1204 snprintf(lc, 20,
"%.3g", p.getValue());
1212 #pragma GCC diagnostic ignored "-Wdeprecated-declarations" 1216 bool haveRoom = (nx > x + 20);
1217 haveRoom = (haveRoom &&
1218 (nx > x + 6 + paint.fontMetrics().width(label)));
1221 (pointCount == 0 || !italic))) {
1223 (v, paint, x + 5, textY, label,
1231 prevFrame = p.getFrame();
1236 paint.setRenderHint(QPainter::Antialiasing,
true);
1237 paint.drawPath(path);
1239 && !path.isEmpty()) {
1240 paint.setRenderHint(QPainter::Antialiasing, pointCount <= v->getPaintWidth());
1241 paint.drawPath(path);
1247 paint.setRenderHint(QPainter::Antialiasing,
false);
1253 auto model = ModelById::getAs<SparseTimeValueModel>(
m_model);
1276 auto model = ModelById::getAs<SparseTimeValueModel>(
m_model);
1277 if (!model || model->isEmpty())
return;
1291 LogRange::mapRange(min, max);
1309 (v, paint, QRect(w - 10, 0, 10, h),
1310 LogRange::unmap(min),
1311 LogRange::unmap(max));
1312 paint.drawLine(w, 0, w, h);
1319 5 + paint.fontMetrics().ascent(),
1321 paint.fontMetrics(),
1329 #ifdef DEBUG_TIME_VALUE_LAYER 1330 cerr <<
"TimeValueLayer::drawStart(" << e->x() <<
"," << e->y() <<
")" << endl;
1333 auto model = ModelById::getAs<SparseTimeValueModel>(
m_model);
1337 int resolution = model->getResolution();
1338 if (frame < 0) frame = 0;
1339 frame = (frame / resolution) * resolution;
1343 bool havePoint =
false;
1346 if (!points.empty()) {
1347 for (EventVector::iterator i = points.begin();
1348 i != points.end(); ++i) {
1349 if (((i->getFrame() / resolution) * resolution) != frame) {
1350 #ifdef DEBUG_TIME_VALUE_LAYER 1351 cerr <<
"ignoring out-of-range frame at " << i->getFrame() << endl;
1378 #ifdef DEBUG_TIME_VALUE_LAYER 1379 cerr <<
"TimeValueLayer::drawDrag(" << e->x() <<
"," << e->y() <<
")" << endl;
1382 auto model = ModelById::getAs<SparseTimeValueModel>(
m_model);
1386 int resolution = model->getResolution();
1387 if (frame < 0) frame = 0;
1388 frame = (frame / resolution) * resolution;
1394 #ifdef DEBUG_TIME_VALUE_LAYER 1395 cerr << points.size() <<
" points" << endl;
1398 bool havePoint =
false;
1400 if (!points.empty()) {
1401 for (EventVector::iterator i = points.begin();
1402 i != points.end(); ++i) {
1405 #ifdef DEBUG_TIME_VALUE_LAYER 1406 cerr <<
"ignoring current editing point at " << i->getFrame() <<
", " << i->getValue() << endl;
1410 if (((i->getFrame() / resolution) * resolution) != frame) {
1411 #ifdef DEBUG_TIME_VALUE_LAYER 1412 cerr <<
"ignoring out-of-range frame at " << i->getFrame() << endl;
1416 #ifdef DEBUG_TIME_VALUE_LAYER 1417 cerr <<
"adjusting to new point at " << i->getFrame() <<
", " << i->getValue() << endl;
1434 .withValue(
float(value));
1441 #ifdef DEBUG_TIME_VALUE_LAYER 1442 cerr <<
"TimeValueLayer::drawEnd" << endl;
1444 auto model = ModelById::getAs<SparseTimeValueModel>(
m_model);
1454 auto model = ModelById::getAs<SparseTimeValueModel>(
m_model);
1458 if (points.empty())
return;
1478 auto model = ModelById::getAs<SparseTimeValueModel>(
m_model);
1484 if (points.empty())
return;
1498 #ifdef DEBUG_TIME_VALUE_LAYER 1499 cerr <<
"TimeValueLayer::editStart(" << e->x() <<
"," << e->y() <<
")" << endl;
1502 auto model = ModelById::getAs<SparseTimeValueModel>(
m_model);
1506 if (points.empty())
return;
1522 #ifdef DEBUG_TIME_VALUE_LAYER 1523 cerr <<
"TimeValueLayer::editDrag(" << e->x() <<
"," << e->y() <<
")" << endl;
1526 auto model = ModelById::getAs<SparseTimeValueModel>(
m_model);
1530 if (frame < 0) frame = 0;
1531 frame = frame / model->getResolution() * model->getResolution();
1542 .withValue(
float(value));
1549 #ifdef DEBUG_TIME_VALUE_LAYER 1550 cerr <<
"TimeValueLayer::editEnd" << endl;
1552 auto model = ModelById::getAs<SparseTimeValueModel>(
m_model);
1561 newName = tr(
"Edit Point");
1563 newName = tr(
"Relocate Point");
1566 newName = tr(
"Change Point Value");
1580 auto model = ModelById::getAs<SparseTimeValueModel>(
m_model);
1581 if (!model)
return false;
1584 if (points.empty())
return false;
1586 Event point = *points.begin();
1589 (model->getSampleRate(),
1596 dialog->
setValue(point.getValue());
1597 dialog->
setText(point.getLabel());
1599 if (dialog->exec() == QDialog::Accepted) {
1601 Event newPoint = point
1604 .withLabel(dialog->
getText());
1606 ChangeEventsCommand *command =
1607 new ChangeEventsCommand(
m_model.untyped, tr(
"Edit Point"));
1608 command->remove(point);
1609 command->add(newPoint);
1620 auto model = ModelById::getAs<SparseTimeValueModel>(
m_model);
1623 ChangeEventsCommand *command =
1624 new ChangeEventsCommand(
m_model.untyped, tr(
"Drag Selection"));
1626 EventVector points =
1627 model->getEventsWithin(s.getStartFrame(), s.getDuration());
1629 for (Event p: points) {
1631 Event newPoint = p.withFrame
1632 (p.getFrame() + newStartFrame - s.getStartFrame());
1634 command->add(newPoint);
1643 auto model = ModelById::getAs<SparseTimeValueModel>(
m_model);
1644 if (!model || !s.getDuration())
return;
1646 ChangeEventsCommand *command =
1647 new ChangeEventsCommand(
m_model.untyped, tr(
"Resize Selection"));
1649 EventVector points =
1650 model->getEventsWithin(s.getStartFrame(), s.getDuration());
1652 double ratio = double(newSize.getDuration()) /
double(s.getDuration());
1653 double oldStart = double(s.getStartFrame());
1654 double newStart = double(newSize.getStartFrame());
1656 for (Event p: points) {
1658 double newFrame = (double(p.getFrame()) - oldStart) * ratio + newStart;
1661 .withFrame(lrint(newFrame));
1663 command->add(newPoint);
1672 auto model = ModelById::getAs<SparseTimeValueModel>(
m_model);
1675 ChangeEventsCommand *command =
1676 new ChangeEventsCommand(
m_model.untyped, tr(
"Delete Selected Points"));
1678 EventVector points =
1679 model->getEventsWithin(s.getStartFrame(), s.getDuration());
1681 for (Event p: points) {
1691 auto model = ModelById::getAs<SparseTimeValueModel>(
m_model);
1694 EventVector points =
1695 model->getEventsWithin(s.getStartFrame(), s.getDuration());
1697 for (Event p: points) {
1704 sv_frame_t ,
bool interactive)
1706 auto model = ModelById::getAs<SparseTimeValueModel>(
m_model);
1707 if (!model)
return false;
1709 EventVector points = from.getPoints();
1711 bool realign =
false;
1715 QMessageBox::StandardButton button =
1716 QMessageBox::question(v->
getView(), tr(
"Re-align pasted items?"),
1717 tr(
"The items you are pasting came from a layer with different source material from this one. Do you want to re-align them in time, to match the source material for this layer?"),
1718 QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel,
1721 if (button == QMessageBox::Cancel) {
1725 if (button == QMessageBox::Yes) {
1730 ChangeEventsCommand *command =
1731 new ChangeEventsCommand(
m_model.untyped, tr(
"Paste"));
1733 enum ValueAvailability {
1734 UnknownAvailability,
1740 Labeller::ValueType generation = Labeller::ValueNone;
1742 bool haveUsableLabels =
false;
1744 labeller.setSampleRate(model->getSampleRate());
1748 ValueAvailability availability = UnknownAvailability;
1750 for (EventVector::const_iterator i = points.begin();
1751 i != points.end(); ++i) {
1753 if (availability == UnknownAvailability) {
1754 if (i->hasValue()) availability = AllValues;
1755 else availability = NoValues;
1759 if (i->hasValue()) {
1760 if (availability == NoValues) {
1761 availability = SomeValues;
1764 if (availability == AllValues) {
1765 availability = SomeValues;
1769 if (!haveUsableLabels) {
1770 if (i->hasLabel()) {
1771 if (i->getLabel().contains(QRegExp(
"[0-9]"))) {
1772 haveUsableLabels =
true;
1777 if (availability == SomeValues && haveUsableLabels)
break;
1780 if (availability == NoValues || availability == SomeValues) {
1783 if (availability == NoValues) {
1784 text = tr(
"The items you are pasting do not have values.\nWhat values do you want to use for these items?");
1786 text = tr(
"Some of the items you are pasting do not have values.\nWhat values do you want to use for these items?");
1789 Labeller::TypeNameMap names = labeller.getTypeNames();
1791 QStringList options;
1792 std::vector<Labeller::ValueType> genopts;
1794 for (Labeller::TypeNameMap::const_iterator i = names.begin();
1795 i != names.end(); ++i) {
1796 if (i->first == Labeller::ValueNone) options << tr(
"Zero for all items");
1797 else options << i->second;
1798 genopts.push_back(i->first);
1801 static int prevSelection = 0;
1805 (
nullptr, tr(
"Choose value calculation"),
1806 text, options, prevSelection, &ok);
1813 generation = Labeller::ValueNone;
1815 for (QStringList::const_iterator i = options.begin();
1816 i != options.end(); ++i) {
1817 if (selected == *i) {
1818 generation = genopts[selection];
1824 labeller.setType(generation);
1826 if (generation == Labeller::ValueFromCyclicalCounter ||
1827 generation == Labeller::ValueFromTwoLevelCounter) {
1828 int cycleSize = QInputDialog::getInt
1829 (
nullptr, tr(
"Select cycle size"),
1830 tr(
"Cycle size:"), 4, 2, 16, 1);
1831 labeller.setCounterCycleSize(cycleSize);
1834 prevSelection = selection;
1840 for (EventVector::const_iterator i = points.begin();
1841 i != points.end(); ++i) {
1843 sv_frame_t frame = 0;
1847 frame = i->getFrame();
1851 if (i->hasReferenceFrame()) {
1852 frame = i->getReferenceFrame();
1855 frame = i->getFrame();
1859 Event newPoint = i->withFrame(frame);
1861 if (!i->hasLabel() && i->hasValue()) {
1862 newPoint = newPoint.withLabel(QString(
"%1").arg(i->getValue()));
1865 bool usePrev =
false;
1866 Event formerPrevPoint = prevPoint;
1868 if (!i->hasValue()) {
1869 #ifdef DEBUG_TIME_VALUE_LAYER 1870 cerr <<
"Setting value on point at " << newPoint.getFrame() <<
" from labeller";
1871 if (i == points.begin()) {
1872 cerr <<
", no prev point" << endl;
1874 cerr <<
", prev point is at " << prevPoint.getFrame() << endl;
1878 Labeller::Revaluing valuing =
1880 (newPoint, (i == points.begin()) ?
nullptr : &prevPoint);
1882 #ifdef DEBUG_TIME_VALUE_LAYER 1883 cerr <<
"New point value = " << newPoint.getValue() << endl;
1885 if (valuing.first == Labeller::AppliesToPreviousEvent) {
1887 prevPoint = valuing.second;
1889 newPoint = valuing.second;
1894 command->remove(formerPrevPoint);
1895 command->add(prevPoint);
1898 prevPoint = newPoint;
1899 command->add(newPoint);
1908 QString indent, QString extraAttributes)
const 1912 s += QString(
"plotStyle=\"%1\" " 1913 "verticalScale=\"%2\" " 1914 "scaleMinimum=\"%3\" " 1915 "scaleMaximum=\"%4\" " 1916 "drawDivisions=\"%5\" " 1917 "derivative=\"%6\" ")
1928 s += QString(
"fillColourMap=\"%1\" ")
1933 s += QString(
"colourMap=\"%1\" ")
1946 QString colourMapId = attributes.value(
"fillColourMap");
1948 if (colourMap >= 0) {
1951 colourMap = attributes.value(
"colourMap").toInt(&ok);
1958 attributes.value(
"plotStyle").toInt(&ok);
1962 attributes.value(
"verticalScale").toInt(&ok);
1965 bool draw = (attributes.value(
"drawDivisions").trimmed() ==
"true");
1968 bool derivative = (attributes.value(
"derivative").trimmed() ==
"true");
1971 float min = attributes.value(
"scaleMinimum").toFloat(&ok);
1972 float max = attributes.value(
"scaleMaximum").toFloat(&alsoOk);
1973 #ifdef DEBUG_TIME_VALUE_LAYER 1974 cerr <<
"from properties: min = " << min <<
", max = " << max << endl;
int getPropertyRangeAndValue(const PropertyName &, int *min, int *max, int *deflt) const override
bool snapToSimilarFeature(LayerGeometryProvider *v, sv_frame_t &frame, int &resolution, SnapType snap) const override
Adjust the given frame to snap to the next feature that has "effectively" the same value as the featu...
ModelId getModel() const override
Return the ID of the model represented in this layer.
virtual bool snapToFeatureFrame(LayerGeometryProvider *, sv_frame_t &, int &resolution, SnapType, int) const
Adjust the given frame to snap to the nearest feature, if possible.
void editStart(LayerGeometryProvider *v, QMouseEvent *) override
void editEnd(LayerGeometryProvider *v, QMouseEvent *) override
QString getPropertyIconName(const PropertyName &) const override
void drawStart(LayerGeometryProvider *v, QMouseEvent *) override
PropertyList getProperties() const override
void getScaleExtents(LayerGeometryProvider *, double &min, double &max, bool &log) const
void editDrag(LayerGeometryProvider *v, QMouseEvent *) override
virtual bool shouldIlluminateLocalFeatures(const Layer *, QPoint &) const =0
void drawDrag(LayerGeometryProvider *v, QMouseEvent *) override
void finish(ChangeEventsCommand *command)
RangeMapper * getNewVerticalZoomRangeMapper() const override
Create and return a range mapper for vertical zoom step values.
static QString abbreviate(QString text, int maxLength, Policy policy=ElideEnd, bool fuzzy=true, QString ellipsis="")
Abbreviate the given text to the given maximum length (including ellipsis), using the given abbreviat...
double getValueForY(LayerGeometryProvider *, int y) const override
void setPlotStyle(PlotStyle style)
virtual QColor getForegroundQColor(LayerGeometryProvider *v) const
void setFrameTime(sv_frame_t frame)
void toXml(QTextStream &stream, QString indent="", QString extraAttributes="") const override
void paintVertical(LayerGeometryProvider *v, const VerticalScaleLayer *layer, QPainter &paint, int x0, double minlog, double maxlog)
void paint(LayerGeometryProvider *v, QPainter &paint, QRect rect) const override
Paint the given rectangle of this layer onto the given view using the given painter, superimposing it on top of any existing material in that view.
sv_frame_t getFrameTime() const
virtual sv_frame_t getFrameForX(int x) const =0
Return the closest frame to the given pixel x-coordinate.
bool getDisplayExtents(double &min, double &max) const override
Return the minimum and maximum values within the visible area for the y axis of this layer...
QString getScaleUnits() const override
static int getColourMapCount()
Return the number of known colour maps.
void resizeSelection(Selection s, Selection newSize) override
std::vector< QColor > getPartialShades(LayerGeometryProvider *v) const
int getWidth(LayerGeometryProvider *v, QPainter &paint)
virtual double scaleSize(double size) const =0
VerticalScale m_verticalScale
virtual QColor getBaseQColor() const
void eraseEnd(LayerGeometryProvider *v, QMouseEvent *) override
void layerParameterRangesChanged()
void toXml(QTextStream &stream, QString indent="", QString extraAttributes="") const override
PropertyList getProperties() const override
int getWidth(LayerGeometryProvider *v, QPainter &paint)
virtual bool snapToSimilarFeature(LayerGeometryProvider *, sv_frame_t &, int &resolution, SnapType) const
Adjust the given frame to snap to the next feature that has "effectively" the same value as the featu...
static int getBackwardCompatibilityColourMap(int n)
Older versions of colour-handling code save and reload colour maps by numerical index and can't prope...
void modelChanged(ModelId)
void setText(QString text)
QString getPropertyValueLabel(const PropertyName &, int value) const override
Interface for classes that provide geometry information (such as size, start frame, and a large number of other properties) about the disposition of a layer.
static QString getColourMapLabel(int n)
Return a human-readable label for the colour map with the given index.
int getVerticalScaleWidth(LayerGeometryProvider *v, bool, QPainter &) const override
void setModel(ModelId model)
int getColourIndex(QString name) const
Return the index of the colour with the given name, if found in the database.
virtual sv_frame_t alignFromReference(LayerGeometryProvider *v, sv_frame_t frame) const
QString getPropertyGroupName(const PropertyName &) const override
static int getColourMapById(QString id)
Return the index for the colour map with the given machine-readable id string, or -1 if the id is not...
bool paste(LayerGeometryProvider *v, const Clipboard &from, sv_frame_t frameOffset, bool interactive) override
Paste from the given clipboard onto the layer at the given frame offset.
void layerParametersChanged()
void setProperty(const PropertyName &, int value) override
bool snapToFeatureFrame(LayerGeometryProvider *v, sv_frame_t &frame, int &resolution, SnapType snap, int ycoord) const override
Adjust the given frame to snap to the nearest feature, if possible.
void copy(LayerGeometryProvider *v, Selection s, Clipboard &to) override
QColor getColourForValue(LayerGeometryProvider *v, double value) const override
bool clipboardHasDifferentAlignment(LayerGeometryProvider *v, const Clipboard &clip) const
void setProperties(const QXmlAttributes &attributes) override
Set the particular properties of a layer (those specific to the subclass) from a set of XML attribute...
ChangeEventsCommand * m_editingCommand
void paintPianoVertical(LayerGeometryProvider *v, QPainter &paint, QRect rect, double minf, double maxf)
int getWidth(LayerGeometryProvider *v, QPainter &paint)
int getPropertyRangeAndValue(const PropertyName &, int *min, int *max, int *deflt) const override
virtual sv_frame_t alignToReference(LayerGeometryProvider *v, sv_frame_t frame) const
QColor map(double value) const
Map the given value to a colour.
void paintVertical(LayerGeometryProvider *v, const VerticalScaleLayer *layer, QPainter &paint, int x0, double minf, double maxf)
bool isLayerScrollable(const LayerGeometryProvider *v) const override
This should return true if the layer can safely be scrolled automatically by a given view (simply cop...
A class for mapping intensity values onto various colour maps.
int getWidth(LayerGeometryProvider *v, QPainter &paint)
bool getValueExtents(double &min, double &max, bool &logarithmic, QString &unit) const override
Return the minimum and maximum values for the y axis of the model in this layer, as well as whether t...
virtual bool shouldShowFeatureLabels() const =0
void connectSignals(ModelId)
virtual int getPaintHeight() const
PropertyType getPropertyType(const PropertyName &) const override
bool valueExtentsMatchMine(LayerGeometryProvider *v) const
int getVerticalZoomSteps(int &defaultStep) const override
Get the number of vertical zoom steps available for this layer.
PropertyType getPropertyType(const PropertyName &) const override
void setVerticalScale(VerticalScale scale)
virtual sv_frame_t getModelsEndFrame() const =0
EventVector getLocalPoints(LayerGeometryProvider *v, int) const
void drawEnd(LayerGeometryProvider *v, QMouseEvent *) override
int getCurrentVerticalZoomStep() const override
Get the current vertical zoom step.
void paintVertical(LayerGeometryProvider *v, const ColourScaleLayer *layer, QPainter &paint, int x0, double minf, double maxf)
int getYForValue(LayerGeometryProvider *, double value) const override
VerticalScaleLayer and ColourScaleLayer methods.
virtual QPen scalePen(QPen pen) const =0
void setProperties(const QXmlAttributes &attributes) override
Set the particular properties of a layer (those specific to the subclass) from a set of XML attribute...
bool setDisplayExtents(double min, double max) override
Set the displayed minimum and maximum values for the y axis to the given range, if supported...
void eraseDrag(LayerGeometryProvider *v, QMouseEvent *) override
QString getFeatureDescription(LayerGeometryProvider *v, QPoint &) const override
QString getLabelPreceding(sv_frame_t) const override
int getCompletion(LayerGeometryProvider *) const override
Return the proportion of background work complete in drawing this view, as a percentage – in most ca...
void setDrawSegmentDivisions(bool)
bool shouldAutoAlign() const
QString getPropertyValueLabel(const PropertyName &, int value) const override
void setVerticalZoomStep(int) override
Set the vertical zoom step.
bool m_drawSegmentDivisions
virtual int getId() const =0
Retrieve the id of this object.
bool editOpen(LayerGeometryProvider *v, QMouseEvent *) override
Open an editor on the item under the mouse (e.g.
int getDefaultColourHint(bool dark, bool &impose) override
static QString getColourMapId(int n)
Return a machine-readable id string for the colour map with the given index.
void setShowDerivative(bool)
virtual int getTextLabelYCoord(const Layer *layer, QPainter &) const =0
Return a y-coordinate at which text labels for individual items in a layer may be drawn...
static void drawVisibleText(const LayerGeometryProvider *, QPainter &p, int x, int y, QString text, TextStyle style)
bool needsTextLabelHeight() const override
True if this layer will need to place text labels when it is painted.
virtual bool getVisibleExtentsForUnit(QString unit, double &min, double &max, bool &log) const =0
Return the visible vertical extents for the given unit, if any.
virtual sv_frame_t getEndFrame() const =0
Retrieve the last visible sample frame on the widget.
void moveSelection(Selection s, sv_frame_t newStartFrame) override
void setFillColourMap(int)
void setProperty(const PropertyName &, int value) override
virtual int getXForFrame(sv_frame_t frame) const =0
Return the pixel x-coordinate corresponding to a given sample frame (which may be negative)...
virtual int getPaintWidth() const
void paintVerticalScale(LayerGeometryProvider *v, bool, QPainter &paint, QRect rect) const override
QString getPropertyLabel(const PropertyName &) const override
QString getPropertyLabel(const PropertyName &) const override
QString getPropertyGroupName(const PropertyName &) const override
static ColourDatabase * getInstance()
void paintVertical(LayerGeometryProvider *v, const ColourScaleLayer *layer, QPainter &paint, int x0, double minf, double maxf)
void deleteSelection(Selection s) override
virtual View * getView()=0
void setValue(float value)
void eraseStart(LayerGeometryProvider *v, QMouseEvent *) override