Mercurial > hg > svgui
diff layer/TimeValueLayer.cpp @ 1486:ac0a8addabcf
Merge from branch by-id
author | Chris Cannam |
---|---|
date | Wed, 17 Jul 2019 14:25:16 +0100 |
parents | e540aa5d89cd |
children | a2fbcfeb2572 |
line wrap: on
line diff
--- a/layer/TimeValueLayer.cpp Thu Jun 13 15:35:01 2019 +0100 +++ b/layer/TimeValueLayer.cpp Wed Jul 17 14:25:16 2019 +0100 @@ -54,7 +54,6 @@ TimeValueLayer::TimeValueLayer() : SingleColourLayer(), - m_model(nullptr), m_editing(false), m_originalPoint(0, 0.0, tr("New Point")), m_editingPoint(0, 0.0, tr("New Point")), @@ -71,28 +70,41 @@ } +int +TimeValueLayer::getCompletion(LayerGeometryProvider *) const +{ + auto model = ModelById::get(m_model); + if (model) return model->getCompletion(); + else return 0; +} + void -TimeValueLayer::setModel(SparseTimeValueModel *model) +TimeValueLayer::setModel(ModelId modelId) { - if (m_model == model) return; - m_model = model; + auto newModel = ModelById::getAs<SparseTimeValueModel>(modelId); + + if (!modelId.isNone() && !newModel) { + throw std::logic_error("Not a SparseTimeValueModel"); + } + + if (m_model == modelId) return; + m_model = modelId; - connectSignals(m_model); + if (newModel) { + + connectSignals(m_model); - m_scaleMinimum = 0; - m_scaleMaximum = 0; + m_scaleMinimum = 0; + m_scaleMaximum = 0; - if (m_model && m_model->getRDFTypeURI().endsWith("Segment")) { - setPlotStyle(PlotSegmentation); + if (newModel->getRDFTypeURI().endsWith("Segment")) { + setPlotStyle(PlotSegmentation); + } + if (newModel->getRDFTypeURI().endsWith("Change")) { + setPlotStyle(PlotSegmentation); + } } - if (m_model && m_model->getRDFTypeURI().endsWith("Change")) { - setPlotStyle(PlotSegmentation); - } - -#ifdef DEBUG_TIME_VALUE_LAYER - cerr << "TimeValueLayer::setModel(" << model << ")" << endl; -#endif - + emit modelReplaced(); } @@ -152,10 +164,19 @@ return SingleColourLayer::getPropertyGroupName(name); } +bool +TimeValueLayer::needsTextLabelHeight() const +{ + auto model = ModelById::getAs<SparseTimeValueModel>(m_model); + if (!model) return false; + return m_plotStyle == PlotSegmentation && model->hasTextLabels(); +} + QString TimeValueLayer::getScaleUnits() const { - if (m_model) return m_model->getScaleUnits(); + auto model = ModelById::getAs<SparseTimeValueModel>(m_model); + if (model) return model->getScaleUnits(); else return ""; } @@ -192,7 +213,8 @@ } else if (name == "Scale Units") { if (deflt) *deflt = 0; - if (m_model) { + auto model = ModelById::getAs<SparseTimeValueModel>(m_model); + if (model) { val = UnitDatabase::getInstance()->getUnitId (getScaleUnits()); } @@ -258,10 +280,11 @@ } else if (name == "Vertical Scale") { setVerticalScale(VerticalScale(value)); } else if (name == "Scale Units") { - if (m_model) { - m_model->setScaleUnits + auto model = ModelById::getAs<SparseTimeValueModel>(m_model); + if (model) { + model->setScaleUnits (UnitDatabase::getInstance()->getUnitById(value)); - emit modelChanged(); + emit modelChanged(m_model); } } else if (name == "Draw Segment Division Lines") { setDrawSegmentDivisions(value > 0.5); @@ -335,10 +358,11 @@ TimeValueLayer::getValueExtents(double &min, double &max, bool &logarithmic, QString &unit) const { - if (!m_model) return false; + auto model = ModelById::getAs<SparseTimeValueModel>(m_model); + if (!model) return false; - min = m_model->getValueMinimum(); - max = m_model->getValueMaximum(); + min = model->getValueMinimum(); + max = model->getValueMaximum(); logarithmic = (m_verticalScale == LogScale); @@ -375,7 +399,8 @@ bool TimeValueLayer::getDisplayExtents(double &min, double &max) const { - if (!m_model || shouldAutoAlign()) return false; + auto model = ModelById::getAs<SparseTimeValueModel>(m_model); + if (!model || shouldAutoAlign()) return false; if (m_scaleMinimum == m_scaleMaximum) { bool log; @@ -401,7 +426,8 @@ bool TimeValueLayer::setDisplayExtents(double min, double max) { - if (!m_model) return false; + auto model = ModelById::getAs<SparseTimeValueModel>(m_model); + if (!model) return false; if (min == max) { if (min == 0.f) { @@ -426,7 +452,8 @@ TimeValueLayer::getVerticalZoomSteps(int &defaultStep) const { if (shouldAutoAlign()) return 0; - if (!m_model) return 0; + auto model = ModelById::getAs<SparseTimeValueModel>(m_model); + if (!model) return 0; defaultStep = 0; return 100; @@ -436,7 +463,8 @@ TimeValueLayer::getCurrentVerticalZoomStep() const { if (shouldAutoAlign()) return 0; - if (!m_model) return 0; + auto model = ModelById::getAs<SparseTimeValueModel>(m_model); + if (!model) return 0; RangeMapper *mapper = getNewVerticalZoomRangeMapper(); if (!mapper) return 0; @@ -459,7 +487,8 @@ TimeValueLayer::setVerticalZoomStep(int step) { if (shouldAutoAlign()) return; - if (!m_model) return; + auto model = ModelById::getAs<SparseTimeValueModel>(m_model); + if (!model) return; RangeMapper *mapper = getNewVerticalZoomRangeMapper(); if (!mapper) return; @@ -511,7 +540,8 @@ RangeMapper * TimeValueLayer::getNewVerticalZoomRangeMapper() const { - if (!m_model) return nullptr; + auto model = ModelById::getAs<SparseTimeValueModel>(m_model); + if (!model) return nullptr; RangeMapper *mapper; @@ -534,7 +564,8 @@ EventVector TimeValueLayer::getLocalPoints(LayerGeometryProvider *v, int x) const { - if (!m_model) return {}; + auto model = ModelById::getAs<SparseTimeValueModel>(m_model); + if (!model) return {}; // Return all points at a frame f, where f is the closest frame to // pixel coordinate x whose pixel coordinate is both within a @@ -544,12 +575,12 @@ sv_frame_t frame = v->getFrameForX(x); - EventVector exact = m_model->getEventsStartingAt(frame); + EventVector exact = model->getEventsStartingAt(frame); if (!exact.empty()) return exact; // overspill == 1, so one event either side of the given span - EventVector neighbouring = m_model->getEventsWithin - (frame, m_model->getResolution(), 1); + EventVector neighbouring = model->getEventsWithin + (frame, model->getResolution(), 1); double fuzz = v->scaleSize(2); sv_frame_t suitable = 0; @@ -573,7 +604,7 @@ } if (have) { - return m_model->getEventsStartingAt(suitable); + return model->getEventsStartingAt(suitable); } else { return {}; } @@ -582,10 +613,11 @@ QString TimeValueLayer::getLabelPreceding(sv_frame_t frame) const { - if (!m_model || !m_model->hasTextLabels()) return ""; + auto model = ModelById::getAs<SparseTimeValueModel>(m_model); + if (!model || !model->hasTextLabels()) return ""; Event e; - if (m_model->getNearestEventMatching + if (model->getNearestEventMatching (frame, [](Event e) { return e.hasLabel() && e.getLabel() != ""; }, EventSeries::Backward, @@ -601,12 +633,13 @@ { int x = pos.x(); - if (!m_model || !m_model->getSampleRate()) return ""; + auto model = ModelById::getAs<SparseTimeValueModel>(m_model); + if (!model || !model->getSampleRate()) return ""; EventVector points = getLocalPoints(v, x); if (points.empty()) { - if (!m_model->isReady()) { + if (!model->isReady()) { return tr("In progress"); } else { return tr("No local points"); @@ -615,7 +648,7 @@ sv_frame_t useFrame = points.begin()->getFrame(); - RealTime rt = RealTime::frame2RealTime(useFrame, m_model->getSampleRate()); + RealTime rt = RealTime::frame2RealTime(useFrame, model->getSampleRate()); QString valueText; float value = points.begin()->getValue(); @@ -656,7 +689,8 @@ int &resolution, SnapType snap) const { - if (!m_model) { + auto model = ModelById::getAs<SparseTimeValueModel>(m_model); + if (!model) { return Layer::snapToFeatureFrame(v, frame, resolution, snap); } @@ -667,7 +701,7 @@ // an editing operation, i.e. closest feature in either direction // but only if it is "close enough" - resolution = m_model->getResolution(); + resolution = model->getResolution(); if (snap == SnapNeighbouring) { EventVector points = getLocalPoints(v, v->getXForFrame(frame)); @@ -677,7 +711,7 @@ } Event e; - if (m_model->getNearestEventMatching + if (model->getNearestEventMatching (frame, [](Event) { return true; }, snap == SnapLeft ? EventSeries::Backward : EventSeries::Forward, @@ -695,20 +729,21 @@ int &resolution, SnapType snap) const { - if (!m_model) { + auto model = ModelById::getAs<SparseTimeValueModel>(m_model); + if (!model) { return Layer::snapToSimilarFeature(v, frame, resolution, snap); } // snap is only permitted to be SnapLeft or SnapRight here. - resolution = m_model->getResolution(); + resolution = model->getResolution(); Event ref; Event e; float matchvalue; bool found; - found = m_model->getNearestEventMatching + found = model->getNearestEventMatching (frame, [](Event) { return true; }, EventSeries::Backward, ref); if (!found) { @@ -717,7 +752,7 @@ matchvalue = ref.getValue(); - found = m_model->getNearestEventMatching + found = model->getNearestEventMatching (frame, [matchvalue](Event e) { double epsilon = 0.0001; @@ -741,11 +776,14 @@ max = 0.0; log = false; + auto model = ModelById::getAs<SparseTimeValueModel>(m_model); + if (!model) return; + if (shouldAutoAlign()) { if (!v->getValueExtents(getScaleUnits(), min, max, log)) { - min = m_model->getValueMinimum(); - max = m_model->getValueMaximum(); + min = model->getValueMinimum(); + max = model->getValueMaximum(); } else if (log) { LogRange::mapRange(min, max); } @@ -812,7 +850,6 @@ bool TimeValueLayer::shouldAutoAlign() const { - if (!m_model) return false; QString unit = getScaleUnits(); return (m_verticalScale == AutoAlignScale && unit != ""); } @@ -851,9 +888,10 @@ void TimeValueLayer::paint(LayerGeometryProvider *v, QPainter &paint, QRect rect) const { - if (!m_model || !m_model->isOK()) return; + auto model = ModelById::getAs<SparseTimeValueModel>(m_model); + if (!model || !model->isOK()) return; - sv_samplerate_t sampleRate = m_model->getSampleRate(); + sv_samplerate_t sampleRate = model->getSampleRate(); if (!sampleRate) return; paint.setRenderHint(QPainter::Antialiasing, false); @@ -865,7 +903,7 @@ sv_frame_t frame1 = v->getFrameForX(x1); if (m_derivative) --frame0; - EventVector points(m_model->getEventsWithin(frame0, frame1 - frame0, 1)); + EventVector points(model->getEventsWithin(frame0, frame1 - frame0, 1)); if (points.empty()) return; paint.setPen(getBaseQColor()); @@ -876,11 +914,11 @@ #ifdef DEBUG_TIME_VALUE_LAYER cerr << "TimeValueLayer::paint: resolution is " - << m_model->getResolution() << " frames" << endl; + << model->getResolution() << " frames" << endl; #endif - double min = m_model->getValueMinimum(); - double max = m_model->getValueMaximum(); + double min = model->getValueMinimum(); + double max = model->getValueMaximum(); if (max == min) max = min + 1.0; int origin = int(nearbyint(v->getPaintHeight() - @@ -900,7 +938,7 @@ } int w = - v->getXForFrame(frame0 + m_model->getResolution()) - + v->getXForFrame(frame0 + model->getResolution()) - v->getXForFrame(frame0); if (m_plotStyle == PlotStems) { @@ -953,7 +991,7 @@ continue; } gap = (p.getFrame() > prevFrame && - (p.getFrame() - prevFrame >= m_model->getResolution() * 2)); + (p.getFrame() - prevFrame >= model->getResolution() * 2)); } if (m_plotStyle != PlotSegmentation) { @@ -1077,7 +1115,7 @@ if (m_plotStyle == PlotDiscreteCurves) { bool nextGap = (nvalue == 0.0) || - (nf - p.getFrame() >= m_model->getResolution() * 2); + (nf - p.getFrame() >= model->getResolution() * 2); if (nextGap) { x1 = x0; y1 = y0; @@ -1140,6 +1178,11 @@ italic = true; } + // Qt 5.13 deprecates QFontMetrics::width(), but its suggested + // replacement (horizontalAdvance) was only added in Qt 5.11 + // which is too new for us +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" + if (label != "") { // Quick test for 20px before we do the slower test using metrics bool haveRoom = (nx > x + 20); @@ -1179,7 +1222,8 @@ int TimeValueLayer::getVerticalScaleWidth(LayerGeometryProvider *v, bool, QPainter &paint) const { - if (!m_model) { + auto model = ModelById::getAs<SparseTimeValueModel>(m_model); + if (!model) { return 0; } else if (shouldAutoAlign() && !valueExtentsMatchMine(v)) { return 0; @@ -1201,7 +1245,8 @@ void TimeValueLayer::paintVerticalScale(LayerGeometryProvider *v, bool, QPainter &paint, QRect) const { - if (!m_model || m_model->isEmpty()) return; + auto model = ModelById::getAs<SparseTimeValueModel>(m_model); + if (!model || model->isEmpty()) return; QString unit; double min, max; @@ -1257,10 +1302,11 @@ cerr << "TimeValueLayer::drawStart(" << e->x() << "," << e->y() << ")" << endl; #endif - if (!m_model) return; + auto model = ModelById::getAs<SparseTimeValueModel>(m_model); + if (!model) return; sv_frame_t frame = v->getFrameForX(e->x()); - int resolution = m_model->getResolution(); + int resolution = model->getResolution(); if (frame < 0) frame = 0; frame = (frame / resolution) * resolution; @@ -1290,7 +1336,7 @@ m_originalPoint = m_editingPoint; if (m_editingCommand) finish(m_editingCommand); - m_editingCommand = new ChangeEventsCommand(m_model, tr("Draw Point")); + m_editingCommand = new ChangeEventsCommand(m_model.untyped, tr("Draw Point")); if (!havePoint) { m_editingCommand->add(m_editingPoint); } @@ -1305,10 +1351,11 @@ cerr << "TimeValueLayer::drawDrag(" << e->x() << "," << e->y() << ")" << endl; #endif - if (!m_model || !m_editing) return; + auto model = ModelById::getAs<SparseTimeValueModel>(m_model); + if (!model || !m_editing) return; sv_frame_t frame = v->getFrameForX(e->x()); - int resolution = m_model->getResolution(); + int resolution = model->getResolution(); if (frame < 0) frame = 0; frame = (frame / resolution) * resolution; @@ -1366,7 +1413,8 @@ #ifdef DEBUG_TIME_VALUE_LAYER cerr << "TimeValueLayer::drawEnd" << endl; #endif - if (!m_model || !m_editing) return; + auto model = ModelById::getAs<SparseTimeValueModel>(m_model); + if (!model || !m_editing) return; finish(m_editingCommand); m_editingCommand = nullptr; m_editing = false; @@ -1375,7 +1423,8 @@ void TimeValueLayer::eraseStart(LayerGeometryProvider *v, QMouseEvent *e) { - if (!m_model) return; + auto model = ModelById::getAs<SparseTimeValueModel>(m_model); + if (!model) return; EventVector points = getLocalPoints(v, e->x()); if (points.empty()) return; @@ -1398,7 +1447,8 @@ void TimeValueLayer::eraseEnd(LayerGeometryProvider *v, QMouseEvent *e) { - if (!m_model || !m_editing) return; + auto model = ModelById::getAs<SparseTimeValueModel>(m_model); + if (!model || !m_editing) return; m_editing = false; @@ -1407,7 +1457,7 @@ if (points.begin()->getFrame() != m_editingPoint.getFrame() || points.begin()->getValue() != m_editingPoint.getValue()) return; - m_editingCommand = new ChangeEventsCommand(m_model, tr("Erase Point")); + m_editingCommand = new ChangeEventsCommand(m_model.untyped, tr("Erase Point")); m_editingCommand->remove(m_editingPoint); finish(m_editingCommand); m_editingCommand = nullptr; @@ -1421,7 +1471,8 @@ cerr << "TimeValueLayer::editStart(" << e->x() << "," << e->y() << ")" << endl; #endif - if (!m_model) return; + auto model = ModelById::getAs<SparseTimeValueModel>(m_model); + if (!model) return; EventVector points = getLocalPoints(v, e->x()); if (points.empty()) return; @@ -1444,16 +1495,17 @@ cerr << "TimeValueLayer::editDrag(" << e->x() << "," << e->y() << ")" << endl; #endif - if (!m_model || !m_editing) return; + auto model = ModelById::getAs<SparseTimeValueModel>(m_model); + if (!model || !m_editing) return; sv_frame_t frame = v->getFrameForX(e->x()); if (frame < 0) frame = 0; - frame = frame / m_model->getResolution() * m_model->getResolution(); + frame = frame / model->getResolution() * model->getResolution(); double value = getValueForY(v, e->y()); if (!m_editingCommand) { - m_editingCommand = new ChangeEventsCommand(m_model, tr("Drag Point")); + m_editingCommand = new ChangeEventsCommand(m_model.untyped, tr("Drag Point")); } m_editingCommand->remove(m_editingPoint); @@ -1469,7 +1521,8 @@ #ifdef DEBUG_TIME_VALUE_LAYER cerr << "TimeValueLayer::editEnd" << endl; #endif - if (!m_model || !m_editing) return; + auto model = ModelById::getAs<SparseTimeValueModel>(m_model); + if (!model || !m_editing) return; if (m_editingCommand) { @@ -1496,7 +1549,8 @@ bool TimeValueLayer::editOpen(LayerGeometryProvider *v, QMouseEvent *e) { - if (!m_model) return false; + auto model = ModelById::getAs<SparseTimeValueModel>(m_model); + if (!model) return false; EventVector points = getLocalPoints(v, e->x()); if (points.empty()) return false; @@ -1504,7 +1558,7 @@ Event point = *points.begin(); ItemEditDialog *dialog = new ItemEditDialog - (m_model->getSampleRate(), + (model->getSampleRate(), ItemEditDialog::ShowTime | ItemEditDialog::ShowValue | ItemEditDialog::ShowText, @@ -1522,7 +1576,7 @@ .withLabel(dialog->getText()); ChangeEventsCommand *command = - new ChangeEventsCommand(m_model, tr("Edit Point")); + new ChangeEventsCommand(m_model.untyped, tr("Edit Point")); command->remove(point); command->add(newPoint); finish(command); @@ -1535,13 +1589,14 @@ void TimeValueLayer::moveSelection(Selection s, sv_frame_t newStartFrame) { - if (!m_model) return; + auto model = ModelById::getAs<SparseTimeValueModel>(m_model); + if (!model) return; ChangeEventsCommand *command = - new ChangeEventsCommand(m_model, tr("Drag Selection")); + new ChangeEventsCommand(m_model.untyped, tr("Drag Selection")); EventVector points = - m_model->getEventsWithin(s.getStartFrame(), s.getDuration()); + model->getEventsWithin(s.getStartFrame(), s.getDuration()); for (Event p: points) { @@ -1557,13 +1612,14 @@ void TimeValueLayer::resizeSelection(Selection s, Selection newSize) { - if (!m_model || !s.getDuration()) return; + auto model = ModelById::getAs<SparseTimeValueModel>(m_model); + if (!model || !s.getDuration()) return; ChangeEventsCommand *command = - new ChangeEventsCommand(m_model, tr("Resize Selection")); + new ChangeEventsCommand(m_model.untyped, tr("Resize Selection")); EventVector points = - m_model->getEventsWithin(s.getStartFrame(), s.getDuration()); + model->getEventsWithin(s.getStartFrame(), s.getDuration()); double ratio = double(newSize.getDuration()) / double(s.getDuration()); double oldStart = double(s.getStartFrame()); @@ -1585,13 +1641,14 @@ void TimeValueLayer::deleteSelection(Selection s) { - if (!m_model) return; + auto model = ModelById::getAs<SparseTimeValueModel>(m_model); + if (!model) return; ChangeEventsCommand *command = - new ChangeEventsCommand(m_model, tr("Delete Selected Points")); + new ChangeEventsCommand(m_model.untyped, tr("Delete Selected Points")); EventVector points = - m_model->getEventsWithin(s.getStartFrame(), s.getDuration()); + model->getEventsWithin(s.getStartFrame(), s.getDuration()); for (Event p: points) { command->remove(p); @@ -1603,10 +1660,11 @@ void TimeValueLayer::copy(LayerGeometryProvider *v, Selection s, Clipboard &to) { - if (!m_model) return; + auto model = ModelById::getAs<SparseTimeValueModel>(m_model); + if (!model) return; EventVector points = - m_model->getEventsWithin(s.getStartFrame(), s.getDuration()); + model->getEventsWithin(s.getStartFrame(), s.getDuration()); for (Event p: points) { to.addPoint(p.withReferenceFrame(alignToReference(v, p.getFrame()))); @@ -1617,7 +1675,8 @@ TimeValueLayer::paste(LayerGeometryProvider *v, const Clipboard &from, sv_frame_t /* frameOffset */, bool interactive) { - if (!m_model) return false; + auto model = ModelById::getAs<SparseTimeValueModel>(m_model); + if (!model) return false; EventVector points = from.getPoints(); @@ -1641,7 +1700,7 @@ } ChangeEventsCommand *command = - new ChangeEventsCommand(m_model, tr("Paste")); + new ChangeEventsCommand(m_model.untyped, tr("Paste")); enum ValueAvailability { UnknownAvailability, @@ -1654,7 +1713,7 @@ bool haveUsableLabels = false; Labeller labeller; - labeller.setSampleRate(m_model->getSampleRate()); + labeller.setSampleRate(model->getSampleRate()); if (interactive) {