# HG changeset patch # User Chris Cannam # Date 1563369916 -3600 # Node ID ac0a8addabcfd8a2546977e8496733d981af3339 # Parent de41a11cabc24cacbfd4726caed6e9f6ea812a02# Parent 0e971e3d93e2dd018bedeaacaa8eb9b6cf940719 Merge from branch by-id diff -r de41a11cabc2 -r ac0a8addabcf layer/Colour3DPlotLayer.cpp --- a/layer/Colour3DPlotLayer.cpp Thu Jun 13 15:35:01 2019 +0100 +++ b/layer/Colour3DPlotLayer.cpp Wed Jul 17 14:25:16 2019 +0100 @@ -43,7 +43,6 @@ Colour3DPlotLayer::Colour3DPlotLayer() : - m_model(nullptr), m_colourScale(ColourScaleType::Linear), m_colourScaleSet(false), m_colourMap(0), @@ -59,20 +58,26 @@ m_miny(0), m_maxy(0), m_synchronous(false), - m_peakCache(nullptr), m_peakCacheDivisor(8) { QSettings settings; settings.beginGroup("Preferences"); - setColourMap(settings.value("colour-3d-plot-colour", ColourMapper::Green).toInt()); + setColourMap(settings.value("colour-3d-plot-colour", + ColourMapper::Green).toInt()); settings.endGroup(); } Colour3DPlotLayer::~Colour3DPlotLayer() { invalidateRenderers(); - if (m_peakCache) m_peakCache->aboutToDelete(); - delete m_peakCache; +} + +const ZoomConstraint * +Colour3DPlotLayer::getZoomConstraint() const +{ + auto model = ModelById::get(m_model); + if (model) return model->getZoomConstraint(); + else return nullptr; } ColourScaleType @@ -136,35 +141,38 @@ } void -Colour3DPlotLayer::setModel(const DenseThreeDimensionalModel *model) +Colour3DPlotLayer::setModel(ModelId modelId) { - SVDEBUG << "Colour3DPlotLayer::setModel(" << model << ")" << endl; + auto newModel = ModelById::getAs(modelId); - if (m_model == model) return; - const DenseThreeDimensionalModel *oldModel = m_model; - m_model = model; - if (!m_model || !m_model->isOK()) return; + if (!modelId.isNone() && !newModel) { + throw std::logic_error("Not a DenseThreeDimensionalModel"); + } + + if (m_model == modelId) return; + m_model = modelId; - connectSignals(m_model); + if (newModel) { + connectSignals(m_model); - connect(m_model, SIGNAL(modelChanged()), - this, SLOT(handleModelChanged())); - connect(m_model, SIGNAL(modelChangedWithin(sv_frame_t, sv_frame_t)), - this, SLOT(handleModelChangedWithin(sv_frame_t, sv_frame_t))); + connect(newModel.get(), SIGNAL(modelChanged(ModelId)), + this, SLOT(handleModelChanged(ModelId))); + connect(newModel.get(), SIGNAL(modelChangedWithin(ModelId, sv_frame_t, sv_frame_t)), + this, SLOT(handleModelChangedWithin(ModelId, sv_frame_t, sv_frame_t))); - m_peakResolution = 256; - if (model->getResolution() > 512) { - m_peakResolution = 16; - } else if (model->getResolution() > 128) { - m_peakResolution = 64; - } else if (model->getResolution() > 2) { - m_peakResolution = 128; + m_peakResolution = 256; + if (newModel->getResolution() > 512) { + m_peakResolution = 16; + } else if (newModel->getResolution() > 128) { + m_peakResolution = 64; + } else if (newModel->getResolution() > 2) { + m_peakResolution = 128; + } } - + invalidatePeakCache(); emit modelReplaced(); - emit sliceableModelReplaced(oldModel, model); } void @@ -173,10 +181,11 @@ // renderers use the peak cache, so we must invalidate those too invalidateRenderers(); invalidateMagnitudes(); - - if (m_peakCache) m_peakCache->aboutToDelete(); - delete m_peakCache; - m_peakCache = nullptr; + + if (!m_peakCache.isNone()) { + ModelById::release(m_peakCache); + m_peakCache = {}; + } } void @@ -198,21 +207,24 @@ m_viewMags.clear(); } -Dense3DModelPeakCache * +ModelId Colour3DPlotLayer::getPeakCache() const { - if (!m_peakCache) { - m_peakCache = new Dense3DModelPeakCache(m_model, m_peakCacheDivisor); + if (m_peakCache.isNone()) { + auto peakCache = std::make_shared + (m_model, m_peakCacheDivisor); + m_peakCache = ModelById::add(peakCache); } return m_peakCache; } void -Colour3DPlotLayer::handleModelChanged() +Colour3DPlotLayer::handleModelChanged(ModelId modelId) { if (!m_colourScaleSet && m_colourScale == ColourScaleType::Linear) { - if (m_model) { - if (m_model->shouldUseLogValueScale()) { + auto model = ModelById::getAs(m_model); + if (model) { + if (model->shouldUseLogValueScale()) { setColourScale(ColourScaleType::Log); } else { m_colourScaleSet = true; @@ -220,22 +232,25 @@ } } invalidatePeakCache(); - emit modelChanged(); + emit modelChanged(modelId); } void -Colour3DPlotLayer::handleModelChangedWithin(sv_frame_t startFrame, sv_frame_t endFrame) +Colour3DPlotLayer::handleModelChangedWithin(ModelId modelId, + sv_frame_t startFrame, + sv_frame_t endFrame) { if (!m_colourScaleSet && m_colourScale == ColourScaleType::Linear) { - if (m_model && m_model->getWidth() > 50) { - if (m_model->shouldUseLogValueScale()) { + auto model = ModelById::getAs(m_model); + if (model && model->getWidth() > 50) { + if (model->shouldUseLogValueScale()) { setColourScale(ColourScaleType::Log); } else { m_colourScaleSet = true; } } } - emit modelChangedWithin(startFrame, endFrame); + emit modelChangedWithin(modelId, startFrame, endFrame); } Layer::PropertyList @@ -649,14 +664,23 @@ return false; } +int +Colour3DPlotLayer::getCompletion(LayerGeometryProvider *) const +{ + auto model = ModelById::get(m_model); + if (model) return model->getCompletion(); + else return 0; +} + bool Colour3DPlotLayer::getValueExtents(double &min, double &max, bool &logarithmic, QString &unit) const { - if (!m_model) return false; + auto model = ModelById::getAs(m_model); + if (!model) return false; min = 0; - max = double(m_model->getHeight()); + max = double(model->getHeight()); logarithmic = (m_binScale == BinScale::Log); unit = ""; @@ -667,9 +691,10 @@ bool Colour3DPlotLayer::getDisplayExtents(double &min, double &max) const { - if (!m_model) return false; + auto model = ModelById::getAs(m_model); + if (!model) return false; - double hmax = double(m_model->getHeight()); + double hmax = double(model->getHeight()); min = m_miny; max = m_maxy; @@ -686,8 +711,6 @@ bool Colour3DPlotLayer::setDisplayExtents(double min, double max) { - if (!m_model) return false; - m_miny = int(lrint(min)); m_maxy = int(lrint(max)); @@ -707,37 +730,40 @@ int Colour3DPlotLayer::getVerticalZoomSteps(int &defaultStep) const { - if (!m_model) return 0; + auto model = ModelById::getAs(m_model); + if (!model) return 0; defaultStep = 0; - int h = m_model->getHeight(); + int h = model->getHeight(); return h; } int Colour3DPlotLayer::getCurrentVerticalZoomStep() const { - if (!m_model) return 0; + auto model = ModelById::getAs(m_model); + if (!model) return 0; double min, max; getDisplayExtents(min, max); - return m_model->getHeight() - int(lrint(max - min)); + return model->getHeight() - int(lrint(max - min)); } void Colour3DPlotLayer::setVerticalZoomStep(int step) { - if (!m_model) return; + auto model = ModelById::getAs(m_model); + if (!model) return; // SVDEBUG << "Colour3DPlotLayer::setVerticalZoomStep(" <getHeight(), + 0, model->getHeight(), ""); } double Colour3DPlotLayer::getYForBin(const LayerGeometryProvider *v, double bin) const { double y = bin; - if (!m_model) return y; - double mn = 0, mx = m_model->getHeight(); + auto model = ModelById::getAs(m_model); + if (!model) return y; + double mn = 0, mx = model->getHeight(); getDisplayExtents(mn, mx); double h = v->getPaintHeight(); if (m_binScale == BinScale::Linear) { @@ -777,8 +808,9 @@ Colour3DPlotLayer::getBinForY(const LayerGeometryProvider *v, double y) const { double bin = y; - if (!m_model) return bin; - double mn = 0, mx = m_model->getHeight(); + auto model = ModelById::getAs(m_model); + if (!model) return bin; + double mn = 0, mx = model->getHeight(); getDisplayExtents(mn, mx); double h = v->getPaintHeight(); if (m_binScale == BinScale::Linear) { @@ -798,17 +830,18 @@ QString Colour3DPlotLayer::getFeatureDescription(LayerGeometryProvider *v, QPoint &pos) const { - if (!m_model) return ""; + auto model = ModelById::getAs(m_model); + if (!model) return ""; int x = pos.x(); int y = pos.y(); - sv_frame_t modelStart = m_model->getStartFrame(); - int modelResolution = m_model->getResolution(); + sv_frame_t modelStart = model->getStartFrame(); + int modelResolution = model->getResolution(); double srRatio = v->getViewManager()->getMainModelSampleRate() / - m_model->getSampleRate(); + model->getSampleRate(); int sx0 = int((double(v->getFrameForX(x)) / srRatio - double(modelStart)) / modelResolution); @@ -816,7 +849,7 @@ int f0 = sx0 * modelResolution; int f1 = f0 + modelResolution; - int sh = m_model->getHeight(); + int sh = model->getHeight(); int symin = m_miny; int symax = m_maxy; @@ -832,26 +865,26 @@ int sy = getIBinForY(v, y); - if (sy < 0 || sy >= m_model->getHeight()) { + if (sy < 0 || sy >= model->getHeight()) { return ""; } if (m_invertVertical) { - sy = m_model->getHeight() - sy - 1; + sy = model->getHeight() - sy - 1; } - float value = m_model->getValueAt(sx0, sy); + float value = model->getValueAt(sx0, sy); // cerr << "bin value (" << sx0 << "," << sy << ") is " << value << endl; - QString binName = m_model->getBinName(sy); + QString binName = model->getBinName(sy); if (binName == "") binName = QString("[%1]").arg(sy + 1); else binName = QString("%1 [%2]").arg(binName).arg(sy + 1); QString text = tr("Time:\t%1 - %2\nBin:\t%3\nValue:\t%4") - .arg(RealTime::frame2RealTime(f0, m_model->getSampleRate()) + .arg(RealTime::frame2RealTime(f0, model->getSampleRate()) .toText(true).c_str()) - .arg(RealTime::frame2RealTime(f1, m_model->getSampleRate()) + .arg(RealTime::frame2RealTime(f1, model->getSampleRate()) .toText(true).c_str()) .arg(binName) .arg(value); @@ -870,15 +903,21 @@ int Colour3DPlotLayer::getVerticalScaleWidth(LayerGeometryProvider *, bool, QPainter &paint) const { - if (!m_model) return 0; + auto model = ModelById::getAs(m_model); + if (!model) return 0; - QString sampleText = QString("[%1]").arg(m_model->getHeight()); + // 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" + + QString sampleText = QString("[%1]").arg(model->getHeight()); int tw = paint.fontMetrics().width(sampleText); bool another = false; - for (int i = 0; i < m_model->getHeight(); ++i) { - if (m_model->getBinName(i).length() > sampleText.length()) { - sampleText = m_model->getBinName(i); + for (int i = 0; i < model->getHeight(); ++i) { + if (model->getBinName(i).length() > sampleText.length()) { + sampleText = model->getBinName(i); another = true; } } @@ -892,7 +931,8 @@ void Colour3DPlotLayer::paintVerticalScale(LayerGeometryProvider *v, bool, QPainter &paint, QRect rect) const { - if (!m_model) return; + auto model = ModelById::getAs(m_model); + if (!model) return; int h = rect.height(), w = rect.width(); @@ -930,25 +970,27 @@ int msw = paint.fontMetrics().width(maxstr); - QMatrix m; + QTransform m; m.translate(cw - 6, ch + 10); m.rotate(-90); - paint.setWorldMatrix(m); + paint.setWorldTransform(m); - PaintAssistant::drawVisibleText(v, paint, 2, 0, minstr, PaintAssistant::OutlinedText); + PaintAssistant::drawVisibleText(v, paint, 2, 0, minstr, + PaintAssistant::OutlinedText); m.translate(ch - msw - 2, 0); - paint.setWorldMatrix(m); + paint.setWorldTransform(m); - PaintAssistant::drawVisibleText(v, paint, 0, 0, maxstr, PaintAssistant::OutlinedText); + PaintAssistant::drawVisibleText(v, paint, 0, 0, maxstr, + PaintAssistant::OutlinedText); paint.restore(); } paint.setPen(v->getForeground()); - int sh = m_model->getHeight(); + int sh = model->getHeight(); int symin = m_miny; int symax = m_maxy; @@ -994,10 +1036,10 @@ int idx = i - 1; if (m_invertVertical) { - idx = m_model->getHeight() - idx - 1; + idx = model->getHeight() - idx - 1; } - QString text = m_model->getBinName(idx); + QString text = model->getBinName(idx); if (text == "") text = QString("[%1]").arg(idx + 1); int ty = y0 + (h/2) - (paint.fontMetrics().height()/2) + @@ -1013,13 +1055,15 @@ Colour3DPlotRenderer * Colour3DPlotLayer::getRenderer(const LayerGeometryProvider *v) const { + auto model = ModelById::getAs(m_model); + if (!model) return nullptr; + int viewId = v->getId(); if (m_renderers.find(viewId) == m_renderers.end()) { Colour3DPlotRenderer::Sources sources; sources.verticalBinLayer = this; - sources.fft = nullptr; sources.source = m_model; sources.peakCaches.push_back(getPeakCache()); @@ -1037,16 +1081,16 @@ maxValue = m_viewMags[viewId].getMax(); } else if (m_normalization == ColumnNormalization::Hybrid) { minValue = 0; - maxValue = log10(m_model->getMaximumLevel() + 1.0); + maxValue = log10(model->getMaximumLevel() + 1.0); } else if (m_normalization == ColumnNormalization::None) { - minValue = m_model->getMinimumLevel(); - maxValue = m_model->getMaximumLevel(); + minValue = model->getMinimumLevel(); + maxValue = model->getMaximumLevel(); } SVDEBUG << "Colour3DPlotLayer: rebuilding renderer, value range is " << minValue << " -> " << maxValue - << " (model min = " << m_model->getMinimumLevel() - << ", max = " << m_model->getMaximumLevel() << ")" + << " (model min = " << model->getMinimumLevel() + << ", max = " << model->getMaximumLevel() << ")" << endl; if (maxValue <= minValue) { @@ -1139,9 +1183,10 @@ void Colour3DPlotLayer::paint(LayerGeometryProvider *v, QPainter &paint, QRect rect) const { + auto model = ModelById::getAs(m_model); /* - if (m_model) { - SVDEBUG << "Colour3DPlotLayer::paint: model says shouldUseLogValueScale = " << m_model->shouldUseLogValueScale() << endl; + if (model) { + SVDEBUG << "Colour3DPlotLayer::paint: model says shouldUseLogValueScale = " << model->shouldUseLogValueScale() << endl; } */ Profiler profiler("Colour3DPlotLayer::paint"); @@ -1150,7 +1195,7 @@ #endif int completion = 0; - if (!m_model || !m_model->isOK() || !m_model->isReady(&completion)) { + if (!model || !model->isOK() || !model->isReady(&completion)) { if (completion > 0) { paint.fillRect(0, 10, v->getPaintWidth() * completion / 100, 10, QColor(120, 120, 120)); @@ -1158,7 +1203,7 @@ return; } - if (m_model->getWidth() == 0) { + if (model->getWidth() == 0) { #ifdef DEBUG_COLOUR_3D_PLOT_LAYER_PAINT SVDEBUG << "Colour3DPlotLayer::paint(): model width == 0, " << "nothing to paint (yet)" << endl; @@ -1174,11 +1219,12 @@ int &resolution, SnapType snap) const { - if (!m_model) { + auto model = ModelById::getAs(m_model); + if (!model) { return Layer::snapToFeatureFrame(v, frame, resolution, snap); } - resolution = m_model->getResolution(); + resolution = model->getResolution(); sv_frame_t left = (frame / resolution) * resolution; sv_frame_t right = left + resolution; diff -r de41a11cabc2 -r ac0a8addabcf layer/Colour3DPlotLayer.h --- a/layer/Colour3DPlotLayer.h Thu Jun 13 15:35:01 2019 +0100 +++ b/layer/Colour3DPlotLayer.h Wed Jul 17 14:25:16 2019 +0100 @@ -46,23 +46,28 @@ Colour3DPlotLayer(); ~Colour3DPlotLayer(); - const ZoomConstraint *getZoomConstraint() const override { - return m_model ? m_model->getZoomConstraint() : 0; - } - const Model *getModel() const override { return m_model; } - void paint(LayerGeometryProvider *v, QPainter &paint, QRect rect) const override; + ModelId getModel() const override { return m_model; } + + const ZoomConstraint *getZoomConstraint() const override; + + void paint(LayerGeometryProvider *v, + QPainter &paint, QRect rect) const override; void setSynchronousPainting(bool synchronous) override; - int getVerticalScaleWidth(LayerGeometryProvider *v, bool, QPainter &) const override; - void paintVerticalScale(LayerGeometryProvider *v, bool, QPainter &paint, QRect rect) const override; + int getVerticalScaleWidth(LayerGeometryProvider *v, + bool, QPainter &) const override; + void paintVerticalScale(LayerGeometryProvider *v, + bool, QPainter &paint, QRect rect) const override; - QString getFeatureDescription(LayerGeometryProvider *v, QPoint &) const override; + QString getFeatureDescription(LayerGeometryProvider *v, + QPoint &) const override; bool snapToFeatureFrame(LayerGeometryProvider *v, sv_frame_t &frame, - int &resolution, - SnapType snap) const override; + int &resolution, + SnapType snap) const override; - void setLayerDormant(const LayerGeometryProvider *v, bool dormant) override; + void setLayerDormant(const LayerGeometryProvider *v, + bool dormant) override; bool isLayerScrollable(const LayerGeometryProvider *v) const override; @@ -70,9 +75,9 @@ return ColourHasMeaningfulValue; } - void setModel(const DenseThreeDimensionalModel *model); + void setModel(ModelId model); // a DenseThreeDimensionalModel - int getCompletion(LayerGeometryProvider *) const override { return m_model->getCompletion(); } + int getCompletion(LayerGeometryProvider *) const override; PropertyList getProperties() const override; PropertyType getPropertyType(const PropertyName &) const override; @@ -80,11 +85,11 @@ QString getPropertyIconName(const PropertyName &) const override; QString getPropertyGroupName(const PropertyName &) const override; int getPropertyRangeAndValue(const PropertyName &, - int *min, int *max, int *deflt) const override; + int *min, int *max, int *deflt) const override; QString getPropertyValueLabel(const PropertyName &, - int value) const override; + int value) const override; QString getPropertyValueIconName(const PropertyName &, - int value) const override; + int value) const override; RangeMapper *getNewPropertyRangeMapper(const PropertyName &) const override; void setProperty(const PropertyName &, int value) override; void setProperties(const QXmlAttributes &) override; @@ -132,30 +137,30 @@ bool hasLightBackground() const override; bool getValueExtents(double &min, double &max, - bool &logarithmic, QString &unit) const override; + bool &logarithmic, QString &unit) const override; bool getDisplayExtents(double &min, double &max) const override; bool setDisplayExtents(double min, double max) override; bool getYScaleValue(const LayerGeometryProvider *, int /* y */, - double &/* value */, QString &/* unit */) const override; + double &/* value */, QString &/* unit */) const override; int getVerticalZoomSteps(int &defaultStep) const override; int getCurrentVerticalZoomStep() const override; void setVerticalZoomStep(int) override; RangeMapper *getNewVerticalZoomRangeMapper() const override; - const Model *getSliceableModel() const override { return m_model; } + ModelId getSliceableModel() const override { return m_model; } void toXml(QTextStream &stream, QString indent = "", - QString extraAttributes = "") const override; + QString extraAttributes = "") const override; protected slots: - void handleModelChanged(); - void handleModelChangedWithin(sv_frame_t, sv_frame_t); + void handleModelChanged(ModelId); + void handleModelChangedWithin(ModelId, sv_frame_t, sv_frame_t); protected: - const DenseThreeDimensionalModel *m_model; // I do not own this + ModelId m_model; // A DenseThreeDimensionalModel ColourScaleType m_colourScale; bool m_colourScaleSet; @@ -182,10 +187,10 @@ static std::pair convertToColumnNorm(int value); static int convertFromColumnNorm(ColumnNormalization norm, bool visible); - mutable Dense3DModelPeakCache *m_peakCache; + mutable ModelId m_peakCache; const int m_peakCacheDivisor; - Dense3DModelPeakCache *getPeakCache() const; void invalidatePeakCache(); + ModelId getPeakCache() const; typedef std::map ViewMagMap; // key is view id mutable ViewMagMap m_viewMags; diff -r de41a11cabc2 -r ac0a8addabcf layer/Colour3DPlotRenderer.cpp --- a/layer/Colour3DPlotRenderer.cpp Thu Jun 13 15:35:01 2019 +0100 +++ b/layer/Colour3DPlotRenderer.cpp Wed Jul 17 14:25:16 2019 +0100 @@ -334,7 +334,7 @@ Colour3DPlotRenderer::RenderType Colour3DPlotRenderer::decideRenderType(const LayerGeometryProvider *v) const { - const DenseThreeDimensionalModel *model = m_sources.source; + auto model = ModelById::getAs(m_sources.source); if (!model || !v || !(v->getViewManager())) { return DrawBufferPixelResolution; // or anything } @@ -398,7 +398,7 @@ } if (m_params.colourScale.getScale() == ColourScaleType::Phase && - m_sources.fft) { + !m_sources.fft.isNone()) { return column; } else { column = ColumnOp::applyGain(column, m_params.scaleFactor); @@ -414,27 +414,36 @@ Profiler profiler("Colour3DPlotRenderer::getColumn"); ColumnOp::Column column; + ColumnOp::Column fullColumn; - if (m_params.colourScale.getScale() == ColourScaleType::Phase && - m_sources.fft) { - - ColumnOp::Column fullColumn = m_sources.fft->getPhases(sx); - - column = vector(fullColumn.data() + minbin, - fullColumn.data() + minbin + nbins); - - } else { - - ColumnOp::Column fullColumn = - (peakCacheIndex >= 0 ? - m_sources.peakCaches[peakCacheIndex] : - m_sources.source) - ->getColumn(sx); - - column = vector(fullColumn.data() + minbin, - fullColumn.data() + minbin + nbins); + if (m_params.colourScale.getScale() == ColourScaleType::Phase) { + auto fftModel = ModelById::getAs(m_sources.fft); + if (fftModel) { + fullColumn = fftModel->getPhases(sx); + } } + if (fullColumn.empty()) { + + if (peakCacheIndex >= 0) { + auto peakCache = ModelById::getAs + (m_sources.peakCaches[peakCacheIndex]); + if (!peakCache) { + return vector(nbins, 0.f); + } + fullColumn = peakCache->getColumn(sx); + } else { + auto model = ModelById::getAs + (m_sources.source); + if (!model) { + return vector(nbins, 0.f); + } + fullColumn = model->getColumn(sx); + } + } + + column = vector(fullColumn.data() + minbin, + fullColumn.data() + minbin + nbins); return column; } @@ -451,7 +460,8 @@ bool illuminate = v->shouldIlluminateLocalFeatures (m_sources.verticalBinLayer, illuminatePos); - const DenseThreeDimensionalModel *model = m_sources.source; + auto model = ModelById::getAs(m_sources.source); + if (!model) return magRange; int x0 = rect.left(); int x1 = rect.right() + 1; @@ -526,6 +536,11 @@ int rw = rx1 - rx0; if (rw < 1) rw = 1; + // 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" + bool showLabel = (rw > 10 && paint.fontMetrics().width("0.000000") < rw - 3 && paint.fontMetrics().height() < (h / sh)); @@ -602,7 +617,7 @@ peakCacheIndex = -1; binsPerPeak = -1; - const DenseThreeDimensionalModel *model = m_sources.source; + auto model = ModelById::getAs(m_sources.source); if (!model) return; if (m_params.binDisplay == BinDisplay::PeakFrequencies) return; if (m_params.colourScale.getScale() == ColourScaleType::Phase) return; @@ -611,7 +626,10 @@ int binResolution = model->getResolution(); for (int ix = 0; in_range_for(m_sources.peakCaches, ix); ++ix) { - int bpp = m_sources.peakCaches[ix]->getColumnsPerPeak(); + auto peakCache = ModelById::getAs + (m_sources.peakCaches[ix]); + if (!peakCache) continue; + int bpp = peakCache->getColumnsPerPeak(); ZoomLevel equivZoom(ZoomLevel::FramesPerPixel, binResolution * bpp); #ifdef DEBUG_COLOUR_PLOT_REPAINT SVDEBUG << "getPreferredPeakCache: zoomLevel = " << zoomLevel @@ -653,10 +671,8 @@ // buffer is at the same resolution as the target in the cache, so // no extra scaling needed. - const DenseThreeDimensionalModel *model = m_sources.source; - if (!model || !model->isOK() || !model->isReady()) { - throw std::logic_error("no source model provided, or model not ready"); - } + auto model = ModelById::getAs(m_sources.source); + if (!model) return; int h = v->getPaintHeight(); @@ -794,10 +810,8 @@ // buffer is at bin resolution, i.e. buffer x == source column // number. We use toolkit smooth scaling for interpolation. - const DenseThreeDimensionalModel *model = m_sources.source; - if (!model || !model->isOK() || !model->isReady()) { - throw std::logic_error("no source model provided, or model not ready"); - } + auto model = ModelById::getAs(m_sources.source); + if (!model) return; // The draw buffer will contain a fragment at bin resolution. We // need to ensure that it starts and ends at points where a @@ -950,12 +964,25 @@ Profiler profiler("Colour3DPlotRenderer::renderDrawBuffer"); int divisor = 1; - const DenseThreeDimensionalModel *sourceModel = m_sources.source; + + std::shared_ptr sourceModel; + if (peakCacheIndex >= 0) { - divisor = m_sources.peakCaches[peakCacheIndex]->getColumnsPerPeak(); - sourceModel = m_sources.peakCaches[peakCacheIndex]; + auto peakCache = ModelById::getAs + (m_sources.peakCaches[peakCacheIndex]); + if (peakCache) { + divisor = peakCache->getColumnsPerPeak(); + sourceModel = peakCache; + } } + if (!sourceModel) { + sourceModel = ModelById::getAs + (m_sources.source); + } + + if (!sourceModel) return 0; + #ifdef DEBUG_COLOUR_PLOT_REPAINT SVDEBUG << "renderDrawBuffer: w = " << w << ", h = " << h << ", peakCacheIndex = " << peakCacheIndex << " (divisor = " @@ -1125,7 +1152,8 @@ RenderTimer::SlowRender : RenderTimer::NoTimeout); - const FFTModel *fft = m_sources.fft; + auto fft = ModelById::getAs(m_sources.fft); + if (!fft) return 0; int sh = fft->getHeight(); diff -r de41a11cabc2 -r ac0a8addabcf layer/Colour3DPlotRenderer.h --- a/layer/Colour3DPlotRenderer.h Thu Jun 13 15:35:01 2019 +0100 +++ b/layer/Colour3DPlotRenderer.h Wed Jul 17 14:25:16 2019 +0100 @@ -23,16 +23,16 @@ #include "base/ColumnOp.h" #include "base/MagnitudeRange.h" +#include "data/model/Model.h" + #include #include #include class LayerGeometryProvider; class VerticalBinLayer; -class DenseThreeDimensionalModel; +class RenderTimer; class Dense3DModelPeakCache; -class FFTModel; -class RenderTimer; enum class BinDisplay { AllBins, @@ -49,13 +49,13 @@ { public: struct Sources { - Sources() : verticalBinLayer(0), source(0), fft(0) { } + Sources() : verticalBinLayer(0) { } // These must all outlive this class - const VerticalBinLayer *verticalBinLayer; // always - const DenseThreeDimensionalModel *source; // always - const FFTModel *fft; // optionally - std::vector peakCaches; // zero or more + const VerticalBinLayer *verticalBinLayer; // always + ModelId source; // always; a DenseThreeDimensionalModel + ModelId fft; // optionally; an FFTModel; used for phase/peak-freq modes + std::vector peakCaches; // zero or more }; struct Parameters { diff -r de41a11cabc2 -r ac0a8addabcf layer/FlexiNoteLayer.cpp --- a/layer/FlexiNoteLayer.cpp Thu Jun 13 15:35:01 2019 +0100 +++ b/layer/FlexiNoteLayer.cpp Wed Jul 17 14:25:16 2019 +0100 @@ -53,7 +53,6 @@ FlexiNoteLayer::FlexiNoteLayer() : SingleColourLayer(), - m_model(nullptr), m_editing(false), m_intelligentActions(true), m_dragPointX(0), @@ -73,15 +72,20 @@ } void -FlexiNoteLayer::setModel(NoteModel *model) +FlexiNoteLayer::setModel(ModelId modelId) { - if (m_model == model) return; - m_model = model; + auto newModel = ModelById::getAs(modelId); + + if (!modelId.isNone() && !newModel) { + throw std::logic_error("Not a NoteModel"); + } + + if (m_model == modelId) return; + m_model = modelId; - connectSignals(m_model); - - // m_scaleMinimum = 0; - // m_scaleMaximum = 0; + if (newModel) { + connectSignals(m_model); + } emit modelReplaced(); } @@ -123,7 +127,8 @@ QString FlexiNoteLayer::getScaleUnits() const { - if (m_model) return m_model->getScaleUnits(); + auto model = ModelById::getAs(m_model); + if (model) return model->getScaleUnits(); else return ""; } @@ -144,7 +149,8 @@ } else if (name == "Scale Units") { if (deflt) *deflt = 0; - if (m_model) { + auto model = ModelById::getAs(m_model); + if (model) { val = UnitDatabase::getInstance()->getUnitId (getScaleUnits()); } @@ -179,10 +185,11 @@ if (name == "Vertical Scale") { setVerticalScale(VerticalScale(value)); } else if (name == "Scale Units") { - if (m_model) { - m_model->setScaleUnits + auto model = ModelById::getAs(m_model); + if (model) { + model->setScaleUnits (UnitDatabase::getInstance()->getUnitById(value)); - emit modelChanged(); + emit modelChanged(m_model); } } else { return SingleColourLayer::setProperty(name, value); @@ -215,13 +222,22 @@ // return false; } +int +FlexiNoteLayer::getCompletion(LayerGeometryProvider *) const +{ + auto model = ModelById::get(m_model); + if (model) return model->getCompletion(); + else return 0; +} + bool FlexiNoteLayer::getValueExtents(double &min, double &max, bool &logarithmic, QString &unit) const { - if (!m_model) return false; - min = m_model->getValueMinimum(); - max = m_model->getValueMaximum(); + auto model = ModelById::getAs(m_model); + if (!model) return false; + min = model->getValueMinimum(); + max = model->getValueMaximum(); if (shouldConvertMIDIToHz()) { unit = "Hz"; @@ -238,7 +254,8 @@ bool FlexiNoteLayer::getDisplayExtents(double &min, double &max) const { - if (!m_model || shouldAutoAlign()) { + auto model = ModelById::getAs(m_model); + if (!model || shouldAutoAlign()) { // std::cerr << "No model or shouldAutoAlign()" << std::endl; return false; } @@ -250,8 +267,8 @@ } if (m_scaleMinimum == m_scaleMaximum) { - min = m_model->getValueMinimum(); - max = m_model->getValueMaximum(); + min = model->getValueMinimum(); + max = model->getValueMaximum(); } else { min = m_scaleMinimum; max = m_scaleMaximum; @@ -272,7 +289,8 @@ bool FlexiNoteLayer::setDisplayExtents(double min, double max) { - if (!m_model) return false; + auto model = ModelById::getAs(m_model); + if (!model) return false; if (min == max) { if (min == 0.f) { @@ -297,7 +315,8 @@ FlexiNoteLayer::getVerticalZoomSteps(int &defaultStep) const { if (shouldAutoAlign()) return 0; - if (!m_model) return 0; + auto model = ModelById::getAs(m_model); + if (!model) return 0; defaultStep = 0; return 100; @@ -307,7 +326,8 @@ FlexiNoteLayer::getCurrentVerticalZoomStep() const { if (shouldAutoAlign()) return 0; - if (!m_model) return 0; + auto model = ModelById::getAs(m_model); + if (!model) return 0; RangeMapper *mapper = getNewVerticalZoomRangeMapper(); if (!mapper) return 0; @@ -328,7 +348,8 @@ FlexiNoteLayer::setVerticalZoomStep(int step) { if (shouldAutoAlign()) return; - if (!m_model) return; + auto model = ModelById::getAs(m_model); + if (!model) return; RangeMapper *mapper = getNewVerticalZoomRangeMapper(); if (!mapper) return; @@ -378,7 +399,8 @@ RangeMapper * FlexiNoteLayer::getNewVerticalZoomRangeMapper() const { - if (!m_model) return nullptr; + auto model = ModelById::getAs(m_model); + if (!model) return nullptr; RangeMapper *mapper; @@ -401,21 +423,22 @@ EventVector FlexiNoteLayer::getLocalPoints(LayerGeometryProvider *v, int x) const { - if (!m_model) return {}; + auto model = ModelById::getAs(m_model); + if (!model) return {}; sv_frame_t frame = v->getFrameForX(x); - EventVector local = m_model->getEventsCovering(frame); + EventVector local = model->getEventsCovering(frame); if (!local.empty()) return local; int fuzz = ViewManager::scalePixelSize(2); sv_frame_t start = v->getFrameForX(x - fuzz); sv_frame_t end = v->getFrameForX(x + fuzz); - local = m_model->getEventsStartingWithin(frame, end - frame); + local = model->getEventsStartingWithin(frame, end - frame); if (!local.empty()) return local; - local = m_model->getEventsSpanning(start, frame - start); + local = model->getEventsSpanning(start, frame - start); if (!local.empty()) return local; return {}; @@ -424,11 +447,12 @@ bool FlexiNoteLayer::getPointToDrag(LayerGeometryProvider *v, int x, int y, Event &point) const { - if (!m_model) return false; + auto model = ModelById::getAs(m_model); + if (!model) return false; sv_frame_t frame = v->getFrameForX(x); - EventVector onPoints = m_model->getEventsCovering(frame); + EventVector onPoints = model->getEventsCovering(frame); if (onPoints.empty()) return false; int nearestDistance = -1; @@ -448,11 +472,12 @@ FlexiNoteLayer::getNoteToEdit(LayerGeometryProvider *v, int x, int y, Event &point) const { // GF: find the note that is closest to the cursor - if (!m_model) return false; + auto model = ModelById::getAs(m_model); + if (!model) return false; sv_frame_t frame = v->getFrameForX(x); - EventVector onPoints = m_model->getEventsCovering(frame); + EventVector onPoints = model->getEventsCovering(frame); if (onPoints.empty()) return false; int nearestDistance = -1; @@ -473,12 +498,13 @@ { int x = pos.x(); - if (!m_model || !m_model->getSampleRate()) return ""; + auto model = ModelById::getAs(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"); @@ -493,9 +519,9 @@ int y = getYForValue(v, i->getValue()); int h = NOTE_HEIGHT; // GF: larger notes - if (m_model->getValueQuantization() != 0.0) { + if (model->getValueQuantization() != 0.0) { h = y - getYForValue - (v, i->getValue() + m_model->getValueQuantization()); + (v, i->getValue() + model->getValueQuantization()); if (h < NOTE_HEIGHT) h = NOTE_HEIGHT; } @@ -509,9 +535,9 @@ if (i == points.end()) return tr("No local points"); RealTime rt = RealTime::frame2RealTime(note.getFrame(), - m_model->getSampleRate()); + model->getSampleRate()); RealTime rd = RealTime::frame2RealTime(note.getDuration(), - m_model->getSampleRate()); + model->getSampleRate()); QString pitchText; @@ -562,11 +588,12 @@ int &resolution, SnapType snap) const { - if (!m_model) { + auto model = ModelById::getAs(m_model); + if (!model) { return Layer::snapToFeatureFrame(v, frame, resolution, snap); } - resolution = m_model->getResolution(); + resolution = model->getResolution(); EventVector points; if (snap == SnapNeighbouring) { @@ -577,7 +604,7 @@ return true; } - points = m_model->getEventsCovering(frame); + points = model->getEventsCovering(frame); sv_frame_t snapped = frame; bool found = false; @@ -650,8 +677,9 @@ if (!v->getValueExtents(queryUnits, min, max, log)) { - min = m_model->getValueMinimum(); - max = m_model->getValueMaximum(); + auto model = ModelById::getAs(m_model); + min = model->getValueMinimum(); + max = model->getValueMaximum(); if (shouldConvertMIDIToHz()) { min = Pitch::getFrequencyForPitch(int(lrint(min))); @@ -752,16 +780,16 @@ bool FlexiNoteLayer::shouldAutoAlign() const { - if (!m_model) return false; return (m_verticalScale == AutoAlignScale); } void FlexiNoteLayer::paint(LayerGeometryProvider *v, QPainter &paint, QRect rect) const { - if (!m_model || !m_model->isOK()) return; + auto model = ModelById::getAs(m_model); + if (!model || !model->isOK()) return; - sv_samplerate_t sampleRate = m_model->getSampleRate(); + sv_samplerate_t sampleRate = model->getSampleRate(); if (!sampleRate) return; // Profiler profiler("FlexiNoteLayer::paint", true); @@ -770,7 +798,7 @@ sv_frame_t frame0 = v->getFrameForX(x0); sv_frame_t frame1 = v->getFrameForX(x1); - EventVector points(m_model->getEventsSpanning(frame0, frame1 - frame0)); + EventVector points(model->getEventsSpanning(frame0, frame1 - frame0)); if (points.empty()) return; paint.setPen(getBaseQColor()); @@ -779,10 +807,10 @@ brushColour.setAlpha(80); // SVDEBUG << "FlexiNoteLayer::paint: resolution is " -// << m_model->getResolution() << " frames" << endl; +// << model->getResolution() << " frames" << endl; - 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; QPoint localPos; @@ -810,8 +838,8 @@ int w = v->getXForFrame(p.getFrame() + p.getDuration()) - x; int h = NOTE_HEIGHT; //GF: larger notes - if (m_model->getValueQuantization() != 0.0) { - h = y - getYForValue(v, p.getValue() + m_model->getValueQuantization()); + if (model->getValueQuantization() != 0.0) { + h = y - getYForValue(v, p.getValue() + model->getValueQuantization()); if (h < NOTE_HEIGHT) h = NOTE_HEIGHT; //GF: larger notes } @@ -827,7 +855,7 @@ paint.setPen(v->getForeground()); QString vlabel = tr("freq: %1%2") - .arg(p.getValue()).arg(m_model->getScaleUnits()); + .arg(p.getValue()).arg(model->getScaleUnits()); PaintAssistant::drawVisibleText (v, paint, x, @@ -837,7 +865,7 @@ QString hlabel = tr("dur: %1") .arg(RealTime::frame2RealTime - (p.getDuration(), m_model->getSampleRate()).toText(true) + (p.getDuration(), model->getSampleRate()).toText(true) .c_str()); PaintAssistant::drawVisibleText (v, paint, @@ -869,7 +897,7 @@ int FlexiNoteLayer::getVerticalScaleWidth(LayerGeometryProvider *v, bool, QPainter &paint) const { - if (!m_model || shouldAutoAlign()) { + if (shouldAutoAlign()) { return 0; } else { if (m_verticalScale == LogScale || m_verticalScale == MIDIRangeScale) { @@ -883,7 +911,8 @@ void FlexiNoteLayer::paintVerticalScale(LayerGeometryProvider *v, bool, QPainter &paint, QRect) const { - if (!m_model || m_model->isEmpty()) return; + auto model = ModelById::getAs(m_model); + if (!model || model->isEmpty()) return; QString unit; double min, max; @@ -923,11 +952,12 @@ { // SVDEBUG << "FlexiNoteLayer::drawStart(" << e->x() << "," << e->y() << ")" << endl; - if (!m_model) return; + auto model = ModelById::getAs(m_model); + if (!model) 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()); @@ -935,7 +965,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")); m_editingCommand->add(m_editingPoint); m_editing = true; @@ -946,11 +976,12 @@ { // SVDEBUG << "FlexiNoteLayer::drawDrag(" << e->x() << "," << e->y() << ")" << endl; - if (!m_model || !m_editing) return; + auto model = ModelById::getAs(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 newValue = getValueForY(v, e->y()); @@ -975,7 +1006,8 @@ FlexiNoteLayer::drawEnd(LayerGeometryProvider *, QMouseEvent *) { // SVDEBUG << "FlexiNoteLayer::drawEnd(" << e->x() << "," << e->y() << ")" << endl; - if (!m_model || !m_editing) return; + auto model = ModelById::getAs(m_model); + if (!model || !m_editing) return; finish(m_editingCommand); m_editingCommand = nullptr; m_editing = false; @@ -984,7 +1016,8 @@ void FlexiNoteLayer::eraseStart(LayerGeometryProvider *v, QMouseEvent *e) { - if (!m_model) return; + auto model = ModelById::getAs(m_model); + if (!model) return; if (!getPointToDrag(v, e->x(), e->y(), m_editingPoint)) return; @@ -1004,15 +1037,15 @@ void FlexiNoteLayer::eraseEnd(LayerGeometryProvider *v, QMouseEvent *e) { - if (!m_model || !m_editing) return; - + if (!m_editing) return; m_editing = false; Event p(0); if (!getPointToDrag(v, e->x(), e->y(), p)) return; - if (p.getFrame() != m_editingPoint.getFrame() || p.getValue() != m_editingPoint.getValue()) return; + if (p.getFrame() != m_editingPoint.getFrame() || + p.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; @@ -1025,7 +1058,8 @@ // SVDEBUG << "FlexiNoteLayer::editStart(" << e->x() << "," << e->y() << ")" << endl; std::cerr << "FlexiNoteLayer::editStart(" << e->x() << "," << e->y() << ")" << std::endl; - if (!m_model) return; + auto model = ModelById::getAs(m_model); + if (!model) return; if (!getPointToDrag(v, e->x(), e->y(), m_editingPoint)) return; m_originalPoint = m_editingPoint; @@ -1056,7 +1090,7 @@ m_greatestLeftNeighbourFrame = -1; m_smallestRightNeighbourFrame = std::numeric_limits::max(); - EventVector allEvents = m_model->getAllEvents(); + EventVector allEvents = model->getAllEvents(); for (auto currentNote: allEvents) { @@ -1082,7 +1116,8 @@ // SVDEBUG << "FlexiNoteLayer::editDrag(" << e->x() << "," << e->y() << ")" << endl; std::cerr << "FlexiNoteLayer::editDrag(" << e->x() << "," << e->y() << ")" << std::endl; - if (!m_model || !m_editing) return; + auto model = ModelById::getAs(m_model); + if (!model || !m_editing) return; int xdist = e->x() - m_dragStartX; int ydist = e->y() - m_dragStartY; @@ -1091,12 +1126,13 @@ sv_frame_t dragFrame = v->getFrameForX(newx); if (dragFrame < 0) dragFrame = 0; - dragFrame = dragFrame / m_model->getResolution() * m_model->getResolution(); + dragFrame = dragFrame / model->getResolution() * model->getResolution(); double value = getValueForY(v, newy); 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); @@ -1182,7 +1218,8 @@ std::cerr << "FlexiNoteLayer::editEnd(" << e->x() << "," << e->y() << ")" << std::endl; - if (!m_model || !m_editing) return; + auto model = ModelById::getAs(m_model); + if (!model || !m_editing) return; if (m_editingCommand) { @@ -1218,9 +1255,11 @@ void FlexiNoteLayer::splitStart(LayerGeometryProvider *v, QMouseEvent *e) { + auto model = ModelById::getAs(m_model); + if (!model) return; + // GF: note splitting starts (!! remove printing soon) std::cerr << "splitStart (n.b. editStart will be called later, if the user drags the mouse)" << std::endl; - if (!m_model) return; if (!getPointToDrag(v, e->x(), e->y(), m_editingPoint)) return; // m_originalPoint = m_editingPoint; @@ -1241,9 +1280,10 @@ void FlexiNoteLayer::splitEnd(LayerGeometryProvider *v, QMouseEvent *e) { + auto model = ModelById::getAs(m_model); // GF: note splitting ends. (!! remove printing soon) std::cerr << "splitEnd" << std::endl; - if (!m_model || !m_editing || m_editMode != SplitNote) return; + if (!model || !m_editing || m_editMode != SplitNote) return; int xdist = e->x() - m_dragStartX; int ydist = e->y() - m_dragStartY; @@ -1266,13 +1306,15 @@ void FlexiNoteLayer::splitNotesAt(LayerGeometryProvider *v, sv_frame_t frame, QMouseEvent *e) { - EventVector onPoints = m_model->getEventsCovering(frame); + auto model = ModelById::getAs(m_model); + if (!model) return; + + EventVector onPoints = model->getEventsCovering(frame); if (onPoints.empty()) return; Event note(*onPoints.begin()); - ChangeEventsCommand *command = new ChangeEventsCommand - (m_model, tr("Edit Point")); + auto command = new ChangeEventsCommand(m_model.untyped, tr("Edit Point")); command->remove(note); if (!e || !(e->modifiers() & Qt::ShiftModifier)) { @@ -1306,15 +1348,16 @@ void FlexiNoteLayer::addNote(LayerGeometryProvider *v, QMouseEvent *e) { + auto model = ModelById::getAs(m_model); std::cerr << "addNote" << std::endl; - if (!m_model) return; + if (!model) return; sv_frame_t duration = 10000; sv_frame_t frame = v->getFrameForX(e->x()); double value = getValueForY(v, e->y()); - EventVector noteList = m_model->getAllEvents(); + EventVector noteList = model->getAllEvents(); if (m_intelligentActions) { sv_frame_t smallestRightNeighbourFrame = 0; @@ -1333,16 +1376,15 @@ } if (!m_intelligentActions || - (m_model->getEventsCovering(frame).empty() && duration > 0)) { + (model->getEventsCovering(frame).empty() && duration > 0)) { Event newNote(frame, float(value), duration, 100.f, tr("new note")); - ChangeEventsCommand *command = new ChangeEventsCommand - (m_model, tr("Add Point")); + auto command = new ChangeEventsCommand(m_model.untyped, tr("Add Point")); command->add(newNote); finish(command); } } -SparseTimeValueModel * +ModelId FlexiNoteLayer::getAssociatedPitchModel(LayerGeometryProvider *v) const { // Better than we used to do, but still not very satisfactory @@ -1354,29 +1396,28 @@ if (layer && layer->getLayerPresentationName() != "candidate") { // cerr << "FlexiNoteLayer::getAssociatedPitchModel: looks like our layer is " << layer << endl; - SparseTimeValueModel *model = qobject_cast - (layer->getModel()); -// cerr << "FlexiNoteLayer::getAssociatedPitchModel: and its model is " << model << endl; + auto modelId = layer->getModel(); + auto model = ModelById::getAs(modelId); if (model && model->getScaleUnits() == "Hz") { - cerr << "FlexiNoteLayer::getAssociatedPitchModel: it's good, returning " << model << endl; - return model; +// cerr << "FlexiNoteLayer::getAssociatedPitchModel: it's good, returning " << model << endl; + return modelId; } } } - cerr << "FlexiNoteLayer::getAssociatedPitchModel: failed to find a model" << endl; - return nullptr; +// cerr << "FlexiNoteLayer::getAssociatedPitchModel: failed to find a model" << endl; + return {}; } void FlexiNoteLayer::snapSelectedNotesToPitchTrack(LayerGeometryProvider *v, Selection s) { - if (!m_model) return; + auto model = ModelById::getAs(m_model); + if (!model) return; EventVector points = - m_model->getEventsStartingWithin(s.getStartFrame(), s.getDuration()); + model->getEventsStartingWithin(s.getStartFrame(), s.getDuration()); - ChangeEventsCommand *command = new ChangeEventsCommand - (m_model, tr("Snap Notes")); + auto command = new ChangeEventsCommand(m_model.untyped, tr("Snap Notes")); cerr << "snapSelectedNotesToPitchTrack: selection is from " << s.getStartFrame() << " to " << s.getEndFrame() << endl; @@ -1408,18 +1449,20 @@ void FlexiNoteLayer::mergeNotes(LayerGeometryProvider *v, Selection s, bool inclusive) { + auto model = ModelById::getAs(m_model); + if (!model) return; + EventVector points; if (inclusive) { - points = m_model->getEventsSpanning(s.getStartFrame(), s.getDuration()); + points = model->getEventsSpanning(s.getStartFrame(), s.getDuration()); } else { - points = m_model->getEventsWithin(s.getStartFrame(), s.getDuration()); + points = model->getEventsWithin(s.getStartFrame(), s.getDuration()); } EventVector::iterator i = points.begin(); if (i == points.end()) return; - ChangeEventsCommand *command = - new ChangeEventsCommand(m_model, tr("Merge Notes")); + auto command = new ChangeEventsCommand(m_model.untyped, tr("Merge Notes")); Event newNote(*i); @@ -1446,7 +1489,8 @@ bool FlexiNoteLayer::updateNoteValueFromPitchCurve(LayerGeometryProvider *v, Event ¬e) const { - SparseTimeValueModel *model = getAssociatedPitchModel(v); + ModelId modelId = getAssociatedPitchModel(v); + auto model = ModelById::getAs(modelId); if (!model) return false; std::cerr << model->getTypeName() << std::endl; @@ -1525,8 +1569,7 @@ void FlexiNoteLayer::getRelativeMousePosition(LayerGeometryProvider *v, Event ¬e, int x, int y, bool &closeToLeft, bool &closeToRight, bool &closeToTop, bool &closeToBottom) const { - // GF: TODO: consoloidate the tolerance values - if (!m_model) return; + // GF: TODO: consolidate the tolerance values int ctol = 0; int noteStartX = v->getXForFrame(note.getFrame()); @@ -1555,7 +1598,8 @@ FlexiNoteLayer::editOpen(LayerGeometryProvider *v, QMouseEvent *e) { std::cerr << "Opening note editor dialog" << std::endl; - if (!m_model) return false; + auto model = ModelById::getAs(m_model); + if (!model) return false; Event note(0); if (!getPointToDrag(v, e->x(), e->y(), note)) return false; @@ -1563,7 +1607,7 @@ // Event note = *points.begin(); ItemEditDialog *dialog = new ItemEditDialog - (m_model->getSampleRate(), + (model->getSampleRate(), ItemEditDialog::ShowTime | ItemEditDialog::ShowDuration | ItemEditDialog::ShowValue | @@ -1583,8 +1627,7 @@ .withDuration(dialog->getFrameDuration()) .withLabel(dialog->getText()); - ChangeEventsCommand *command = new ChangeEventsCommand - (m_model, tr("Edit Point")); + auto command = new ChangeEventsCommand(m_model.untyped, tr("Edit Point")); command->remove(note); command->add(newNote); finish(command); @@ -1597,13 +1640,13 @@ void FlexiNoteLayer::moveSelection(Selection s, sv_frame_t newStartFrame) { - if (!m_model) return; - - ChangeEventsCommand *command = - new ChangeEventsCommand(m_model, tr("Drag Selection")); + auto model = ModelById::getAs(m_model); + if (!model) return; + + auto command = new ChangeEventsCommand(m_model.untyped, tr("Drag Selection")); EventVector points = - m_model->getEventsStartingWithin(s.getStartFrame(), s.getDuration()); + model->getEventsStartingWithin(s.getStartFrame(), s.getDuration()); for (Event p: points) { command->remove(p); @@ -1618,13 +1661,13 @@ void FlexiNoteLayer::resizeSelection(Selection s, Selection newSize) { - if (!m_model || !s.getDuration()) return; + auto model = ModelById::getAs(m_model); + if (!model || !s.getDuration()) return; - ChangeEventsCommand *command = - new ChangeEventsCommand(m_model, tr("Resize Selection")); + auto command = new ChangeEventsCommand(m_model.untyped, tr("Resize Selection")); EventVector points = - m_model->getEventsStartingWithin(s.getStartFrame(), s.getDuration()); + model->getEventsStartingWithin(s.getStartFrame(), s.getDuration()); double ratio = double(newSize.getDuration()) / double(s.getDuration()); double oldStart = double(s.getStartFrame()); @@ -1648,13 +1691,14 @@ void FlexiNoteLayer::deleteSelection(Selection s) { - if (!m_model) return; + auto model = ModelById::getAs(m_model); + if (!model) return; - ChangeEventsCommand *command = - new ChangeEventsCommand(m_model, tr("Delete Selected Points")); + auto command = + new ChangeEventsCommand(m_model.untyped, tr("Delete Selected Points")); EventVector points = - m_model->getEventsStartingWithin(s.getStartFrame(), s.getDuration()); + model->getEventsStartingWithin(s.getStartFrame(), s.getDuration()); for (Event p: points) { command->remove(p); @@ -1666,13 +1710,14 @@ void FlexiNoteLayer::deleteSelectionInclusive(Selection s) { - if (!m_model) return; + auto model = ModelById::getAs(m_model); + if (!model) return; - ChangeEventsCommand *command = - new ChangeEventsCommand(m_model, tr("Delete Selected Points")); + auto command = + new ChangeEventsCommand(m_model.untyped, tr("Delete Selected Points")); EventVector points = - m_model->getEventsSpanning(s.getStartFrame(), s.getDuration()); + model->getEventsSpanning(s.getStartFrame(), s.getDuration()); for (Event p: points) { command->remove(p); @@ -1684,10 +1729,11 @@ void FlexiNoteLayer::copy(LayerGeometryProvider *v, Selection s, Clipboard &to) { - if (!m_model) return; + auto model = ModelById::getAs(m_model); + if (!model) return; EventVector points = - m_model->getEventsStartingWithin(s.getStartFrame(), s.getDuration()); + model->getEventsStartingWithin(s.getStartFrame(), s.getDuration()); for (Event p: points) { to.addPoint(p.withReferenceFrame(alignToReference(v, p.getFrame()))); @@ -1697,7 +1743,8 @@ bool FlexiNoteLayer::paste(LayerGeometryProvider *v, const Clipboard &from, sv_frame_t /*frameOffset */, bool /* interactive */) { - if (!m_model) return false; + auto model = ModelById::getAs(m_model); + if (!model) return false; const EventVector &points = from.getPoints(); @@ -1720,8 +1767,7 @@ } } - ChangeEventsCommand *command = - new ChangeEventsCommand(m_model, tr("Paste")); + auto command = new ChangeEventsCommand(m_model.untyped, tr("Paste")); for (EventVector::const_iterator i = points.begin(); i != points.end(); ++i) { @@ -1745,8 +1791,8 @@ Event p = *i; Event newPoint = p; if (!p.hasValue()) { - newPoint = newPoint.withValue((m_model->getValueMinimum() + - m_model->getValueMaximum()) / 2); + newPoint = newPoint.withValue((model->getValueMinimum() + + model->getValueMaximum()) / 2); } if (!p.hasDuration()) { sv_frame_t nextFrame = frame; @@ -1758,7 +1804,7 @@ nextFrame = j->getFrame(); } if (nextFrame == frame) { - newPoint = newPoint.withDuration(m_model->getResolution()); + newPoint = newPoint.withDuration(model->getResolution()); } else { newPoint = newPoint.withDuration(nextFrame - frame); } @@ -1789,13 +1835,11 @@ if (lrintf(p.getValue()) == pitch) { m_pendingNoteOns.erase(i); Event note = p.withDuration(frame - p.getFrame()); - if (m_model) { - ChangeEventsCommand *c = new ChangeEventsCommand - (m_model, tr("Record Note")); - c->add(note); - // execute and bundle: - CommandHistory::getInstance()->addCommand(c, true, true); - } + auto c = new ChangeEventsCommand + (m_model.untyped, tr("Record Note")); + c->add(note); + // execute and bundle: + CommandHistory::getInstance()->addCommand(c, true, true); break; } } @@ -1840,10 +1884,13 @@ void FlexiNoteLayer::setVerticalRangeToNoteRange(LayerGeometryProvider *v) { + auto model = ModelById::getAs(m_model); + if (!model) return; + double minf = std::numeric_limits::max(); double maxf = 0; bool hasNotes = 0; - EventVector allPoints = m_model->getAllEvents(); + EventVector allPoints = model->getAllEvents(); for (EventVector::const_iterator i = allPoints.begin(); i != allPoints.end(); ++i) { hasNotes = 1; diff -r de41a11cabc2 -r ac0a8addabcf layer/FlexiNoteLayer.h --- a/layer/FlexiNoteLayer.h Thu Jun 13 15:35:01 2019 +0100 +++ b/layer/FlexiNoteLayer.h Wed Jul 17 14:25:16 2019 +0100 @@ -81,8 +81,8 @@ void snapSelectedNotesToPitchTrack(LayerGeometryProvider *v, Selection s); void mergeNotes(LayerGeometryProvider *v, Selection s, bool inclusive); - const Model *getModel() const override { return m_model; } - void setModel(NoteModel *model); + ModelId getModel() const override { return m_model; } + void setModel(ModelId model); // a NoteModel please PropertyList getProperties() const override; QString getPropertyLabel(const PropertyName &) const override; @@ -118,10 +118,10 @@ bool isLayerEditable() const override { return true; } - int getCompletion(LayerGeometryProvider *) const override { return m_model->getCompletion(); } + int getCompletion(LayerGeometryProvider *) const override; bool getValueExtents(double &min, double &max, - bool &log, QString &unit) const override; + bool &log, QString &unit) const override; bool getDisplayExtents(double &min, double &max) const override; bool setDisplayExtents(double min, double max) override; @@ -176,11 +176,11 @@ bool getPointToDrag(LayerGeometryProvider *v, int x, int y, Event &) const; bool getNoteToEdit(LayerGeometryProvider *v, int x, int y, Event &) const; void getRelativeMousePosition(LayerGeometryProvider *v, Event ¬e, int x, int y, bool &closeToLeft, bool &closeToRight, bool &closeToTop, bool &closeToBottom) const; - SparseTimeValueModel *getAssociatedPitchModel(LayerGeometryProvider *v) const; + ModelId getAssociatedPitchModel(LayerGeometryProvider *v) const; bool updateNoteValueFromPitchCurve(LayerGeometryProvider *v, Event ¬e) const; void splitNotesAt(LayerGeometryProvider *v, sv_frame_t frame, QMouseEvent *e); - NoteModel *m_model; + ModelId m_model; bool m_editing; bool m_intelligentActions; int m_dragPointX; diff -r de41a11cabc2 -r ac0a8addabcf layer/HorizontalFrequencyScale.cpp --- a/layer/HorizontalFrequencyScale.cpp Thu Jun 13 15:35:01 2019 +0100 +++ b/layer/HorizontalFrequencyScale.cpp Wed Jul 17 14:25:16 2019 +0100 @@ -56,6 +56,11 @@ int marginx = -1; for (int i = 0; i < n; ++i) { + + // 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" double val = ticks[i].value; QString label = QString::fromStdString(ticks[i].label); diff -r de41a11cabc2 -r ac0a8addabcf layer/ImageLayer.cpp --- a/layer/ImageLayer.cpp Thu Jun 13 15:35:01 2019 +0100 +++ b/layer/ImageLayer.cpp Wed Jul 17 14:25:16 2019 +0100 @@ -43,8 +43,6 @@ ImageLayer::m_imageMapMutex; ImageLayer::ImageLayer() : - Layer(), - m_model(nullptr), m_editing(false), m_editingCommand(nullptr) { @@ -58,13 +56,29 @@ } } +int +ImageLayer::getCompletion(LayerGeometryProvider *) const +{ + auto model = ModelById::get(m_model); + if (model) return model->getCompletion(); + else return 0; +} + void -ImageLayer::setModel(ImageModel *model) +ImageLayer::setModel(ModelId modelId) { - if (m_model == model) return; - m_model = model; + auto newModel = ModelById::getAs(modelId); + + if (!modelId.isNone() && !newModel) { + throw std::logic_error("Not an ImageModel"); + } + + if (m_model == modelId) return; + m_model = modelId; - connectSignals(m_model); + if (newModel) { + connectSignals(m_model); + } emit modelReplaced(); } @@ -122,10 +136,11 @@ EventVector ImageLayer::getLocalPoints(LayerGeometryProvider *v, int x, int ) const { - if (!m_model) return {}; + auto model = ModelById::getAs(m_model); + if (!model) return {}; // SVDEBUG << "ImageLayer::getLocalPoints(" << x << "," << y << "):"; - EventVector points(m_model->getAllEvents()); + EventVector points(model->getAllEvents()); EventVector rv; @@ -169,12 +184,13 @@ { int x = pos.x(); - if (!m_model || !m_model->getSampleRate()) return ""; + auto model = ModelById::getAs(m_model); + if (!model || !model->getSampleRate()) return ""; EventVector points = getLocalPoints(v, x, pos.y()); if (points.empty()) { - if (!m_model->isReady()) { + if (!model->isReady()) { return tr("In progress"); } else { return ""; @@ -183,7 +199,7 @@ // int useFrame = points.begin()->frame; -// RealTime rt = RealTime::frame2RealTime(useFrame, m_model->getSampleRate()); +// RealTime rt = RealTime::frame2RealTime(useFrame, model->getSampleRate()); QString text; /* @@ -208,11 +224,12 @@ int &resolution, SnapType snap) const { - if (!m_model) { + auto model = ModelById::getAs(m_model); + if (!model) { return Layer::snapToFeatureFrame(v, frame, resolution, snap); } - resolution = m_model->getResolution(); + resolution = model->getResolution(); if (snap == SnapNeighbouring) { EventVector points = getLocalPoints(v, v->getXForFrame(frame), -1); @@ -222,7 +239,7 @@ } Event e; - if (m_model->getNearestEventMatching + if (model->getNearestEventMatching (frame, [](Event) { return true; }, snap == SnapLeft ? EventSeries::Backward : EventSeries::Forward, @@ -237,9 +254,10 @@ void ImageLayer::paint(LayerGeometryProvider *v, QPainter &paint, QRect rect) const { - if (!m_model || !m_model->isOK()) return; + auto model = ModelById::getAs(m_model); + if (!model || !model->isOK()) return; - sv_samplerate_t sampleRate = m_model->getSampleRate(); + sv_samplerate_t sampleRate = model->getSampleRate(); if (!sampleRate) return; // Profiler profiler("ImageLayer::paint", true); @@ -250,7 +268,7 @@ sv_frame_t frame0 = v->getFrameForX(x0); sv_frame_t frame1 = v->getFrameForX(x1); - EventVector points(m_model->getEventsWithin(frame0, frame1 - frame0, 2)); + EventVector points(model->getEventsWithin(frame0, frame1 - frame0, 2)); if (points.empty()) return; paint.save(); @@ -341,6 +359,11 @@ likelyWidth = availableWidth; } + // 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" + int singleWidth = paint.fontMetrics().width(label); if (singleWidth < availableWidth && singleWidth < likelyWidth * 2) { likelyWidth = singleWidth + 4; @@ -513,20 +536,21 @@ { // SVDEBUG << "ImageLayer::drawStart(" << e->x() << "," << e->y() << ")" << endl; - if (!m_model) { + auto model = ModelById::getAs(m_model); + if (!model) { SVDEBUG << "ImageLayer::drawStart: no model" << endl; 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(); m_editingPoint = Event(frame); m_originalPoint = m_editingPoint; if (m_editingCommand) finish(m_editingCommand); - m_editingCommand = new ChangeEventsCommand(m_model, "Add Image"); + m_editingCommand = new ChangeEventsCommand(m_model.untyped, "Add Image"); m_editingCommand->add(m_editingPoint); m_editing = true; @@ -537,11 +561,12 @@ { // SVDEBUG << "ImageLayer::drawDrag(" << e->x() << "," << e->y() << ")" << endl; - if (!m_model || !m_editing) return; + auto model = ModelById::getAs(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(); m_editingCommand->remove(m_editingPoint); m_editingPoint = m_editingPoint @@ -553,7 +578,8 @@ ImageLayer::drawEnd(LayerGeometryProvider *, QMouseEvent *) { // SVDEBUG << "ImageLayer::drawEnd(" << e->x() << "," << e->y() << ")" << endl; - if (!m_model || !m_editing) return; + auto model = ModelById::getAs(m_model); + if (!model || !m_editing) return; ImageDialog dialog(tr("Select image"), "", ""); @@ -586,8 +612,8 @@ } Event point = Event(frame).withURI(url); - ChangeEventsCommand *command = - new ChangeEventsCommand(m_model, "Add Image"); + auto command = + new ChangeEventsCommand(m_model.untyped, "Add Image"); command->add(point); finish(command); return true; @@ -598,7 +624,8 @@ { // SVDEBUG << "ImageLayer::editStart(" << e->x() << "," << e->y() << ")" << endl; - if (!m_model) return; + auto model = ModelById::getAs(m_model); + if (!model) return; EventVector points = getLocalPoints(v, e->x(), e->y()); if (points.empty()) return; @@ -618,16 +645,17 @@ void ImageLayer::editDrag(LayerGeometryProvider *v, QMouseEvent *e) { - if (!m_model || !m_editing) return; + auto model = ModelById::getAs(m_model); + if (!model || !m_editing) return; sv_frame_t frameDiff = v->getFrameForX(e->x()) - v->getFrameForX(m_editOrigin.x()); sv_frame_t frame = m_originalPoint.getFrame() + frameDiff; if (frame < 0) frame = 0; - frame = (frame / m_model->getResolution()) * m_model->getResolution(); + frame = (frame / model->getResolution()) * model->getResolution(); if (!m_editingCommand) { - m_editingCommand = new ChangeEventsCommand(m_model, tr("Move Image")); + m_editingCommand = new ChangeEventsCommand(m_model.untyped, tr("Move Image")); } m_editingCommand->remove(m_editingPoint); @@ -640,7 +668,8 @@ ImageLayer::editEnd(LayerGeometryProvider *, QMouseEvent *) { // SVDEBUG << "ImageLayer::editEnd(" << e->x() << "," << e->y() << ")" << endl; - if (!m_model || !m_editing) return; + auto model = ModelById::getAs(m_model); + if (!model || !m_editing) return; if (m_editingCommand) { finish(m_editingCommand); @@ -653,7 +682,8 @@ bool ImageLayer::editOpen(LayerGeometryProvider *v, QMouseEvent *e) { - if (!m_model) return false; + auto model = ModelById::getAs(m_model); + if (!model) return false; EventVector points = getLocalPoints(v, e->x(), e->y()); if (points.empty()) return false; @@ -669,8 +699,8 @@ checkAddSource(dialog.getImage()); - ChangeEventsCommand *command = - new ChangeEventsCommand(m_model, tr("Edit Image")); + auto command = + new ChangeEventsCommand(m_model.untyped, tr("Edit Image")); command->remove(*points.begin()); command->add(points.begin()-> withURI(dialog.getImage()).withLabel(dialog.getLabel())); @@ -683,13 +713,14 @@ void ImageLayer::moveSelection(Selection s, sv_frame_t newStartFrame) { - if (!m_model) return; + auto model = ModelById::getAs(m_model); + if (!model) return; - ChangeEventsCommand *command = - new ChangeEventsCommand(m_model, tr("Drag Selection")); + auto command = + new ChangeEventsCommand(m_model.untyped, tr("Drag Selection")); EventVector points = - m_model->getEventsStartingWithin(s.getStartFrame(), s.getDuration()); + model->getEventsStartingWithin(s.getStartFrame(), s.getDuration()); for (Event p: points) { command->remove(p); @@ -704,13 +735,14 @@ void ImageLayer::resizeSelection(Selection s, Selection newSize) { - if (!m_model) return; + auto model = ModelById::getAs(m_model); + if (!model) return; - ChangeEventsCommand *command = - new ChangeEventsCommand(m_model, tr("Resize Selection")); + auto command = + new ChangeEventsCommand(m_model.untyped, tr("Resize Selection")); EventVector points = - m_model->getEventsStartingWithin(s.getStartFrame(), s.getDuration()); + model->getEventsStartingWithin(s.getStartFrame(), s.getDuration()); double ratio = double(newSize.getDuration()) / double(s.getDuration()); double oldStart = double(s.getStartFrame()); @@ -732,13 +764,14 @@ void ImageLayer::deleteSelection(Selection s) { - if (!m_model) return; + auto model = ModelById::getAs(m_model); + if (!model) return; - ChangeEventsCommand *command = - new ChangeEventsCommand(m_model, tr("Delete Selection")); + auto command = + new ChangeEventsCommand(m_model.untyped, tr("Delete Selection")); EventVector points = - m_model->getEventsStartingWithin(s.getStartFrame(), s.getDuration()); + model->getEventsStartingWithin(s.getStartFrame(), s.getDuration()); for (Event p: points) { command->remove(p); @@ -750,10 +783,11 @@ void ImageLayer::copy(LayerGeometryProvider *v, Selection s, Clipboard &to) { - if (!m_model) return; + auto model = ModelById::getAs(m_model); + if (!model) return; EventVector points = - m_model->getEventsStartingWithin(s.getStartFrame(), s.getDuration()); + model->getEventsStartingWithin(s.getStartFrame(), s.getDuration()); for (Event p: points) { to.addPoint(p.withReferenceFrame(alignToReference(v, p.getFrame()))); @@ -763,7 +797,8 @@ bool ImageLayer::paste(LayerGeometryProvider *v, const Clipboard &from, sv_frame_t /* frameOffset */, bool /* interactive */) { - if (!m_model) return false; + auto model = ModelById::getAs(m_model); + if (!model) return false; const EventVector &points = from.getPoints(); @@ -786,8 +821,7 @@ } } - ChangeEventsCommand *command = - new ChangeEventsCommand(m_model, tr("Paste")); + auto command = new ChangeEventsCommand(m_model.untyped, tr("Paste")); for (EventVector::const_iterator i = points.begin(); i != points.end(); ++i) { @@ -863,7 +897,8 @@ void ImageLayer::checkAddSources() { - const EventVector &points(m_model->getAllEvents()); + auto model = ModelById::getAs(m_model); + const EventVector &points(model->getAllEvents()); for (EventVector::const_iterator i = points.begin(); i != points.end(); ++i) { @@ -895,7 +930,7 @@ m_images.erase(img); for (ViewImageMap::iterator i = m_scaled.begin(); i != m_scaled.end(); ++i) { i->second.erase(img); - emit modelChanged(); + emit modelChanged(getModel()); } } diff -r de41a11cabc2 -r ac0a8addabcf layer/ImageLayer.h --- a/layer/ImageLayer.h Thu Jun 13 15:35:01 2019 +0100 +++ b/layer/ImageLayer.h Wed Jul 17 14:25:16 2019 +0100 @@ -43,8 +43,8 @@ QString getFeatureDescription(LayerGeometryProvider *v, QPoint &) const override; bool snapToFeatureFrame(LayerGeometryProvider *v, sv_frame_t &frame, - int &resolution, - SnapType snap) const override; + int &resolution, + SnapType snap) const override; void drawStart(LayerGeometryProvider *v, QMouseEvent *) override; void drawDrag(LayerGeometryProvider *v, QMouseEvent *) override; @@ -64,16 +64,16 @@ bool editOpen(LayerGeometryProvider *, QMouseEvent *) override; // on double-click - const Model *getModel() const override { return m_model; } - void setModel(ImageModel *model); + ModelId getModel() const override { return m_model; } + void setModel(ModelId model); // an ImageModel please PropertyList getProperties() const override; QString getPropertyLabel(const PropertyName &) const override; PropertyType getPropertyType(const PropertyName &) const override; int getPropertyRangeAndValue(const PropertyName &, - int *min, int *max, int *deflt) const override; + int *min, int *max, int *deflt) const override; QString getPropertyValueLabel(const PropertyName &, - int value) const override; + int value) const override; void setProperty(const PropertyName &, int value) override; ColourSignificance getLayerColourSignificance() const override { @@ -84,13 +84,13 @@ bool isLayerEditable() const override { return true; } - int getCompletion(LayerGeometryProvider *) const override { return m_model->getCompletion(); } + int getCompletion(LayerGeometryProvider *) const override; bool getValueExtents(double &min, double &max, - bool &logarithmic, QString &unit) const override; + bool &logarithmic, QString &unit) const override; void toXml(QTextStream &stream, QString indent = "", - QString extraAttributes = "") const override; + QString extraAttributes = "") const override; int getVerticalScaleWidth(LayerGeometryProvider *, bool, QPainter &) const override { return 0; } @@ -127,7 +127,7 @@ QString getLocalFilename(QString img) const; void checkAddSource(QString img) const; - ImageModel *m_model; + ModelId m_model; // an ImageModel bool m_editing; QPoint m_editOrigin; Event m_originalPoint; diff -r de41a11cabc2 -r ac0a8addabcf layer/Layer.cpp --- a/layer/Layer.cpp Thu Jun 13 15:35:01 2019 +0100 +++ b/layer/Layer.cpp Wed Jul 17 14:25:16 2019 +0100 @@ -46,19 +46,22 @@ } void -Layer::connectSignals(const Model *model) +Layer::connectSignals(ModelId modelId) { - connect(model, SIGNAL(modelChanged()), - this, SIGNAL(modelChanged())); + auto model = ModelById::get(modelId); + if (!model) return; + + connect(model.get(), SIGNAL(modelChanged(ModelId)), + this, SIGNAL(modelChanged(ModelId))); - connect(model, SIGNAL(modelChangedWithin(sv_frame_t, sv_frame_t)), - this, SIGNAL(modelChangedWithin(sv_frame_t, sv_frame_t))); + connect(model.get(), SIGNAL(modelChangedWithin(ModelId, sv_frame_t, sv_frame_t)), + this, SIGNAL(modelChangedWithin(ModelId, sv_frame_t, sv_frame_t))); - connect(model, SIGNAL(completionChanged()), - this, SIGNAL(modelCompletionChanged())); + connect(model.get(), SIGNAL(completionChanged(ModelId)), + this, SIGNAL(modelCompletionChanged(ModelId))); - connect(model, SIGNAL(alignmentCompletionChanged()), - this, SIGNAL(modelAlignmentCompletionChanged())); + connect(model.get(), SIGNAL(alignmentCompletionChanged(ModelId)), + this, SIGNAL(modelAlignmentCompletionChanged(ModelId))); } QString @@ -84,7 +87,8 @@ (factory->getLayerType(this)); QString modelName; - if (getModel()) modelName = getModel()->objectName(); + auto model = ModelById::get(getModel()); + if (model) modelName = model->objectName(); QString text; if (modelName != "") { @@ -103,15 +107,11 @@ emit layerNameChanged(); } -PlayParameters * +std::shared_ptr Layer::getPlayParameters() { -// cerr << "Layer (" << this << ", " << objectName() << ")::getPlayParameters: model is "<< getModel() << endl; - const Model *model = getModel(); - if (model) { - return PlayParameterRepository::getInstance()->getPlayParameters(model); - } - return nullptr; + return PlayParameterRepository::getInstance()->getPlayParameters + (getModel().untyped); } void @@ -143,10 +143,10 @@ { if (!hasTimeXAxis()) return false; - const Model *m = getModel(); - if (!m) return false; + auto model = ModelById::get(getModel()); + if (!model) return false; - value = double(v->getFrameForX(x)) / m->getSampleRate(); + value = double(v->getFrameForX(x)) / model->getSampleRate(); unit = "s"; return true; } @@ -168,10 +168,9 @@ sv_frame_t Layer::alignToReference(LayerGeometryProvider *v, sv_frame_t frame) const { - const Model *m = getModel(); - SVDEBUG << "Layer::alignToReference(" << frame << "): model = " << m << ", alignment reference = " << (m ? m->getAlignmentReference() : nullptr) << endl; - if (m && m->getAlignmentReference()) { - return m->alignToReference(frame); + auto model = ModelById::get(getModel()); + if (model && !model->getAlignmentReference().isNone()) { + return model->alignToReference(frame); } else { return v->getView()->alignToReference(frame); } @@ -180,10 +179,9 @@ sv_frame_t Layer::alignFromReference(LayerGeometryProvider *v, sv_frame_t frame) const { - const Model *m = getModel(); - SVDEBUG << "Layer::alignFromReference(" << frame << "): model = " << m << ", alignment reference = " << (m ? m->getAlignmentReference() : nullptr) << endl; - if (m && m->getAlignmentReference()) { - return m->alignFromReference(frame); + auto model = ModelById::get(getModel()); + if (model && !model->getAlignmentReference().isNone()) { + return model->alignFromReference(frame); } else { return v->getView()->alignFromReference(frame); } @@ -644,12 +642,16 @@ .arg(extraAttributes).arg(encodeEntities(m_presentationName)); } + int modelExportId = -1; + auto model = ModelById::get(getModel()); + if (model) modelExportId = model->getExportId(); + stream << QString("getLayerTypeName (LayerFactory::getInstance()->getLayerType(this)))) .arg(getExportId()) .arg(encodeEntities(objectName())) - .arg(getModel() ? getModel()->getExportId() : -1) + .arg(modelExportId) .arg(extraAttributes); if (m_measureRects.empty()) { @@ -678,12 +680,16 @@ .arg(extraAttributes).arg(encodeEntities(m_presentationName)); } + int modelExportId = -1; + auto model = ModelById::get(getModel()); + if (model) modelExportId = model->getExportId(); + stream << QString("\n") .arg(encodeEntities(LayerFactory::getInstance()->getLayerTypeName (LayerFactory::getInstance()->getLayerType(this)))) .arg(getExportId()) .arg(encodeEntities(objectName())) - .arg(getModel() ? getModel()->getExportId() : -1) + .arg(modelExportId) .arg(extraAttributes); } diff -r de41a11cabc2 -r ac0a8addabcf layer/Layer.h --- a/layer/Layer.h Thu Jun 13 15:35:01 2019 +0100 +++ b/layer/Layer.h Wed Jul 17 14:25:16 2019 +0100 @@ -20,6 +20,8 @@ #include "base/XmlExportable.h" #include "base/Selection.h" +#include "data/model/Model.h" + #include "widgets/CommandHistory.h" #include "system/System.h" @@ -36,7 +38,6 @@ #include class ZoomConstraint; -class Model; class QPainter; class View; class LayerGeometryProvider; @@ -59,10 +60,10 @@ Layer(); virtual ~Layer(); - virtual const Model *getModel() const = 0; - Model *getModel() { - return const_cast(const_cast(this)->getModel()); - } + /** + * Return the ID of the model represented in this layer. + */ + virtual ModelId getModel() const = 0; /** * Return a zoom constraint object defining the supported zoom @@ -410,7 +411,12 @@ */ virtual bool isLayerDormant(const LayerGeometryProvider *v) const; - PlayParameters *getPlayParameters() override; + /** + * Return the play parameters for this layer, if any. The return + * value is a shared_ptr that can be passed to (e.g.) + * PlayParameterRepository::EditCommand to change the parameters. + */ + std::shared_ptr getPlayParameters() override; /** * True if this layer will need to place text labels when it is @@ -556,10 +562,10 @@ void showLayer(LayerGeometryProvider *, bool show); signals: - void modelChanged(); - void modelCompletionChanged(); - void modelAlignmentCompletionChanged(); - void modelChangedWithin(sv_frame_t startFrame, sv_frame_t endFrame); + void modelChanged(ModelId); + void modelCompletionChanged(ModelId); + void modelAlignmentCompletionChanged(ModelId); + void modelChangedWithin(ModelId, sv_frame_t startFrame, sv_frame_t endFrame); void modelReplaced(); void layerParametersChanged(); @@ -570,7 +576,7 @@ void verticalZoomChanged(); protected: - void connectSignals(const Model *); + void connectSignals(ModelId); virtual sv_frame_t alignToReference(LayerGeometryProvider *v, sv_frame_t frame) const; virtual sv_frame_t alignFromReference(LayerGeometryProvider *v, sv_frame_t frame) const; diff -r de41a11cabc2 -r ac0a8addabcf layer/LayerFactory.cpp --- a/layer/LayerFactory.cpp Thu Jun 13 15:35:01 2019 +0100 +++ b/layer/LayerFactory.cpp Wed Jul 17 14:25:16 2019 +0100 @@ -133,55 +133,55 @@ } LayerFactory::LayerTypeSet -LayerFactory::getValidLayerTypes(Model *model) +LayerFactory::getValidLayerTypes(ModelId modelId) { LayerTypeSet types; - if (dynamic_cast(model)) { + if (ModelById::getAs(modelId)) { types.insert(Colour3DPlot); types.insert(Slice); } - if (dynamic_cast(model)) { + if (ModelById::getAs(modelId)) { types.insert(Waveform); } - if (dynamic_cast(model)) { + if (ModelById::getAs(modelId)) { types.insert(Spectrogram); types.insert(MelodicRangeSpectrogram); types.insert(PeakFrequencySpectrogram); } - if (dynamic_cast(model)) { + if (ModelById::getAs(modelId)) { types.insert(TimeInstants); } - if (dynamic_cast(model)) { + if (ModelById::getAs(modelId)) { types.insert(TimeValues); } - if (dynamic_cast(model)) { - NoteModel *nm = dynamic_cast(model); - if (nm->getSubtype() == NoteModel::FLEXI_NOTE) { + if (ModelById::getAs(modelId)) { + auto nm = ModelById::getAs(modelId); + if (nm && nm->getSubtype() == NoteModel::FLEXI_NOTE) { types.insert(FlexiNotes); } else { types.insert(Notes); } } - if (dynamic_cast(model)) { + if (ModelById::getAs(modelId)) { types.insert(Regions); } - if (dynamic_cast(model)) { + if (ModelById::getAs(modelId)) { types.insert(Text); } - if (dynamic_cast(model)) { + if (ModelById::getAs(modelId)) { types.insert(Image); } - if (dynamic_cast(model)) { + if (ModelById::getAs(modelId)) { types.insert(Spectrum); } @@ -300,11 +300,8 @@ } void -LayerFactory::setModel(Layer *layer, Model *model) +LayerFactory::setModel(Layer *layer, ModelId model) { -// if (trySetModel(layer, model)) -// return; - if (trySetModel(layer, model)) return; @@ -341,35 +338,34 @@ if (trySetModel(layer, model)) return; - if (trySetModel(layer, model)) - return; - if (trySetModel(layer, model)) return; - -// if (trySetModel(layer, model)) -// return; } -Model * -LayerFactory::createEmptyModel(LayerType layerType, Model *baseModel) +std::shared_ptr +LayerFactory::createEmptyModel(LayerType layerType, ModelId baseModelId) { + auto baseModel = ModelById::get(baseModelId); + if (!baseModel) return {}; + + sv_samplerate_t rate = baseModel->getSampleRate(); + if (layerType == TimeInstants) { - return new SparseOneDimensionalModel(baseModel->getSampleRate(), 1); + return std::make_shared(rate, 1); } else if (layerType == TimeValues) { - return new SparseTimeValueModel(baseModel->getSampleRate(), 1, true); + return std::make_shared(rate, 1, true); } else if (layerType == FlexiNotes) { - return new NoteModel(baseModel->getSampleRate(), 1, true); + return std::make_shared(rate, 1, true); } else if (layerType == Notes) { - return new NoteModel(baseModel->getSampleRate(), 1, true); + return std::make_shared(rate, 1, true); } else if (layerType == Regions) { - return new RegionModel(baseModel->getSampleRate(), 1, true); + return std::make_shared(rate, 1, true); } else if (layerType == Text) { - return new TextModel(baseModel->getSampleRate(), 1, true); + return std::make_shared(rate, 1, true); } else if (layerType == Image) { - return new ImageModel(baseModel->getSampleRate(), 1, true); + return std::make_shared(rate, 1, true); } else { - return nullptr; + return {}; } } diff -r de41a11cabc2 -r ac0a8addabcf layer/LayerFactory.h --- a/layer/LayerFactory.h Thu Jun 13 15:35:01 2019 +0100 +++ b/layer/LayerFactory.h Wed Jul 17 14:25:16 2019 +0100 @@ -19,8 +19,9 @@ #include #include +#include "data/model/Model.h" + class Layer; -class Model; class Clipboard; class LayerFactory @@ -56,7 +57,7 @@ virtual ~LayerFactory(); typedef std::set LayerTypeSet; - LayerTypeSet getValidLayerTypes(Model *model); + LayerTypeSet getValidLayerTypes(ModelId modelId); /** * Return the set of layer types that an end user should be @@ -86,8 +87,8 @@ bool isLayerSliceable(const Layer *); - void setModel(Layer *layer, Model *model); - Model *createEmptyModel(LayerType type, Model *baseModel); + void setModel(Layer *layer, ModelId model); + std::shared_ptr createEmptyModel(LayerType type, ModelId baseModel); int getChannel(Layer *layer); void setChannel(Layer *layer, int channel); @@ -100,12 +101,14 @@ protected: template - bool trySetModel(Layer *layerBase, Model *modelBase) { + bool trySetModel(Layer *layerBase, ModelId modelId) { LayerClass *layer = dynamic_cast(layerBase); if (!layer) return false; - ModelClass *model = dynamic_cast(modelBase); - if (!model) return false; - layer->setModel(model); + if (!modelId.isNone()) { + auto model = ModelById::getAs(modelId); + if (!model) return false; + } + layer->setModel(modelId); return true; } diff -r de41a11cabc2 -r ac0a8addabcf layer/LinearColourScale.cpp --- a/layer/LinearColourScale.cpp Thu Jun 13 15:35:01 2019 +0100 +++ b/layer/LinearColourScale.cpp Wed Jul 17 14:25:16 2019 +0100 @@ -26,6 +26,11 @@ LinearColourScale::getWidth(LayerGeometryProvider *, QPainter &paint) { + // 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" + return paint.fontMetrics().width("-000.00") + 15; } diff -r de41a11cabc2 -r ac0a8addabcf layer/LinearNumericalScale.cpp --- a/layer/LinearNumericalScale.cpp Thu Jun 13 15:35:01 2019 +0100 +++ b/layer/LinearNumericalScale.cpp Wed Jul 17 14:25:16 2019 +0100 @@ -27,6 +27,11 @@ LinearNumericalScale::getWidth(LayerGeometryProvider *, QPainter &paint) { + // 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" + return paint.fontMetrics().width("-000.00") + 10; } diff -r de41a11cabc2 -r ac0a8addabcf layer/LogColourScale.cpp --- a/layer/LogColourScale.cpp Thu Jun 13 15:35:01 2019 +0100 +++ b/layer/LogColourScale.cpp Wed Jul 17 14:25:16 2019 +0100 @@ -28,6 +28,11 @@ LogColourScale::getWidth(LayerGeometryProvider *, QPainter &paint) { + // 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" + return paint.fontMetrics().width("-000.00") + 15; } diff -r de41a11cabc2 -r ac0a8addabcf layer/LogNumericalScale.cpp --- a/layer/LogNumericalScale.cpp Thu Jun 13 15:35:01 2019 +0100 +++ b/layer/LogNumericalScale.cpp Wed Jul 17 14:25:16 2019 +0100 @@ -28,6 +28,11 @@ LogNumericalScale::getWidth(LayerGeometryProvider *, QPainter &paint) { + // 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" + return paint.fontMetrics().width("-000.00") + 10; } diff -r de41a11cabc2 -r ac0a8addabcf layer/NoteLayer.cpp --- a/layer/NoteLayer.cpp Thu Jun 13 15:35:01 2019 +0100 +++ b/layer/NoteLayer.cpp Wed Jul 17 14:25:16 2019 +0100 @@ -48,7 +48,6 @@ NoteLayer::NoteLayer() : SingleColourLayer(), - m_model(nullptr), m_editing(false), m_dragPointX(0), m_dragPointY(0), @@ -65,16 +64,30 @@ SVDEBUG << "constructed NoteLayer" << endl; } +int +NoteLayer::getCompletion(LayerGeometryProvider *) const +{ + auto model = ModelById::get(m_model); + if (model) return model->getCompletion(); + else return 0; +} + void -NoteLayer::setModel(NoteModel *model) -{ - if (m_model == model) return; - m_model = model; +NoteLayer::setModel(ModelId modelId) +{ + auto newModel = ModelById::getAs(modelId); + + if (!modelId.isNone() && !newModel) { + throw std::logic_error("Not a NoteModel"); + } + + if (m_model == modelId) return; + m_model = modelId; - connectSignals(m_model); - -// SVDEBUG << "NoteLayer::setModel(" << model << ")" << endl; - + if (newModel) { + connectSignals(m_model); + } + m_scaleMinimum = 0; m_scaleMaximum = 0; @@ -118,7 +131,8 @@ QString NoteLayer::getScaleUnits() const { - if (m_model) return m_model->getScaleUnits(); + auto model = ModelById::getAs(m_model); + if (model) return model->getScaleUnits(); else return ""; } @@ -139,9 +153,10 @@ } else if (name == "Scale Units") { if (deflt) *deflt = 0; - if (m_model) { + auto model = ModelById::getAs(m_model); + if (model) { val = UnitDatabase::getInstance()->getUnitId - (getScaleUnits()); + (model->getScaleUnits()); } } else { @@ -174,10 +189,11 @@ if (name == "Vertical Scale") { setVerticalScale(VerticalScale(value)); } else if (name == "Scale Units") { - if (m_model) { - m_model->setScaleUnits + auto model = ModelById::getAs(m_model); + if (model) { + model->setScaleUnits (UnitDatabase::getInstance()->getUnitById(value)); - emit modelChanged(); + emit modelChanged(m_model); } } else { return SingleColourLayer::setProperty(name, value); @@ -214,9 +230,10 @@ NoteLayer::getValueExtents(double &min, double &max, bool &logarithmic, QString &unit) const { - if (!m_model) return false; - min = m_model->getValueMinimum(); - max = m_model->getValueMaximum(); + auto model = ModelById::getAs(m_model); + if (!model) return false; + min = model->getValueMinimum(); + max = model->getValueMaximum(); if (shouldConvertMIDIToHz()) { unit = "Hz"; @@ -225,7 +242,9 @@ } else unit = getScaleUnits(); if (m_verticalScale == MIDIRangeScale || - m_verticalScale == LogScale) logarithmic = true; + m_verticalScale == LogScale) { + logarithmic = true; + } return true; } @@ -233,7 +252,8 @@ bool NoteLayer::getDisplayExtents(double &min, double &max) const { - if (!m_model || shouldAutoAlign()) return false; + auto model = ModelById::getAs(m_model); + if (!model || shouldAutoAlign()) return false; if (m_verticalScale == MIDIRangeScale) { min = Pitch::getFrequencyForPitch(0); @@ -242,8 +262,8 @@ } if (m_scaleMinimum == m_scaleMaximum) { - min = m_model->getValueMinimum(); - max = m_model->getValueMaximum(); + min = model->getValueMinimum(); + max = model->getValueMaximum(); } else { min = m_scaleMinimum; max = m_scaleMaximum; @@ -264,7 +284,7 @@ bool NoteLayer::setDisplayExtents(double min, double max) { - if (!m_model) return false; + if (m_model.isNone()) return false; if (min == max) { if (min == 0.f) { @@ -288,9 +308,7 @@ int NoteLayer::getVerticalZoomSteps(int &defaultStep) const { - if (shouldAutoAlign()) return 0; - if (!m_model) return 0; - + if (shouldAutoAlign() || m_model.isNone()) return 0; defaultStep = 0; return 100; } @@ -298,8 +316,7 @@ int NoteLayer::getCurrentVerticalZoomStep() const { - if (shouldAutoAlign()) return 0; - if (!m_model) return 0; + if (shouldAutoAlign() || m_model.isNone()) return 0; RangeMapper *mapper = getNewVerticalZoomRangeMapper(); if (!mapper) return 0; @@ -319,8 +336,7 @@ void NoteLayer::setVerticalZoomStep(int step) { - if (shouldAutoAlign()) return; - if (!m_model) return; + if (shouldAutoAlign() || m_model.isNone()) return; RangeMapper *mapper = getNewVerticalZoomRangeMapper(); if (!mapper) return; @@ -370,7 +386,7 @@ RangeMapper * NoteLayer::getNewVerticalZoomRangeMapper() const { - if (!m_model) return nullptr; + if (m_model.isNone()) return nullptr; RangeMapper *mapper; @@ -393,21 +409,22 @@ EventVector NoteLayer::getLocalPoints(LayerGeometryProvider *v, int x) const { - if (!m_model) return {}; + auto model = ModelById::getAs(m_model); + if (!model) return {}; sv_frame_t frame = v->getFrameForX(x); - EventVector local = m_model->getEventsCovering(frame); + EventVector local = model->getEventsCovering(frame); if (!local.empty()) return local; int fuzz = ViewManager::scalePixelSize(2); sv_frame_t start = v->getFrameForX(x - fuzz); sv_frame_t end = v->getFrameForX(x + fuzz); - local = m_model->getEventsStartingWithin(frame, end - frame); + local = model->getEventsStartingWithin(frame, end - frame); if (!local.empty()) return local; - local = m_model->getEventsSpanning(start, frame - start); + local = model->getEventsSpanning(start, frame - start); if (!local.empty()) return local; return {}; @@ -416,11 +433,12 @@ bool NoteLayer::getPointToDrag(LayerGeometryProvider *v, int x, int y, Event &point) const { - if (!m_model) return false; + auto model = ModelById::getAs(m_model); + if (!model) return false; sv_frame_t frame = v->getFrameForX(x); - EventVector onPoints = m_model->getEventsCovering(frame); + EventVector onPoints = model->getEventsCovering(frame); if (onPoints.empty()) return false; int nearestDistance = -1; @@ -441,12 +459,13 @@ { int x = pos.x(); - if (!m_model || !m_model->getSampleRate()) return ""; + auto model = ModelById::getAs(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"); @@ -461,9 +480,9 @@ int y = getYForValue(v, i->getValue()); int h = 3; - if (m_model->getValueQuantization() != 0.0) { + if (model->getValueQuantization() != 0.0) { h = y - getYForValue - (v, i->getValue() + m_model->getValueQuantization()); + (v, i->getValue() + model->getValueQuantization()); if (h < 3) h = 3; } @@ -476,9 +495,9 @@ if (i == points.end()) return tr("No local points"); RealTime rt = RealTime::frame2RealTime(note.getFrame(), - m_model->getSampleRate()); + model->getSampleRate()); RealTime rd = RealTime::frame2RealTime(note.getDuration(), - m_model->getSampleRate()); + model->getSampleRate()); QString pitchText; @@ -530,7 +549,8 @@ int &resolution, SnapType snap) const { - if (!m_model) { + auto model = ModelById::getAs(m_model); + if (!model) { return Layer::snapToFeatureFrame(v, frame, resolution, snap); } @@ -541,7 +561,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)); @@ -551,7 +571,7 @@ } Event e; - if (m_model->getNearestEventMatching + if (model->getNearestEventMatching (frame, [](Event) { return true; }, snap == SnapLeft ? EventSeries::Backward : EventSeries::Forward, @@ -570,6 +590,9 @@ max = 0.0; log = false; + auto model = ModelById::getAs(m_model); + if (!model) return; + QString queryUnits; if (shouldConvertMIDIToHz()) queryUnits = "Hz"; else queryUnits = getScaleUnits(); @@ -578,8 +601,8 @@ if (!v->getValueExtents(queryUnits, min, max, log)) { - min = m_model->getValueMinimum(); - max = m_model->getValueMaximum(); + min = model->getValueMinimum(); + max = model->getValueMaximum(); if (shouldConvertMIDIToHz()) { min = Pitch::getFrequencyForPitch(int(lrint(min))); @@ -681,16 +704,17 @@ bool NoteLayer::shouldAutoAlign() const { - if (!m_model) return false; + if (m_model.isNone()) return false; return (m_verticalScale == AutoAlignScale); } void NoteLayer::paint(LayerGeometryProvider *v, QPainter &paint, QRect rect) const { - if (!m_model || !m_model->isOK()) return; + auto model = ModelById::getAs(m_model); + if (!model || !model->isOK()) return; - sv_samplerate_t sampleRate = m_model->getSampleRate(); + sv_samplerate_t sampleRate = model->getSampleRate(); if (!sampleRate) return; // Profiler profiler("NoteLayer::paint", true); @@ -699,7 +723,7 @@ sv_frame_t frame0 = v->getFrameForX(x0); sv_frame_t frame1 = v->getFrameForX(x1); - EventVector points(m_model->getEventsSpanning(frame0, frame1 - frame0)); + EventVector points(model->getEventsSpanning(frame0, frame1 - frame0)); if (points.empty()) return; paint.setPen(getBaseQColor()); @@ -708,10 +732,10 @@ brushColour.setAlpha(80); // SVDEBUG << "NoteLayer::paint: resolution is " -// << m_model->getResolution() << " frames" << endl; +// << model->getResolution() << " frames" << endl; - 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; QPoint localPos; @@ -739,8 +763,8 @@ int w = v->getXForFrame(p.getFrame() + p.getDuration()) - x; int h = 3; - if (m_model->getValueQuantization() != 0.0) { - h = y - getYForValue(v, p.getValue() + m_model->getValueQuantization()); + if (model->getValueQuantization() != 0.0) { + h = y - getYForValue(v, p.getValue() + model->getValueQuantization()); if (h < 3) h = 3; } @@ -753,6 +777,11 @@ paint.setPen(v->getForeground()); paint.setBrush(v->getForeground()); + // 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" + QString vlabel = QString("%1%2").arg(p.getValue()).arg(getScaleUnits()); PaintAssistant::drawVisibleText(v, paint, x - paint.fontMetrics().width(vlabel) - 2, @@ -761,7 +790,7 @@ vlabel, PaintAssistant::OutlinedText); QString hlabel = RealTime::frame2RealTime - (p.getFrame(), m_model->getSampleRate()).toText(true).c_str(); + (p.getFrame(), model->getSampleRate()).toText(true).c_str(); PaintAssistant::drawVisibleText(v, paint, x, y - h/2 - paint.fontMetrics().descent() - 2, @@ -777,7 +806,7 @@ int NoteLayer::getVerticalScaleWidth(LayerGeometryProvider *v, bool, QPainter &paint) const { - if (!m_model) { + if (m_model.isNone()) { return 0; } @@ -795,7 +824,8 @@ void NoteLayer::paintVerticalScale(LayerGeometryProvider *v, bool, QPainter &paint, QRect) const { - if (!m_model || m_model->isEmpty()) return; + auto model = ModelById::getAs(m_model); + if (!model || model->isEmpty()) return; QString unit; double min, max; @@ -835,11 +865,12 @@ { // SVDEBUG << "NoteLayer::drawStart(" << e->x() << "," << e->y() << ")" << endl; - if (!m_model) return; + auto model = ModelById::getAs(m_model); + if (!model) 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()); @@ -847,7 +878,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")); m_editingCommand->add(m_editingPoint); m_editing = true; @@ -858,11 +889,12 @@ { // SVDEBUG << "NoteLayer::drawDrag(" << e->x() << "," << e->y() << ")" << endl; - if (!m_model || !m_editing) return; + auto model = ModelById::getAs(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 newValue = getValueForY(v, e->y()); @@ -887,7 +919,8 @@ NoteLayer::drawEnd(LayerGeometryProvider *, QMouseEvent *) { // SVDEBUG << "NoteLayer::drawEnd(" << e->x() << "," << e->y() << ")" << endl; - if (!m_model || !m_editing) return; + auto model = ModelById::getAs(m_model); + if (!model || !m_editing) return; finish(m_editingCommand); m_editingCommand = nullptr; m_editing = false; @@ -896,7 +929,8 @@ void NoteLayer::eraseStart(LayerGeometryProvider *v, QMouseEvent *e) { - if (!m_model) return; + auto model = ModelById::getAs(m_model); + if (!model) return; if (!getPointToDrag(v, e->x(), e->y(), m_editingPoint)) return; @@ -916,7 +950,8 @@ void NoteLayer::eraseEnd(LayerGeometryProvider *v, QMouseEvent *e) { - if (!m_model || !m_editing) return; + auto model = ModelById::getAs(m_model); + if (!model || !m_editing) return; m_editing = false; @@ -925,7 +960,7 @@ if (p.getFrame() != m_editingPoint.getFrame() || p.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); @@ -939,7 +974,8 @@ { // SVDEBUG << "NoteLayer::editStart(" << e->x() << "," << e->y() << ")" << endl; - if (!m_model) return; + auto model = ModelById::getAs(m_model); + if (!model) return; if (!getPointToDrag(v, e->x(), e->y(), m_editingPoint)) return; m_originalPoint = m_editingPoint; @@ -962,7 +998,8 @@ { // SVDEBUG << "NoteLayer::editDrag(" << e->x() << "," << e->y() << ")" << endl; - if (!m_model || !m_editing) return; + auto model = ModelById::getAs(m_model); + if (!model || !m_editing) return; int xdist = e->x() - m_dragStartX; int ydist = e->y() - m_dragStartY; @@ -971,13 +1008,13 @@ sv_frame_t frame = v->getFrameForX(newx); if (frame < 0) frame = 0; - frame = frame / m_model->getResolution() * m_model->getResolution(); + frame = frame / model->getResolution() * model->getResolution(); double value = getValueForY(v, newy); 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); @@ -991,7 +1028,8 @@ NoteLayer::editEnd(LayerGeometryProvider *, QMouseEvent *) { // SVDEBUG << "NoteLayer::editEnd(" << e->x() << "," << e->y() << ")" << endl; - if (!m_model || !m_editing) return; + auto model = ModelById::getAs(m_model); + if (!model || !m_editing) return; if (m_editingCommand) { @@ -1018,7 +1056,8 @@ bool NoteLayer::editOpen(LayerGeometryProvider *v, QMouseEvent *e) { - if (!m_model) return false; + auto model = ModelById::getAs(m_model); + if (!model) return false; Event note(0); if (!getPointToDrag(v, e->x(), e->y(), note)) return false; @@ -1026,7 +1065,7 @@ // Event note = *points.begin(); ItemEditDialog *dialog = new ItemEditDialog - (m_model->getSampleRate(), + (model->getSampleRate(), ItemEditDialog::ShowTime | ItemEditDialog::ShowDuration | ItemEditDialog::ShowValue | @@ -1050,7 +1089,7 @@ .withLabel(dialog->getText()); ChangeEventsCommand *command = new ChangeEventsCommand - (m_model, tr("Edit Point")); + (m_model.untyped, tr("Edit Point")); command->remove(note); command->add(newNote); finish(command); @@ -1066,13 +1105,14 @@ void NoteLayer::moveSelection(Selection s, sv_frame_t newStartFrame) { - if (!m_model) return; + auto model = ModelById::getAs(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->getEventsStartingWithin(s.getStartFrame(), s.getDuration()); + model->getEventsStartingWithin(s.getStartFrame(), s.getDuration()); for (Event p: points) { command->remove(p); @@ -1087,13 +1127,14 @@ void NoteLayer::resizeSelection(Selection s, Selection newSize) { - if (!m_model || !s.getDuration()) return; + auto model = ModelById::getAs(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->getEventsStartingWithin(s.getStartFrame(), s.getDuration()); + model->getEventsStartingWithin(s.getStartFrame(), s.getDuration()); double ratio = double(newSize.getDuration()) / double(s.getDuration()); double oldStart = double(s.getStartFrame()); @@ -1117,13 +1158,14 @@ void NoteLayer::deleteSelection(Selection s) { - if (!m_model) return; + auto model = ModelById::getAs(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->getEventsStartingWithin(s.getStartFrame(), s.getDuration()); + model->getEventsStartingWithin(s.getStartFrame(), s.getDuration()); for (Event p: points) { command->remove(p); @@ -1135,10 +1177,11 @@ void NoteLayer::copy(LayerGeometryProvider *v, Selection s, Clipboard &to) { - if (!m_model) return; + auto model = ModelById::getAs(m_model); + if (!model) return; EventVector points = - m_model->getEventsStartingWithin(s.getStartFrame(), s.getDuration()); + model->getEventsStartingWithin(s.getStartFrame(), s.getDuration()); for (Event p: points) { to.addPoint(p.withReferenceFrame(alignToReference(v, p.getFrame()))); @@ -1149,7 +1192,8 @@ NoteLayer::paste(LayerGeometryProvider *v, const Clipboard &from, sv_frame_t /* frameOffset */, bool /* interactive */) { - if (!m_model) return false; + auto model = ModelById::getAs(m_model); + if (!model) return false; const EventVector &points = from.getPoints(); @@ -1173,7 +1217,7 @@ } ChangeEventsCommand *command = - new ChangeEventsCommand(m_model, tr("Paste")); + new ChangeEventsCommand(m_model.untyped, tr("Paste")); for (EventVector::const_iterator i = points.begin(); i != points.end(); ++i) { @@ -1197,8 +1241,8 @@ Event p = *i; Event newPoint = p; if (!p.hasValue()) { - newPoint = newPoint.withValue((m_model->getValueMinimum() + - m_model->getValueMaximum()) / 2); + newPoint = newPoint.withValue((model->getValueMinimum() + + model->getValueMaximum()) / 2); } if (!p.hasDuration()) { sv_frame_t nextFrame = frame; @@ -1210,7 +1254,7 @@ nextFrame = j->getFrame(); } if (nextFrame == frame) { - newPoint = newPoint.withDuration(m_model->getResolution()); + newPoint = newPoint.withDuration(model->getResolution()); } else { newPoint = newPoint.withDuration(nextFrame - frame); } @@ -1233,6 +1277,8 @@ void NoteLayer::addNoteOff(sv_frame_t frame, int pitch) { + auto model = ModelById::getAs(m_model); + for (NoteSet::iterator i = m_pendingNoteOns.begin(); i != m_pendingNoteOns.end(); ++i) { @@ -1241,9 +1287,9 @@ if (lrintf(p.getValue()) == pitch) { m_pendingNoteOns.erase(i); Event note = p.withDuration(frame - p.getFrame()); - if (m_model) { + if (model) { ChangeEventsCommand *c = new ChangeEventsCommand - (m_model, tr("Record Note")); + (m_model.untyped, tr("Record Note")); c->add(note); // execute and bundle: CommandHistory::getInstance()->addCommand(c, true, true); diff -r de41a11cabc2 -r ac0a8addabcf layer/NoteLayer.h --- a/layer/NoteLayer.h Thu Jun 13 15:35:01 2019 +0100 +++ b/layer/NoteLayer.h Wed Jul 17 14:25:16 2019 +0100 @@ -68,8 +68,8 @@ bool paste(LayerGeometryProvider *v, const Clipboard &from, sv_frame_t frameOffset, bool interactive) override; - const Model *getModel() const override { return m_model; } - void setModel(NoteModel *model); + ModelId getModel() const override { return m_model; } + void setModel(ModelId model); // a NoteModel PropertyList getProperties() const override; QString getPropertyLabel(const PropertyName &) const override; @@ -95,7 +95,7 @@ bool isLayerEditable() const override { return true; } - int getCompletion(LayerGeometryProvider *) const override { return m_model->getCompletion(); } + int getCompletion(LayerGeometryProvider *) const override; bool getValueExtents(double &min, double &max, bool &log, QString &unit) const override; @@ -146,7 +146,7 @@ bool getPointToDrag(LayerGeometryProvider *v, int x, int y, Event &) const; - NoteModel *m_model; + ModelId m_model; bool m_editing; int m_dragPointX; int m_dragPointY; diff -r de41a11cabc2 -r ac0a8addabcf layer/PaintAssistant.cpp --- a/layer/PaintAssistant.cpp Thu Jun 13 15:35:01 2019 +0100 +++ b/layer/PaintAssistant.cpp Wed Jul 17 14:25:16 2019 +0100 @@ -114,6 +114,11 @@ if (spaceForLabel) { + // 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" + int tx = 3; if (paint.fontMetrics().width(text) < w - 10) { tx = w - 10 - paint.fontMetrics().width(text); diff -r de41a11cabc2 -r ac0a8addabcf layer/PianoScale.cpp --- a/layer/PianoScale.cpp Thu Jun 13 15:35:01 2019 +0100 +++ b/layer/PianoScale.cpp Wed Jul 17 14:25:16 2019 +0100 @@ -58,7 +58,7 @@ QColor col = Qt::gray; if (i == 61) { // filling middle C col = Qt::blue; - col = col.light(150); + col = col.lighter(150); } if (ppy - y > 2) { paint.fillRect(x0 + 1, @@ -129,7 +129,7 @@ QColor col = Qt::gray; if (i == 61) { // filling middle C col = Qt::blue; - col = col.light(150); + col = col.lighter(150); } if (x - ppx > 2) { paint.fillRect((px + ppx) / 2 + 1, diff -r de41a11cabc2 -r ac0a8addabcf layer/RegionLayer.cpp --- a/layer/RegionLayer.cpp Thu Jun 13 15:35:01 2019 +0100 +++ b/layer/RegionLayer.cpp Wed Jul 17 14:25:16 2019 +0100 @@ -46,7 +46,6 @@ RegionLayer::RegionLayer() : SingleColourLayer(), - m_model(nullptr), m_editing(false), m_dragPointX(0), m_dragPointY(0), @@ -63,26 +62,44 @@ } +int +RegionLayer::getCompletion(LayerGeometryProvider *) const +{ + auto model = ModelById::get(m_model); + if (model) return model->getCompletion(); + else return 0; +} + void -RegionLayer::setModel(RegionModel *model) +RegionLayer::setModel(ModelId modelId) { - if (m_model == model) return; - m_model = model; + auto oldModel = ModelById::getAs(m_model); + auto newModel = ModelById::getAs(modelId); + + if (!modelId.isNone() && !newModel) { + throw std::logic_error("Not a RegionModel"); + } + + if (m_model == modelId) return; + m_model = modelId; - connectSignals(m_model); + if (newModel) { + + connectSignals(m_model); - connect(m_model, SIGNAL(modelChanged()), this, SLOT(recalcSpacing())); - recalcSpacing(); + connect(newModel.get(), SIGNAL(modelChanged()), + this, SLOT(recalcSpacing())); + + recalcSpacing(); -// SVDEBUG << "RegionLayer::setModel(" << model << ")" << endl; - - 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); - } - + emit modelReplaced(); } @@ -157,9 +174,10 @@ } else if (name == "Scale Units") { if (deflt) *deflt = 0; - if (m_model) { + auto model = ModelById::getAs(m_model); + if (model) { val = UnitDatabase::getInstance()->getUnitId - (getScaleUnits()); + (model->getScaleUnits()); } } else { @@ -206,10 +224,11 @@ } else if (name == "Vertical Scale") { setVerticalScale(VerticalScale(value)); } else if (name == "Scale Units") { - if (m_model) { - m_model->setScaleUnits + auto model = ModelById::getAs(m_model); + if (model) { + model->setScaleUnits (UnitDatabase::getInstance()->getUnitById(value)); - emit modelChanged(); + emit modelChanged(m_model); } } else { return SingleColourLayer::setProperty(name, value); @@ -257,11 +276,13 @@ { m_spacingMap.clear(); m_distributionMap.clear(); - if (!m_model) return; + + auto model = ModelById::getAs(m_model); + if (!model) return; // SVDEBUG << "RegionLayer::recalcSpacing" << endl; - EventVector allEvents = m_model->getAllEvents(); + EventVector allEvents = model->getAllEvents(); for (const Event &e: allEvents) { m_distributionMap[e.getValue()]++; // SVDEBUG << "RegionLayer::recalcSpacing: value found: " << e.getValue() << " (now have " << m_distributionMap[e.getValue()] << " of this value)" << endl; @@ -280,9 +301,10 @@ RegionLayer::getValueExtents(double &min, double &max, bool &logarithmic, QString &unit) const { - if (!m_model) return false; - min = m_model->getValueMinimum(); - max = m_model->getValueMaximum(); + auto model = ModelById::getAs(m_model); + if (!model) return false; + min = model->getValueMinimum(); + max = model->getValueMaximum(); unit = getScaleUnits(); if (m_verticalScale == LogScale) logarithmic = true; @@ -293,12 +315,13 @@ bool RegionLayer::getDisplayExtents(double &min, double &max) const { - if (!m_model || + auto model = ModelById::getAs(m_model); + if (!model || m_verticalScale == AutoAlignScale || m_verticalScale == EqualSpaced) return false; - min = m_model->getValueMinimum(); - max = m_model->getValueMaximum(); + min = model->getValueMinimum(); + max = model->getValueMaximum(); return true; } @@ -306,21 +329,22 @@ EventVector RegionLayer::getLocalPoints(LayerGeometryProvider *v, int x) const { - if (!m_model) return EventVector(); + auto model = ModelById::getAs(m_model); + if (!model) return EventVector(); sv_frame_t frame = v->getFrameForX(x); - EventVector local = m_model->getEventsCovering(frame); + EventVector local = model->getEventsCovering(frame); if (!local.empty()) return local; int fuzz = ViewManager::scalePixelSize(2); sv_frame_t start = v->getFrameForX(x - fuzz); sv_frame_t end = v->getFrameForX(x + fuzz); - local = m_model->getEventsStartingWithin(frame, end - frame); + local = model->getEventsStartingWithin(frame, end - frame); if (!local.empty()) return local; - local = m_model->getEventsSpanning(start, frame - start); + local = model->getEventsSpanning(start, frame - start); if (!local.empty()) return local; return {}; @@ -329,11 +353,12 @@ bool RegionLayer::getPointToDrag(LayerGeometryProvider *v, int x, int y, Event &point) const { - if (!m_model) return false; + auto model = ModelById::getAs(m_model); + if (!model) return false; sv_frame_t frame = v->getFrameForX(x); - EventVector onPoints = m_model->getEventsCovering(frame); + EventVector onPoints = model->getEventsCovering(frame); if (onPoints.empty()) return false; int nearestDistance = -1; @@ -352,9 +377,10 @@ QString RegionLayer::getLabelPreceding(sv_frame_t frame) const { - if (!m_model) return ""; - EventVector points = m_model->getEventsStartingWithin - (m_model->getStartFrame(), frame - m_model->getStartFrame()); + auto model = ModelById::getAs(m_model); + if (!model) return ""; + EventVector points = model->getEventsStartingWithin + (model->getStartFrame(), frame - model->getStartFrame()); if (!points.empty()) { for (auto i = points.rbegin(); i != points.rend(); ++i) { if (i->getLabel() != QString()) { @@ -370,12 +396,13 @@ { int x = pos.x(); - if (!m_model || !m_model->getSampleRate()) return ""; + auto model = ModelById::getAs(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"); @@ -393,9 +420,9 @@ int y = getYForValue(v, i->getValue()); int h = 3; - if (m_model->getValueQuantization() != 0.0) { + if (model->getValueQuantization() != 0.0) { h = y - getYForValue - (v, i->getValue() + m_model->getValueQuantization()); + (v, i->getValue() + model->getValueQuantization()); if (h < 3) h = 3; } @@ -408,9 +435,9 @@ if (i == points.end()) return tr("No local points"); RealTime rt = RealTime::frame2RealTime(region.getFrame(), - m_model->getSampleRate()); + model->getSampleRate()); RealTime rd = RealTime::frame2RealTime(region.getDuration(), - m_model->getSampleRate()); + model->getSampleRate()); QString valueText; @@ -441,7 +468,8 @@ int &resolution, SnapType snap) const { - if (!m_model) { + auto model = ModelById::getAs(m_model); + if (!model) { return Layer::snapToFeatureFrame(v, frame, resolution, snap); } @@ -452,7 +480,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)); @@ -469,7 +497,7 @@ Event left; bool haveLeft = false; - if (m_model->getNearestEventMatching + if (model->getNearestEventMatching (frame, [](Event) { return true; }, EventSeries::Backward, left)) { haveLeft = true; } @@ -481,7 +509,7 @@ Event right; bool haveRight = false; - if (m_model->getNearestEventMatching + if (model->getNearestEventMatching (frame, [](Event) { return true; }, EventSeries::Forward, right)) { haveRight = true; } @@ -515,7 +543,8 @@ int &resolution, SnapType snap) const { - if (!m_model) { + auto model = ModelById::getAs(m_model); + if (!model) { return Layer::snapToSimilarFeature(v, frame, resolution, snap); } @@ -523,14 +552,14 @@ // don't do the same trick as in snapToFeatureFrame, of snapping // to the end of a feature sometimes. - 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) { @@ -539,7 +568,7 @@ matchvalue = ref.getValue(); - found = m_model->getNearestEventMatching + found = model->getNearestEventMatching (frame, [matchvalue](Event e) { double epsilon = 0.0001; @@ -559,7 +588,8 @@ QString RegionLayer::getScaleUnits() const { - if (m_model) return m_model->getScaleUnits(); + auto model = ModelById::getAs(m_model); + if (model) return model->getScaleUnits(); else return ""; } @@ -570,6 +600,9 @@ max = 0.0; log = false; + auto model = ModelById::getAs(m_model); + if (!model) return; + QString queryUnits; queryUnits = getScaleUnits(); @@ -577,8 +610,8 @@ if (!v->getValueExtents(queryUnits, min, max, log)) { - min = m_model->getValueMinimum(); - max = m_model->getValueMaximum(); + min = model->getValueMinimum(); + max = model->getValueMaximum(); // cerr << "RegionLayer[" << this << "]::getScaleExtents: min = " << min << ", max = " << max << ", log = " << log << endl; @@ -603,8 +636,8 @@ } else { - min = m_model->getValueMinimum(); - max = m_model->getValueMaximum(); + min = model->getValueMinimum(); + max = model->getValueMaximum(); if (m_verticalScale == LogScale) { LogRange::mapRange(min, max); @@ -808,9 +841,10 @@ void RegionLayer::paint(LayerGeometryProvider *v, QPainter &paint, QRect rect) const { - if (!m_model || !m_model->isOK()) return; + auto model = ModelById::getAs(m_model); + if (!model || !model->isOK()) return; - sv_samplerate_t sampleRate = m_model->getSampleRate(); + sv_samplerate_t sampleRate = model->getSampleRate(); if (!sampleRate) return; // Profiler profiler("RegionLayer::paint", true); @@ -820,7 +854,7 @@ sv_frame_t wholeFrame0 = v->getFrameForX(0); sv_frame_t wholeFrame1 = v->getFrameForX(v->getPaintWidth()); - EventVector points(m_model->getEventsSpanning(wholeFrame0, + EventVector points(model->getEventsSpanning(wholeFrame0, wholeFrame1 - wholeFrame0)); if (points.empty()) return; @@ -830,10 +864,10 @@ brushColour.setAlpha(80); // SVDEBUG << "RegionLayer::paint: resolution is " -// << m_model->getResolution() << " frames" << endl; +// << model->getResolution() << " frames" << endl; - 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; QPoint localPos; @@ -878,9 +912,9 @@ if (nx < ex) ex = nx; } - if (m_model->getValueQuantization() != 0.0) { + if (model->getValueQuantization() != 0.0) { h = y - getYForValue - (v, p.getValue() + m_model->getValueQuantization()); + (v, p.getValue() + model->getValueQuantization()); if (h < 3) h = 3; } @@ -917,6 +951,11 @@ paint.setPen(v->getForeground()); paint.setBrush(v->getForeground()); + // 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" + QString vlabel = QString("%1%2").arg(p.getValue()).arg(getScaleUnits()); PaintAssistant::drawVisibleText(v, paint, @@ -926,7 +965,7 @@ vlabel, PaintAssistant::OutlinedText); QString hlabel = RealTime::frame2RealTime - (p.getFrame(), m_model->getSampleRate()).toText(true).c_str(); + (p.getFrame(), model->getSampleRate()).toText(true).c_str(); PaintAssistant::drawVisibleText(v, paint, x, y - h/2 - paint.fontMetrics().descent() - gap, @@ -1009,7 +1048,8 @@ int RegionLayer::getVerticalScaleWidth(LayerGeometryProvider *v, bool, QPainter &paint) const { - if (!m_model || + auto model = ModelById::getAs(m_model); + if (!model || m_verticalScale == AutoAlignScale || m_verticalScale == EqualSpaced) { return 0; @@ -1031,7 +1071,8 @@ void RegionLayer::paintVerticalScale(LayerGeometryProvider *v, bool, QPainter &paint, QRect) const { - if (!m_model || m_model->isEmpty()) return; + auto model = ModelById::getAs(m_model); + if (!model || model->isEmpty()) return; QString unit; double min, max; @@ -1074,11 +1115,12 @@ void RegionLayer::drawStart(LayerGeometryProvider *v, QMouseEvent *e) { - if (!m_model) return; + auto model = ModelById::getAs(m_model); + if (!model) 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()); @@ -1086,8 +1128,7 @@ m_originalPoint = m_editingPoint; if (m_editingCommand) finish(m_editingCommand); - m_editingCommand = new ChangeEventsCommand(m_model, - tr("Draw Region")); + m_editingCommand = new ChangeEventsCommand(m_model.untyped, tr("Draw Region")); m_editingCommand->add(m_editingPoint); recalcSpacing(); @@ -1098,11 +1139,12 @@ void RegionLayer::drawDrag(LayerGeometryProvider *v, QMouseEvent *e) { - if (!m_model || !m_editing) return; + auto model = ModelById::getAs(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 newValue = m_editingPoint.getValue(); if (m_verticalScale != EqualSpaced) newValue = getValueForY(v, e->y()); @@ -1129,7 +1171,8 @@ void RegionLayer::drawEnd(LayerGeometryProvider *, QMouseEvent *) { - if (!m_model || !m_editing) return; + auto model = ModelById::getAs(m_model); + if (!model || !m_editing) return; finish(m_editingCommand); m_editingCommand = nullptr; m_editing = false; @@ -1140,7 +1183,8 @@ void RegionLayer::eraseStart(LayerGeometryProvider *v, QMouseEvent *e) { - if (!m_model) return; + auto model = ModelById::getAs(m_model); + if (!model) return; if (!getPointToDrag(v, e->x(), e->y(), m_editingPoint)) return; @@ -1161,7 +1205,8 @@ void RegionLayer::eraseEnd(LayerGeometryProvider *v, QMouseEvent *e) { - if (!m_model || !m_editing) return; + auto model = ModelById::getAs(m_model); + if (!model || !m_editing) return; m_editing = false; @@ -1171,7 +1216,7 @@ p.getValue() != m_editingPoint.getValue()) return; m_editingCommand = new ChangeEventsCommand - (m_model, tr("Erase Region")); + (m_model.untyped, tr("Erase Region")); m_editingCommand->remove(m_editingPoint); @@ -1184,7 +1229,8 @@ void RegionLayer::editStart(LayerGeometryProvider *v, QMouseEvent *e) { - if (!m_model) return; + auto model = ModelById::getAs(m_model); + if (!model) return; if (!getPointToDrag(v, e->x(), e->y(), m_editingPoint)) { return; @@ -1209,7 +1255,8 @@ void RegionLayer::editDrag(LayerGeometryProvider *v, QMouseEvent *e) { - if (!m_model || !m_editing) return; + auto model = ModelById::getAs(m_model); + if (!model || !m_editing) return; int xdist = e->x() - m_dragStartX; int ydist = e->y() - m_dragStartY; @@ -1218,7 +1265,7 @@ sv_frame_t frame = v->getFrameForX(newx); if (frame < 0) frame = 0; - frame = frame / m_model->getResolution() * m_model->getResolution(); + frame = frame / model->getResolution() * model->getResolution(); // Do not bisect between two values, if one of those values is // that of the point we're actually moving ... @@ -1230,7 +1277,7 @@ double value = getValueForY(v, newy, avoid); if (!m_editingCommand) { - m_editingCommand = new ChangeEventsCommand(m_model, + m_editingCommand = new ChangeEventsCommand(m_model.untyped, tr("Drag Region")); } @@ -1245,7 +1292,8 @@ void RegionLayer::editEnd(LayerGeometryProvider *, QMouseEvent *) { - if (!m_model || !m_editing) return; + auto model = ModelById::getAs(m_model); + if (!model || !m_editing) return; if (m_editingCommand) { @@ -1273,13 +1321,14 @@ bool RegionLayer::editOpen(LayerGeometryProvider *v, QMouseEvent *e) { - if (!m_model) return false; + auto model = ModelById::getAs(m_model); + if (!model) return false; Event region(0); if (!getPointToDrag(v, e->x(), e->y(), region)) return false; ItemEditDialog *dialog = new ItemEditDialog - (m_model->getSampleRate(), + (model->getSampleRate(), ItemEditDialog::ShowTime | ItemEditDialog::ShowDuration | ItemEditDialog::ShowValue | @@ -1300,7 +1349,7 @@ .withLabel(dialog->getText()); ChangeEventsCommand *command = new ChangeEventsCommand - (m_model, tr("Edit Region")); + (m_model.untyped, tr("Edit Region")); command->remove(region); command->add(newRegion); finish(command); @@ -1314,13 +1363,14 @@ void RegionLayer::moveSelection(Selection s, sv_frame_t newStartFrame) { - if (!m_model) return; + auto model = ModelById::getAs(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->getEventsStartingWithin(s.getStartFrame(), s.getDuration()); + model->getEventsStartingWithin(s.getStartFrame(), s.getDuration()); for (EventVector::iterator i = points.begin(); i != points.end(); ++i) { @@ -1338,13 +1388,14 @@ void RegionLayer::resizeSelection(Selection s, Selection newSize) { - if (!m_model || !s.getDuration()) return; + auto model = ModelById::getAs(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->getEventsStartingWithin(s.getStartFrame(), s.getDuration()); + model->getEventsStartingWithin(s.getStartFrame(), s.getDuration()); double ratio = double(newSize.getDuration()) / double(s.getDuration()); double oldStart = double(s.getStartFrame()); @@ -1369,13 +1420,14 @@ void RegionLayer::deleteSelection(Selection s) { - if (!m_model) return; + auto model = ModelById::getAs(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->getEventsStartingWithin(s.getStartFrame(), s.getDuration()); + model->getEventsStartingWithin(s.getStartFrame(), s.getDuration()); for (EventVector::iterator i = points.begin(); i != points.end(); ++i) { @@ -1392,10 +1444,11 @@ void RegionLayer::copy(LayerGeometryProvider *v, Selection s, Clipboard &to) { - if (!m_model) return; + auto model = ModelById::getAs(m_model); + if (!model) return; EventVector points = - m_model->getEventsStartingWithin(s.getStartFrame(), s.getDuration()); + model->getEventsStartingWithin(s.getStartFrame(), s.getDuration()); for (Event p: points) { to.addPoint(p.withReferenceFrame(alignToReference(v, p.getFrame()))); @@ -1405,7 +1458,8 @@ bool RegionLayer::paste(LayerGeometryProvider *v, const Clipboard &from, sv_frame_t /* frameOffset */, bool /* interactive */) { - if (!m_model) return false; + auto model = ModelById::getAs(m_model); + if (!model) return false; const EventVector &points = from.getPoints(); @@ -1429,7 +1483,7 @@ } ChangeEventsCommand *command = - new ChangeEventsCommand(m_model, tr("Paste")); + new ChangeEventsCommand(m_model.untyped, tr("Paste")); for (EventVector::const_iterator i = points.begin(); i != points.end(); ++i) { @@ -1453,8 +1507,8 @@ Event p = *i; Event newPoint = p; if (!p.hasValue()) { - newPoint = newPoint.withValue((m_model->getValueMinimum() + - m_model->getValueMaximum()) / 2); + newPoint = newPoint.withValue((model->getValueMinimum() + + model->getValueMaximum()) / 2); } if (!p.hasDuration()) { sv_frame_t nextFrame = frame; @@ -1466,7 +1520,7 @@ nextFrame = j->getFrame(); } if (nextFrame == frame) { - newPoint = newPoint.withDuration(m_model->getResolution()); + newPoint = newPoint.withDuration(model->getResolution()); } else { newPoint = newPoint.withDuration(nextFrame - frame); } diff -r de41a11cabc2 -r ac0a8addabcf layer/RegionLayer.h --- a/layer/RegionLayer.h Thu Jun 13 15:35:01 2019 +0100 +++ b/layer/RegionLayer.h Wed Jul 17 14:25:16 2019 +0100 @@ -76,8 +76,8 @@ bool paste(LayerGeometryProvider *v, const Clipboard &from, sv_frame_t frameOffset, bool interactive) override; - const Model *getModel() const override { return m_model; } - void setModel(RegionModel *model); + ModelId getModel() const override { return m_model; } + void setModel(ModelId model); // a RegionModel PropertyList getProperties() const override; QString getPropertyLabel(const PropertyName &) const override; @@ -114,7 +114,7 @@ bool isLayerEditable() const override { return true; } - int getCompletion(LayerGeometryProvider *) const override { return m_model->getCompletion(); } + int getCompletion(LayerGeometryProvider *) const override; bool getValueExtents(double &min, double &max, bool &log, QString &unit) const override; @@ -145,7 +145,7 @@ bool getPointToDrag(LayerGeometryProvider *v, int x, int y, Event &) const; - RegionModel *m_model; + ModelId m_model; bool m_editing; int m_dragPointX; int m_dragPointY; diff -r de41a11cabc2 -r ac0a8addabcf layer/SliceLayer.cpp --- a/layer/SliceLayer.cpp Thu Jun 13 15:35:01 2019 +0100 +++ b/layer/SliceLayer.cpp Wed Jul 17 14:25:16 2019 +0100 @@ -32,7 +32,6 @@ SliceLayer::SliceLayer() : - m_sliceableModel(nullptr), m_binAlignment(BinsSpanScalePoints), m_colourMap(int(ColourMapper::Ice)), m_colourInverted(false), @@ -57,27 +56,24 @@ } void -SliceLayer::setSliceableModel(const Model *model) +SliceLayer::setSliceableModel(ModelId modelId) { - const DenseThreeDimensionalModel *sliceable = - dynamic_cast(model); - - if (model && !sliceable) { - cerr << "WARNING: SliceLayer::setSliceableModel(" << model - << "): model is not a DenseThreeDimensionalModel" << endl; + auto newModel = ModelById::getAs(modelId); + + if (!modelId.isNone() && !newModel) { + throw std::logic_error("Not a DenseThreeDimensionalModel"); } - if (m_sliceableModel == sliceable) return; + if (m_sliceableModel == modelId) return; + m_sliceableModel = modelId; - m_sliceableModel = sliceable; + if (newModel) { + connectSignals(m_sliceableModel); - if (!m_sliceableModel) return; - - connectSignals(m_sliceableModel); - - if (m_minbin == 0 && m_maxbin == 0) { - m_minbin = 0; - m_maxbin = m_sliceableModel->getHeight(); + if (m_minbin == 0 && m_maxbin == 0) { + m_minbin = 0; + m_maxbin = newModel->getHeight(); + } } emit modelReplaced(); @@ -85,23 +81,12 @@ } void -SliceLayer::sliceableModelReplaced(const Model *orig, const Model *replacement) +SliceLayer::sliceableModelReplaced(ModelId orig, ModelId replacement) { SVDEBUG << "SliceLayer::sliceableModelReplaced(" << orig << ", " << replacement << ")" << endl; if (orig == m_sliceableModel) { - setSliceableModel - (dynamic_cast(replacement)); - } -} - -void -SliceLayer::modelAboutToBeDeleted(Model *m) -{ - SVDEBUG << "SliceLayer::modelAboutToBeDeleted(" << m << ")" << endl; - - if (m == m_sliceableModel) { - setSliceableModel(nullptr); + setSliceableModel(replacement); } } @@ -119,7 +104,10 @@ { minbin = 0; maxbin = 0; - if (!m_sliceableModel) return ""; + + auto sliceableModel = + ModelById::getAs(m_sliceableModel); + if (!sliceableModel) return ""; if (m_binAlignment == BinsSpanScalePoints) { minbin = int(getBinForX(v, p.x())); @@ -129,13 +117,13 @@ maxbin = int(getBinForX(v, p.x() + 1) + 0.5); } - int mh = m_sliceableModel->getHeight(); + int mh = sliceableModel->getHeight(); if (minbin >= mh) minbin = mh - 1; if (maxbin >= mh) maxbin = mh - 1; if (minbin < 0) minbin = 0; if (maxbin < 0) maxbin = 0; - sv_samplerate_t sampleRate = m_sliceableModel->getSampleRate(); + sv_samplerate_t sampleRate = sliceableModel->getSampleRate(); sv_frame_t f0 = m_currentf0; sv_frame_t f1 = m_currentf1; @@ -420,9 +408,11 @@ void SliceLayer::paint(LayerGeometryProvider *v, QPainter &paint, QRect rect) const { - if (!m_sliceableModel || - !m_sliceableModel->isOK() || - !m_sliceableModel->isReady()) return; + auto sliceableModel = + ModelById::getAs(m_sliceableModel); + if (!sliceableModel || + !sliceableModel->isOK() || + !sliceableModel->isReady()) return; Profiler profiler("SliceLayer::paint()"); @@ -442,7 +432,7 @@ } } - int mh = m_sliceableModel->getHeight(); + int mh = sliceableModel->getHeight(); int bin0 = 0; if (m_maxbin > m_minbin) { mh = m_maxbin - m_minbin; @@ -493,7 +483,7 @@ // cerr << "centre frame " << v->getCentreFrame() << ", x " << f0x << ", f0 " << f0 << ", f1 " << f1 << endl; - int res = m_sliceableModel->getResolution(); + int res = sliceableModel->getResolution(); int col0 = int(f0 / res); int col1 = col0; if (m_samplingMode != NearestSample) col1 = int(f1 / res); @@ -512,7 +502,7 @@ for (int col = col0; col <= col1; ++col) { DenseThreeDimensionalModel::Column column = - m_sliceableModel->getColumn(col); + sliceableModel->getColumn(col); for (int bin = 0; bin < mh; ++bin) { float value = column[bin0 + bin]; if (bin < cs) value *= curve[bin]; @@ -674,6 +664,11 @@ int SliceLayer::getVerticalScaleWidth(LayerGeometryProvider *, bool, QPainter &paint) const { + // 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" + int width; if (m_energyScale == LinearScale || m_energyScale == AbsoluteScale) { width = std::max(paint.fontMetrics().width("0.0") + 13, @@ -1166,10 +1161,12 @@ SliceLayer::getValueExtents(double &min, double &max, bool &logarithmic, QString &unit) const { - if (!m_sliceableModel) return false; + auto sliceableModel = + ModelById::getAs(m_sliceableModel); + if (!sliceableModel) return false; min = 0; - max = double(m_sliceableModel->getHeight()); + max = double(sliceableModel->getHeight()); logarithmic = (m_binScale == BinScale::LogBins); unit = ""; @@ -1180,9 +1177,11 @@ bool SliceLayer::getDisplayExtents(double &min, double &max) const { - if (!m_sliceableModel) return false; + auto sliceableModel = + ModelById::getAs(m_sliceableModel); + if (!sliceableModel) return false; - double hmax = double(m_sliceableModel->getHeight()); + double hmax = double(sliceableModel->getHeight()); min = m_minbin; max = m_maxbin; @@ -1199,7 +1198,9 @@ bool SliceLayer::setDisplayExtents(double min, double max) { - if (!m_sliceableModel) return false; + auto sliceableModel = + ModelById::getAs(m_sliceableModel); + if (!sliceableModel) return false; m_minbin = int(lrint(min)); m_maxbin = int(lrint(max)); @@ -1210,11 +1211,11 @@ if (m_maxbin < 0) { m_maxbin = 0; } - if (m_minbin > m_sliceableModel->getHeight()) { - m_minbin = m_sliceableModel->getHeight(); + if (m_minbin > sliceableModel->getHeight()) { + m_minbin = sliceableModel->getHeight(); } - if (m_maxbin > m_sliceableModel->getHeight()) { - m_maxbin = m_sliceableModel->getHeight(); + if (m_maxbin > sliceableModel->getHeight()) { + m_maxbin = sliceableModel->getHeight(); } if (m_maxbin < m_minbin) { m_maxbin = m_minbin; @@ -1227,31 +1228,37 @@ int SliceLayer::getVerticalZoomSteps(int &defaultStep) const { - if (!m_sliceableModel) return 0; + auto sliceableModel = + ModelById::getAs(m_sliceableModel); + if (!sliceableModel) return 0; defaultStep = 0; - int h = m_sliceableModel->getHeight(); + int h = sliceableModel->getHeight(); return h; } int SliceLayer::getCurrentVerticalZoomStep() const { - if (!m_sliceableModel) return 0; + auto sliceableModel = + ModelById::getAs(m_sliceableModel); + if (!sliceableModel) return 0; double min, max; getDisplayExtents(min, max); - return m_sliceableModel->getHeight() - int(lrint(max - min)); + return sliceableModel->getHeight() - int(lrint(max - min)); } void SliceLayer::setVerticalZoomStep(int step) { - if (!m_sliceableModel) return; + auto sliceableModel = + ModelById::getAs(m_sliceableModel); + if (!sliceableModel) return; // SVDEBUG << "SliceLayer::setVerticalZoomStep(" <getHeight(), + 0, sliceableModel->getHeight(), ""); } void diff -r de41a11cabc2 -r ac0a8addabcf layer/SliceLayer.h --- a/layer/SliceLayer.h Thu Jun 13 15:35:01 2019 +0100 +++ b/layer/SliceLayer.h Wed Jul 17 14:25:16 2019 +0100 @@ -32,9 +32,9 @@ SliceLayer(); ~SliceLayer(); - const Model *getModel() const override { return 0; } + ModelId getModel() const override { return {}; } - void setSliceableModel(const Model *model); + void setSliceableModel(ModelId model); void paint(LayerGeometryProvider *v, QPainter &paint, QRect rect) const override; @@ -117,8 +117,7 @@ QString extraAttributes = "") const override; public slots: - void sliceableModelReplaced(const Model *, const Model *); - void modelAboutToBeDeleted(Model *); + void sliceableModelReplaced(ModelId, ModelId); protected: /// Convert a (possibly non-integral) bin into x-coord. May be overridden @@ -171,28 +170,28 @@ BinsSpanScalePoints }; - const DenseThreeDimensionalModel *m_sliceableModel; - BinAlignment m_binAlignment; - int m_colourMap; - bool m_colourInverted; - EnergyScale m_energyScale; - SamplingMode m_samplingMode; - PlotStyle m_plotStyle; - BinScale m_binScale; - bool m_normalize; - float m_threshold; - float m_initialThreshold; - float m_gain; - int m_minbin; - int m_maxbin; - mutable std::vector m_scalePoints; - mutable int m_scalePaintHeight; - mutable std::map m_xorigins; // LayerGeometryProvider id -> x - mutable std::map m_yorigins; // LayerGeometryProvider id -> y - mutable std::map m_heights; // LayerGeometryProvider id -> h - mutable sv_frame_t m_currentf0; - mutable sv_frame_t m_currentf1; - mutable std::vector m_values; + ModelId m_sliceableModel; // a DenseThreeDimensionalModel + BinAlignment m_binAlignment; + int m_colourMap; + bool m_colourInverted; + EnergyScale m_energyScale; + SamplingMode m_samplingMode; + PlotStyle m_plotStyle; + BinScale m_binScale; + bool m_normalize; + float m_threshold; + float m_initialThreshold; + float m_gain; + int m_minbin; + int m_maxbin; + mutable std::vector m_scalePoints; + mutable int m_scalePaintHeight; + mutable std::map m_xorigins; // LayerGeometryProvider id -> x + mutable std::map m_yorigins; // LayerGeometryProvider id -> y + mutable std::map m_heights; // LayerGeometryProvider id -> h + mutable sv_frame_t m_currentf0; + mutable sv_frame_t m_currentf1; + mutable std::vector m_values; }; #endif diff -r de41a11cabc2 -r ac0a8addabcf layer/SliceableLayer.h --- a/layer/SliceableLayer.h Thu Jun 13 15:35:01 2019 +0100 +++ b/layer/SliceableLayer.h Wed Jul 17 14:25:16 2019 +0100 @@ -34,14 +34,15 @@ // spectrogram that was constructed from a DenseTimeValueModel). // The SliceableLayer retains ownership of the model, and will // emit sliceableModelReplaced if it is about to become invalid. - virtual const Model *getSliceableModel() const = 0; - + virtual ModelId getSliceableModel() const = 0; +/*!!! signals: // Emitted when a model that was obtained through // getSliceableModel is about to be deleted. If replacement is // non-NULL, it may be used instead. void sliceableModelReplaced(const Model *modelToBeReplaced, const Model *replacement); +*/ }; #endif diff -r de41a11cabc2 -r ac0a8addabcf layer/SpectrogramLayer.cpp --- a/layer/SpectrogramLayer.cpp Thu Jun 13 15:35:01 2019 +0100 +++ b/layer/SpectrogramLayer.cpp Wed Jul 17 14:25:16 2019 +0100 @@ -56,7 +56,6 @@ using namespace std; SpectrogramLayer::SpectrogramLayer(Configuration config) : - m_model(nullptr), m_channel(0), m_windowSize(1024), m_windowType(HanningWindow), @@ -83,9 +82,6 @@ m_synchronous(false), m_haveDetailedScale(false), m_exiting(false), - m_fftModel(nullptr), - m_wholeCache(nullptr), - m_peakCache(nullptr), m_peakCacheDivisor(8) { QString colourConfigName = "spectrogram-colour"; @@ -140,17 +136,13 @@ void SpectrogramLayer::deleteDerivedModels() { - if (m_fftModel) m_fftModel->aboutToDelete(); - if (m_peakCache) m_peakCache->aboutToDelete(); - if (m_wholeCache) m_wholeCache->aboutToDelete(); - - delete m_fftModel; - delete m_peakCache; - delete m_wholeCache; - - m_fftModel = nullptr; - m_peakCache = nullptr; - m_wholeCache = nullptr; + ModelById::release(m_fftModel); + ModelById::release(m_peakCache); + ModelById::release(m_wholeCache); + + m_fftModel = {}; + m_peakCache = {}; + m_wholeCache = {}; } pair @@ -208,24 +200,29 @@ } void -SpectrogramLayer::setModel(const DenseTimeValueModel *model) +SpectrogramLayer::setModel(ModelId modelId) { -// cerr << "SpectrogramLayer(" << this << "): setModel(" << model << ")" << endl; - - if (model == m_model) return; - - m_model = model; - - recreateFFTModel(); - - if (!m_model || !m_model->isOK()) return; - - connectSignals(m_model); - - connect(m_model, SIGNAL(modelChanged()), this, SLOT(cacheInvalid())); - connect(m_model, SIGNAL(modelChangedWithin(sv_frame_t, sv_frame_t)), - this, SLOT(cacheInvalid(sv_frame_t, sv_frame_t))); - + auto newModel = ModelById::getAs(modelId); + if (!modelId.isNone() && !newModel) { + throw std::logic_error("Not a DenseTimeValueModel"); + } + + if (modelId == m_model) return; + m_model = modelId; + + if (newModel) { + recreateFFTModel(); + + connectSignals(m_model); + + connect(newModel.get(), + SIGNAL(modelChanged(ModelId)), + this, SLOT(cacheInvalid(ModelId))); + connect(newModel.get(), + SIGNAL(modelChangedWithin(ModelId, sv_frame_t, sv_frame_t)), + this, SLOT(cacheInvalid(ModelId, sv_frame_t, sv_frame_t))); + } + emit modelReplaced(); } @@ -1063,7 +1060,7 @@ } void -SpectrogramLayer::cacheInvalid() +SpectrogramLayer::cacheInvalid(ModelId) { #ifdef DEBUG_SPECTROGRAM_REPAINT cerr << "SpectrogramLayer::cacheInvalid()" << endl; @@ -1075,6 +1072,7 @@ void SpectrogramLayer::cacheInvalid( + ModelId, #ifdef DEBUG_SPECTROGRAM_REPAINT sv_frame_t from, sv_frame_t to #else @@ -1106,7 +1104,10 @@ double SpectrogramLayer::getEffectiveMinFrequency() const { - sv_samplerate_t sr = m_model->getSampleRate(); + auto model = ModelById::getAs(m_model); + if (!model) return 0.0; + + sv_samplerate_t sr = model->getSampleRate(); double minf = double(sr) / getFFTSize(); if (m_minFrequency > 0.0) { @@ -1121,7 +1122,10 @@ double SpectrogramLayer::getEffectiveMaxFrequency() const { - sv_samplerate_t sr = m_model->getSampleRate(); + auto model = ModelById::getAs(m_model); + if (!model) return 0.0; + + sv_samplerate_t sr = model->getSampleRate(); double maxf = double(sr) / 2; if (m_maxFrequency > 0.0) { @@ -1147,10 +1151,13 @@ double SpectrogramLayer::getYForBin(const LayerGeometryProvider *v, double bin) const { + auto model = ModelById::getAs(m_model); + if (!model) return 0.0; + double minf = getEffectiveMinFrequency(); double maxf = getEffectiveMaxFrequency(); bool logarithmic = (m_binScale == BinScale::Log); - sv_samplerate_t sr = m_model->getSampleRate(); + sv_samplerate_t sr = model->getSampleRate(); double freq = (bin * sr) / getFFTSize(); @@ -1162,7 +1169,10 @@ double SpectrogramLayer::getBinForY(const LayerGeometryProvider *v, double y) const { - sv_samplerate_t sr = m_model->getSampleRate(); + auto model = ModelById::getAs(m_model); + if (!model) return 0.0; + + sv_samplerate_t sr = model->getSampleRate(); double minf = getEffectiveMinFrequency(); double maxf = getEffectiveMaxFrequency(); @@ -1179,8 +1189,11 @@ bool SpectrogramLayer::getXBinRange(LayerGeometryProvider *v, int x, double &s0, double &s1) const { - sv_frame_t modelStart = m_model->getStartFrame(); - sv_frame_t modelEnd = m_model->getEndFrame(); + auto model = ModelById::getAs(m_model); + if (!model) return false; + + sv_frame_t modelStart = model->getStartFrame(); + sv_frame_t modelEnd = model->getEndFrame(); // Each pixel column covers an exact range of sample frames: sv_frame_t f0 = v->getFrameForX(x) - modelStart; @@ -1203,6 +1216,9 @@ bool SpectrogramLayer::getXBinSourceRange(LayerGeometryProvider *v, int x, RealTime &min, RealTime &max) const { + auto model = ModelById::getAs(m_model); + if (!model) return false; + double s0 = 0, s1 = 0; if (!getXBinRange(v, x, s0, s1)) return false; @@ -1214,8 +1230,8 @@ int w1 = s1i * windowIncrement + windowIncrement + (m_windowSize - windowIncrement)/2 - 1; - min = RealTime::frame2RealTime(w0, m_model->getSampleRate()); - max = RealTime::frame2RealTime(w1, m_model->getSampleRate()); + min = RealTime::frame2RealTime(w0, model->getSampleRate()); + max = RealTime::frame2RealTime(w1, model->getSampleRate()); return true; } @@ -1223,13 +1239,16 @@ SpectrogramLayer::getYBinSourceRange(LayerGeometryProvider *v, int y, double &freqMin, double &freqMax) const { + auto model = ModelById::getAs(m_model); + if (!model) return false; + double q0 = 0, q1 = 0; if (!getYBinRange(v, y, q0, q1)) return false; int q0i = int(q0 + 0.001); int q1i = int(q1); - sv_samplerate_t sr = m_model->getSampleRate(); + sv_samplerate_t sr = model->getSampleRate(); for (int q = q0i; q <= q1i; ++q) { if (q == q0i) freqMin = (sr * q) / getFFTSize(); @@ -1244,11 +1263,12 @@ double &adjFreqMin, double &adjFreqMax) const { - if (!m_model || !m_model->isOK() || !m_model->isReady()) { + auto model = ModelById::getAs(m_model); + if (!model || !model->isOK() || !model->isReady()) { return false; } - FFTModel *fft = getFFTModel(); + auto fft = ModelById::getAs(m_fftModel); if (!fft) return false; double s0 = 0, s1 = 0; @@ -1263,7 +1283,7 @@ int q0i = int(q0 + 0.001); int q1i = int(q1); - sv_samplerate_t sr = m_model->getSampleRate(); + sv_samplerate_t sr = model->getSampleRate(); bool haveAdj = false; @@ -1311,7 +1331,8 @@ double &min, double &max, double &phaseMin, double &phaseMax) const { - if (!m_model || !m_model->isOK() || !m_model->isReady()) { + auto model = ModelById::getAs(m_model); + if (!model || !model->isOK() || !model->isReady()) { return false; } @@ -1329,7 +1350,7 @@ bool rv = false; - FFTModel *fft = getFFTModel(); + auto fft = ModelById::getAs(m_fftModel); if (fft) { @@ -1374,55 +1395,51 @@ { SVDEBUG << "SpectrogramLayer::recreateFFTModel called" << endl; - if (!m_model || !m_model->isOK()) { - emit sliceableModelReplaced(m_fftModel, nullptr); - deleteDerivedModels(); - return; + { // scope, avoid hanging on to this pointer + auto model = ModelById::getAs(m_model); + if (!model || !model->isOK()) { + deleteDerivedModels(); + return; + } } - - if (m_fftModel) m_fftModel->aboutToDelete(); - if (m_peakCache) m_peakCache->aboutToDelete(); - delete m_peakCache; - m_peakCache = nullptr; - - if (m_wholeCache) m_wholeCache->aboutToDelete(); - delete m_wholeCache; - m_wholeCache = nullptr; - - FFTModel *newModel = new FFTModel(m_model, - m_channel, - m_windowType, - m_windowSize, - getWindowIncrement(), - getFFTSize()); - - if (!newModel->isOK()) { + deleteDerivedModels(); + + auto newFFTModel = std::make_shared(m_model, + m_channel, + m_windowType, + m_windowSize, + getWindowIncrement(), + getFFTSize()); + + if (!newFFTModel->isOK()) { QMessageBox::critical (nullptr, tr("FFT cache failed"), tr("Failed to create the FFT model for this spectrogram.\n" "There may be insufficient memory or disc space to continue.")); - delete newModel; - delete m_fftModel; - m_fftModel = nullptr; return; } - FFTModel *oldModel = m_fftModel; - m_fftModel = newModel; + m_fftModel = ModelById::add(newFFTModel); bool createWholeCache = false; checkCacheSpace(&m_peakCacheDivisor, &createWholeCache); if (createWholeCache) { - m_wholeCache = new Dense3DModelPeakCache(m_fftModel, 1); - m_peakCache = new Dense3DModelPeakCache(m_wholeCache, m_peakCacheDivisor); + + auto whole = std::make_shared(m_fftModel, 1); + m_wholeCache = ModelById::add(whole); + + auto peaks = std::make_shared(m_wholeCache, + m_peakCacheDivisor); + m_peakCache = ModelById::add(peaks); + } else { - m_peakCache = new Dense3DModelPeakCache(m_fftModel, m_peakCacheDivisor); + + auto peaks = std::make_shared(m_fftModel, + m_peakCacheDivisor); + m_peakCache = ModelById::add(peaks); } - - emit sliceableModelReplaced(oldModel, m_fftModel); - delete oldModel; } void @@ -1431,12 +1448,13 @@ { *suggestedPeakDivisor = 8; *createWholeCache = false; - - if (!m_fftModel) return; + + auto fftModel = ModelById::getAs(m_fftModel); + if (!fftModel) return; size_t sz = - size_t(m_fftModel->getWidth()) * - size_t(m_fftModel->getHeight()) * + size_t(fftModel->getWidth()) * + size_t(fftModel->getHeight()) * sizeof(float); try { @@ -1466,7 +1484,7 @@ } } -const Model * +ModelId SpectrogramLayer::getSliceableModel() const { return m_fftModel; @@ -1496,10 +1514,10 @@ Colour3DPlotRenderer::Sources sources; sources.verticalBinLayer = this; - sources.fft = getFFTModel(); + sources.fft = m_fftModel; sources.source = sources.fft; - if (m_peakCache) sources.peakCaches.push_back(m_peakCache); - if (m_wholeCache) sources.peakCaches.push_back(m_wholeCache); + if (!m_peakCache.isNone()) sources.peakCaches.push_back(m_peakCache); + if (!m_wholeCache.isNone()) sources.peakCaches.push_back(m_wholeCache); ColourScale::Parameters cparams; cparams.colourMap = m_colourMap; @@ -1635,7 +1653,8 @@ cerr << "SpectrogramLayer::paint(): rect is " << rect.x() << "," << rect.y() << " " << rect.width() << "x" << rect.height() << endl; #endif - if (!m_model || !m_model->isOK() || !m_model->isReady()) { + auto model = ModelById::getAs(m_model); + if (!model || !model->isOK() || !model->isReady()) { return; } @@ -1649,8 +1668,10 @@ { Profiler profiler("SpectrogramLayer::illuminateLocalFeatures"); + auto model = ModelById::getAs(m_model); + QPoint localPos; - if (!v->shouldIlluminateLocalFeatures(this, localPos) || !m_model) { + if (!v->shouldIlluminateLocalFeatures(this, localPos) || !model) { return; } @@ -1708,8 +1729,9 @@ int SpectrogramLayer::getCompletion(LayerGeometryProvider *) const { - if (!m_fftModel) return 100; - int completion = m_fftModel->getCompletion(); + auto fftModel = ModelById::getAs(m_fftModel); + if (!fftModel) return 100; + int completion = fftModel->getCompletion(); #ifdef DEBUG_SPECTROGRAM_REPAINT cerr << "SpectrogramLayer::getCompletion: completion = " << completion << endl; #endif @@ -1719,17 +1741,19 @@ QString SpectrogramLayer::getError(LayerGeometryProvider *) const { - if (!m_fftModel) return ""; - return m_fftModel->getError(); + auto fftModel = ModelById::getAs(m_fftModel); + if (!fftModel) return ""; + return fftModel->getError(); } bool SpectrogramLayer::getValueExtents(double &min, double &max, bool &logarithmic, QString &unit) const { - if (!m_model) return false; - - sv_samplerate_t sr = m_model->getSampleRate(); + auto model = ModelById::getAs(m_model); + if (!model) return false; + + sv_samplerate_t sr = model->getSampleRate(); min = double(sr) / getFFTSize(); max = double(sr) / 2; @@ -1751,12 +1775,13 @@ bool SpectrogramLayer::setDisplayExtents(double min, double max) { - if (!m_model) return false; + auto model = ModelById::getAs(m_model); + if (!model) return false; // SVDEBUG << "SpectrogramLayer::setDisplayExtents: " << min << "->" << max << endl; if (min < 0) min = 0; - if (max > m_model->getSampleRate()/2.0) max = m_model->getSampleRate()/2.0; + if (max > model->getSampleRate()/2.0) max = model->getSampleRate()/2.0; int minf = int(lrint(min)); int maxf = int(lrint(max)); @@ -1831,6 +1856,11 @@ QPoint cursorPos, vector &extents) const { + // 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" + QRect vertical(cursorPos.x() - 12, 0, 12, v->getPaintHeight()); extents.push_back(vertical); @@ -1869,6 +1899,9 @@ SpectrogramLayer::paintCrosshairs(LayerGeometryProvider *v, QPainter &paint, QPoint cursorPos) const { + auto model = ModelById::getAs(m_model); + if (!model) return; + paint.save(); int sw = getVerticalScaleWidth(v, m_haveDetailedScale, paint); @@ -1885,35 +1918,39 @@ double fundamental = getFrequencyForY(v, cursorPos.y()); - PaintAssistant::drawVisibleText(v, paint, - sw + 2, - cursorPos.y() - 2, - QString("%1 Hz").arg(fundamental), - PaintAssistant::OutlinedText); + PaintAssistant::drawVisibleText + (v, paint, + sw + 2, + cursorPos.y() - 2, + QString("%1 Hz").arg(fundamental), + PaintAssistant::OutlinedText); if (Pitch::isFrequencyInMidiRange(fundamental)) { QString pitchLabel = Pitch::getPitchLabelForFrequency(fundamental); - PaintAssistant::drawVisibleText(v, paint, - sw + 2, - cursorPos.y() + paint.fontMetrics().ascent() + 2, - pitchLabel, - PaintAssistant::OutlinedText); + PaintAssistant::drawVisibleText + (v, paint, + sw + 2, + cursorPos.y() + paint.fontMetrics().ascent() + 2, + pitchLabel, + PaintAssistant::OutlinedText); } sv_frame_t frame = v->getFrameForX(cursorPos.x()); - RealTime rt = RealTime::frame2RealTime(frame, m_model->getSampleRate()); + RealTime rt = RealTime::frame2RealTime(frame, model->getSampleRate()); QString rtLabel = QString("%1 s").arg(rt.toText(true).c_str()); QString frameLabel = QString("%1").arg(frame); - PaintAssistant::drawVisibleText(v, paint, - cursorPos.x() - paint.fontMetrics().width(frameLabel) - 2, - v->getPaintHeight() - 2, - frameLabel, - PaintAssistant::OutlinedText); - PaintAssistant::drawVisibleText(v, paint, - cursorPos.x() + 2, - v->getPaintHeight() - 2, - rtLabel, - PaintAssistant::OutlinedText); + PaintAssistant::drawVisibleText + (v, paint, + cursorPos.x() - paint.fontMetrics().width(frameLabel) - 2, + v->getPaintHeight() - 2, + frameLabel, + PaintAssistant::OutlinedText); + PaintAssistant::drawVisibleText + (v, paint, + cursorPos.x() + 2, + v->getPaintHeight() - 2, + rtLabel, + PaintAssistant::OutlinedText); int harmonic = 2; @@ -1949,7 +1986,8 @@ int x = pos.x(); int y = pos.y(); - if (!m_model || !m_model->isOK()) return ""; + auto model = ModelById::getAs(m_model); + if (!model || !model->isOK()) return ""; double magMin = 0, magMax = 0; double phaseMin = 0, phaseMax = 0; @@ -2068,7 +2106,8 @@ int SpectrogramLayer::getVerticalScaleWidth(LayerGeometryProvider *, bool detailed, QPainter &paint) const { - if (!m_model || !m_model->isOK()) return 0; + auto model = ModelById::getAs(m_model); + if (!model || !model->isOK()) return 0; int cw = 0; if (detailed) cw = getColourScaleWidth(paint); @@ -2076,7 +2115,7 @@ int tw = paint.fontMetrics().width(QString("%1") .arg(m_maxFrequency > 0 ? m_maxFrequency - 1 : - m_model->getSampleRate() / 2)); + model->getSampleRate() / 2)); int fw = paint.fontMetrics().width(tr("43Hz")); if (tw < fw) tw = fw; @@ -2090,7 +2129,8 @@ SpectrogramLayer::paintVerticalScale(LayerGeometryProvider *v, bool detailed, QPainter &paint, QRect rect) const { - if (!m_model || !m_model->isOK()) { + auto model = ModelById::getAs(m_model); + if (!model || !model->isOK()) { return; } @@ -2110,7 +2150,7 @@ int pkw = (m_binScale == BinScale::Log ? 10 : 0); int bins = getFFTSize() / 2; - sv_samplerate_t sr = m_model->getSampleRate(); + sv_samplerate_t sr = model->getSampleRate(); if (m_maxFrequency > 0) { bins = int((double(m_maxFrequency) * getFFTSize()) / sr + 0.1); @@ -2380,9 +2420,10 @@ int SpectrogramLayer::getVerticalZoomSteps(int &defaultStep) const { - if (!m_model) return 0; - - sv_samplerate_t sr = m_model->getSampleRate(); + auto model = ModelById::getAs(m_model); + if (!model) return 0; + + sv_samplerate_t sr = model->getSampleRate(); SpectrogramRangeMapper mapper(sr, getFFTSize()); @@ -2403,12 +2444,13 @@ int SpectrogramLayer::getCurrentVerticalZoomStep() const { - if (!m_model) return 0; + auto model = ModelById::getAs(m_model); + if (!model) return 0; double dmin, dmax; getDisplayExtents(dmin, dmax); - SpectrogramRangeMapper mapper(m_model->getSampleRate(), getFFTSize()); + SpectrogramRangeMapper mapper(model->getSampleRate(), getFFTSize()); int n = mapper.getPositionForValue(dmax - dmin); // SVDEBUG << "SpectrogramLayer::getCurrentVerticalZoomStep: " << n << endl; return n; @@ -2417,14 +2459,15 @@ void SpectrogramLayer::setVerticalZoomStep(int step) { - if (!m_model) return; + auto model = ModelById::getAs(m_model); + if (!model) return; double dmin = m_minFrequency, dmax = m_maxFrequency; // getDisplayExtents(dmin, dmax); // cerr << "current range " << dmin << " -> " << dmax << ", range " << dmax-dmin << ", mid " << (dmax + dmin)/2 << endl; - sv_samplerate_t sr = m_model->getSampleRate(); + sv_samplerate_t sr = model->getSampleRate(); SpectrogramRangeMapper mapper(sr, getFFTSize()); double newdist = mapper.getValueForPosition(step); @@ -2485,8 +2528,9 @@ RangeMapper * SpectrogramLayer::getNewVerticalZoomRangeMapper() const { - if (!m_model) return nullptr; - return new SpectrogramRangeMapper(m_model->getSampleRate(), getFFTSize()); + auto model = ModelById::getAs(m_model); + if (!model) return nullptr; + return new SpectrogramRangeMapper(model->getSampleRate(), getFFTSize()); } void diff -r de41a11cabc2 -r ac0a8addabcf layer/SpectrogramLayer.h --- a/layer/SpectrogramLayer.h Thu Jun 13 15:35:01 2019 +0100 +++ b/layer/SpectrogramLayer.h Wed Jul 17 14:25:16 2019 +0100 @@ -60,7 +60,7 @@ ~SpectrogramLayer(); const ZoomConstraint *getZoomConstraint() const override { return this; } - const Model *getModel() const override { return m_model; } + ModelId getModel() const override { return m_model; } void paint(LayerGeometryProvider *v, QPainter &paint, QRect rect) const override; void setSynchronousPainting(bool synchronous) override; @@ -81,7 +81,7 @@ bool hasLightBackground() const override; - void setModel(const DenseTimeValueModel *model); + void setModel(ModelId model); // a DenseTimeValueModel PropertyList getProperties() const override; QString getPropertyLabel(const PropertyName &) const override; @@ -234,16 +234,16 @@ void setVerticalZoomStep(int) override; RangeMapper *getNewVerticalZoomRangeMapper() const override; - const Model *getSliceableModel() const override; + ModelId getSliceableModel() const override; protected slots: - void cacheInvalid(); - void cacheInvalid(sv_frame_t startFrame, sv_frame_t endFrame); + void cacheInvalid(ModelId); + void cacheInvalid(ModelId, sv_frame_t startFrame, sv_frame_t endFrame); void preferenceChanged(PropertyContainer::PropertyName name); protected: - const DenseTimeValueModel *m_model; // I do not own this + ModelId m_model; // a DenseTimeValueModel int m_channel; int m_windowSize; @@ -306,11 +306,11 @@ int getFFTSize() const; // m_windowSize * getOversampling() - FFTModel *m_fftModel; - FFTModel *getFFTModel() const { return m_fftModel; } - Dense3DModelPeakCache *m_wholeCache; - Dense3DModelPeakCache *m_peakCache; - Dense3DModelPeakCache *getPeakCache() const { return m_peakCache; } + // We take responsibility for registering/deregistering these + // models and caches with ModelById + ModelId m_fftModel; // an FFTModel + ModelId m_wholeCache; // a Dense3DModelPeakCache + ModelId m_peakCache; // a Dense3DModelPeakCache int m_peakCacheDivisor; void checkCacheSpace(int *suggestedPeakDivisor, bool *createWholeCache) const; diff -r de41a11cabc2 -r ac0a8addabcf layer/SpectrumLayer.cpp --- a/layer/SpectrumLayer.cpp Thu Jun 13 15:35:01 2019 +0100 +++ b/layer/SpectrumLayer.cpp Wed Jul 17 14:25:16 2019 +0100 @@ -33,7 +33,6 @@ SpectrumLayer::SpectrumLayer() : - m_originModel(nullptr), m_channel(-1), m_channelSet(false), m_windowSize(4096), @@ -56,29 +55,19 @@ SpectrumLayer::~SpectrumLayer() { - Model *m = const_cast - (static_cast(m_sliceableModel)); - if (m) m->aboutToDelete(); - m_sliceableModel = nullptr; - delete m; + ModelById::release(m_sliceableModel); } void -SpectrumLayer::setModel(DenseTimeValueModel *model) +SpectrumLayer::setModel(ModelId modelId) { - SVDEBUG << "SpectrumLayer::setModel(" << model << ") from " << m_originModel << endl; + auto newModel = ModelById::getAs(modelId); + if (!modelId.isNone() && !newModel) { + throw std::logic_error("Not a DenseTimeValueModel"); + } - if (m_originModel == model) return; - - m_originModel = model; - - if (m_sliceableModel) { - Model *m = const_cast - (static_cast(m_sliceableModel)); - m->aboutToDelete(); - setSliceableModel(nullptr); - delete m; - } + if (m_originModel == modelId) return; + m_originModel = modelId; m_newFFTNeeded = true; @@ -104,26 +93,21 @@ void SpectrumLayer::setupFFT() { - if (m_sliceableModel) { - Model *m = const_cast - (static_cast(m_sliceableModel)); - m->aboutToDelete(); - setSliceableModel(nullptr); - delete m; - } + ModelById::release(m_sliceableModel); + m_sliceableModel = {}; - if (!m_originModel) { + if (m_originModel.isNone()) { return; } int fftSize = getFFTSize(); - FFTModel *newFFT = new FFTModel(m_originModel, - m_channel, - m_windowType, - m_windowSize, - getWindowIncrement(), - fftSize); + auto newFFT = std::make_shared(m_originModel, + m_channel, + m_windowType, + m_windowSize, + getWindowIncrement(), + fftSize); if (m_minbin == 0 && m_maxbin == 0) { m_minbin = 1; @@ -132,7 +116,7 @@ m_maxbin = newFFT->getHeight(); } - setSliceableModel(newFFT); + setSliceableModel(ModelById::add(newFFT)); m_biasCurve.clear(); for (int i = 0; i < fftSize; ++i) { @@ -403,15 +387,19 @@ double SpectrumLayer::getBinForFrequency(double freq) const { - if (!m_sliceableModel) return 0; - double bin = (freq * getFFTSize()) / m_sliceableModel->getSampleRate(); + auto sliceableModel = ModelById::getAs + (m_sliceableModel); + if (!sliceableModel) return 0; + double bin = (freq * getFFTSize()) / sliceableModel->getSampleRate(); return bin; } double SpectrumLayer::getBinForX(const LayerGeometryProvider *v, double x) const { - if (!m_sliceableModel) return 0; + auto sliceableModel = ModelById::getAs + (m_sliceableModel); + if (!sliceableModel) return 0; double bin = getBinForFrequency(getFrequencyForX(v, x)); return bin; } @@ -419,7 +407,9 @@ double SpectrumLayer::getFrequencyForX(const LayerGeometryProvider *v, double x) const { - if (!m_sliceableModel) return 0; + auto sliceableModel = ModelById::getAs + (m_sliceableModel); + if (!sliceableModel) return 0; double fmin = getFrequencyForBin(m_minbin); double fmax = getFrequencyForBin(m_maxbin); @@ -431,15 +421,19 @@ double SpectrumLayer::getFrequencyForBin(double bin) const { - if (!m_sliceableModel) return 0; - double freq = (bin * m_sliceableModel->getSampleRate()) / getFFTSize(); + auto sliceableModel = ModelById::getAs + (m_sliceableModel); + if (!sliceableModel) return 0; + double freq = (bin * sliceableModel->getSampleRate()) / getFFTSize(); return freq; } double SpectrumLayer::getXForBin(const LayerGeometryProvider *v, double bin) const { - if (!m_sliceableModel) return 0; + auto sliceableModel = ModelById::getAs + (m_sliceableModel); + if (!sliceableModel) return 0; double x = getXForFrequency(v, getFrequencyForBin(bin)); return x; } @@ -447,7 +441,9 @@ double SpectrumLayer::getXForFrequency(const LayerGeometryProvider *v, double freq) const { - if (!m_sliceableModel) return 0; + auto sliceableModel = ModelById::getAs + (m_sliceableModel); + if (!sliceableModel) return 0; double fmin = getFrequencyForBin(m_minbin); double fmax = getFrequencyForBin(m_maxbin); @@ -475,8 +471,12 @@ if (value > 0.0) { value = 10.0 * log10(value); - if (value < m_threshold) value = m_threshold; - } else value = m_threshold; + if (value < m_threshold) { + value = m_threshold; + } + } else { + value = m_threshold; + } unit = "dBV"; @@ -513,6 +513,11 @@ int sw = getVerticalScaleWidth(v, false, paint); + // 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" + QRect value(sw, cursorPos.y() - paint.fontMetrics().ascent() - 2, paint.fontMetrics().width("0.0000001 V") + 2, paint.fontMetrics().height()); @@ -543,7 +548,9 @@ SpectrumLayer::paintCrosshairs(LayerGeometryProvider *v, QPainter &paint, QPoint cursorPos) const { - if (!m_sliceableModel) return; + auto sliceableModel = ModelById::getAs + (m_sliceableModel); + if (!sliceableModel) return; paint.save(); QFont fn = paint.font(); @@ -630,7 +637,9 @@ QString SpectrumLayer::getFeatureDescription(LayerGeometryProvider *v, QPoint &p) const { - if (!m_sliceableModel) return ""; + auto sliceableModel = ModelById::getAs + (m_sliceableModel); + if (!sliceableModel) return ""; int minbin = 0, maxbin = 0, range = 0; QString genericDesc = SliceLayer::getFeatureDescriptionAux @@ -651,10 +660,10 @@ QString binstr; QString hzstr; - int minfreq = int(lrint((minbin * m_sliceableModel->getSampleRate()) / + int minfreq = int(lrint((minbin * sliceableModel->getSampleRate()) / getFFTSize())); int maxfreq = int(lrint((std::max(maxbin, minbin) - * m_sliceableModel->getSampleRate()) / + * sliceableModel->getSampleRate()) / getFFTSize())); if (maxbin != minbin) { @@ -698,7 +707,7 @@ QString description; - if (range > int(m_sliceableModel->getResolution())) { + if (range > int(sliceableModel->getResolution())) { description = tr("%1\nBin:\t%2 (%3)\n%4 value:\t%5\ndB:\t%6") .arg(genericDesc) .arg(binstr) @@ -722,8 +731,8 @@ void SpectrumLayer::paint(LayerGeometryProvider *v, QPainter &paint, QRect rect) const { - if (!m_originModel || !m_originModel->isOK() || - !m_originModel->isReady()) { + auto originModel = ModelById::get(m_originModel); + if (!originModel || !originModel->isOK() || !originModel->isReady()) { SVDEBUG << "SpectrumLayer::paint: no origin model, or origin model not OK or not ready" << endl; return; } @@ -733,8 +742,8 @@ const_cast(this)->setupFFT(); //ugh } - FFTModel *fft = dynamic_cast - (const_cast(m_sliceableModel)); + auto fft = ModelById::getAs(m_sliceableModel); + if (!fft) return; double thresh = (pow(10, -6) / m_gain) * (getFFTSize() / 2.0); // -60dB adj diff -r de41a11cabc2 -r ac0a8addabcf layer/SpectrumLayer.h --- a/layer/SpectrumLayer.h Thu Jun 13 15:35:01 2019 +0100 +++ b/layer/SpectrumLayer.h Wed Jul 17 14:25:16 2019 +0100 @@ -37,8 +37,8 @@ SpectrumLayer(); ~SpectrumLayer(); - void setModel(DenseTimeValueModel *model); - virtual const Model *getModel() const override { return m_originModel; } + void setModel(ModelId model); // a DenseTimeValueModel + virtual ModelId getModel() const override { return m_originModel; } virtual bool getCrosshairExtents(LayerGeometryProvider *, QPainter &, QPoint cursorPos, std::vector &extents) const override; @@ -115,7 +115,7 @@ void preferenceChanged(PropertyContainer::PropertyName name); protected: - DenseTimeValueModel *m_originModel; + ModelId m_originModel; // a DenseTimeValueModel int m_channel; bool m_channelSet; int m_windowSize; diff -r de41a11cabc2 -r ac0a8addabcf layer/TextLayer.cpp --- a/layer/TextLayer.cpp Thu Jun 13 15:35:01 2019 +0100 +++ b/layer/TextLayer.cpp Wed Jul 17 14:25:16 2019 +0100 @@ -34,7 +34,6 @@ TextLayer::TextLayer() : SingleColourLayer(), - m_model(nullptr), m_editing(false), m_originalPoint(0, 0.0, tr("Empty Label")), m_editingPoint(0, 0.0, tr("Empty Label")), @@ -43,15 +42,29 @@ } +int +TextLayer::getCompletion(LayerGeometryProvider *) const +{ + auto model = ModelById::get(m_model); + if (model) return model->getCompletion(); + else return 0; +} + void -TextLayer::setModel(TextModel *model) +TextLayer::setModel(ModelId modelId) { - if (m_model == model) return; - m_model = model; + auto newModel = ModelById::getAs(modelId); + + if (!modelId.isNone() && !newModel) { + throw std::logic_error("Not a TextModel"); + } + + if (m_model == modelId) return; + m_model = modelId; - connectSignals(m_model); - -// SVDEBUG << "TextLayer::setModel(" << model << ")" << endl; + if (newModel) { + connectSignals(m_model); + } emit modelReplaced(); } @@ -111,14 +124,15 @@ EventVector TextLayer::getLocalPoints(LayerGeometryProvider *v, int x, int y) const { - if (!m_model) return {}; + auto model = ModelById::getAs(m_model); + if (!model) return {}; int overlap = ViewManager::scalePixelSize(150); sv_frame_t frame0 = v->getFrameForX(-overlap); sv_frame_t frame1 = v->getFrameForX(v->getPaintWidth() + overlap); - EventVector points(m_model->getEventsSpanning(frame0, frame1 - frame0)); + EventVector points(model->getEventsSpanning(frame0, frame1 - frame0)); EventVector rv; QFontMetrics metrics = QFontMetrics(QFont()); @@ -156,11 +170,12 @@ bool TextLayer::getPointToDrag(LayerGeometryProvider *v, int x, int y, Event &p) const { - if (!m_model) return false; + auto model = ModelById::getAs(m_model); + if (!model) return false; sv_frame_t a = v->getFrameForX(x - ViewManager::scalePixelSize(120)); sv_frame_t b = v->getFrameForX(x + ViewManager::scalePixelSize(10)); - EventVector onPoints = m_model->getEventsWithin(a, b); + EventVector onPoints = model->getEventsWithin(a, b); if (onPoints.empty()) return false; double nearestDistance = -1; @@ -186,12 +201,13 @@ { int x = pos.x(); - if (!m_model || !m_model->getSampleRate()) return ""; + auto model = ModelById::getAs(m_model); + if (!model || !model->getSampleRate()) return ""; EventVector points = getLocalPoints(v, x, pos.y()); if (points.empty()) { - if (!m_model->isReady()) { + if (!model->isReady()) { return tr("In progress"); } else { return ""; @@ -200,7 +216,7 @@ sv_frame_t useFrame = points.begin()->getFrame(); - RealTime rt = RealTime::frame2RealTime(useFrame, m_model->getSampleRate()); + RealTime rt = RealTime::frame2RealTime(useFrame, model->getSampleRate()); QString text; @@ -224,7 +240,8 @@ int &resolution, SnapType snap) const { - if (!m_model) { + auto model = ModelById::getAs(m_model); + if (!model) { return Layer::snapToFeatureFrame(v, frame, resolution, snap); } @@ -235,7 +252,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), -1); @@ -245,7 +262,7 @@ } Event e; - if (m_model->getNearestEventMatching + if (model->getNearestEventMatching (frame, [](Event) { return true; }, snap == SnapLeft ? EventSeries::Backward : EventSeries::Forward, @@ -274,9 +291,10 @@ void TextLayer::paint(LayerGeometryProvider *v, QPainter &paint, QRect rect) const { - if (!m_model || !m_model->isOK()) return; + auto model = ModelById::getAs(m_model); + if (!model || !model->isOK()) return; - sv_samplerate_t sampleRate = m_model->getSampleRate(); + sv_samplerate_t sampleRate = model->getSampleRate(); if (!sampleRate) return; // Profiler profiler("TextLayer::paint", true); @@ -286,7 +304,7 @@ sv_frame_t frame0 = v->getFrameForX(x0 - overlap); sv_frame_t frame1 = v->getFrameForX(x1 + overlap); - EventVector points(m_model->getEventsWithin(frame0, frame1 - frame0, 2)); + EventVector points(model->getEventsWithin(frame0, frame1 - frame0, 2)); if (points.empty()) return; QColor brushColour(getBaseQColor()); @@ -299,7 +317,7 @@ penColour = v->getForeground(); // SVDEBUG << "TextLayer::paint: resolution is " -// << m_model->getResolution() << " frames" << endl; +// << model->getResolution() << " frames" << endl; QPoint localPos; Event illuminatePoint(0); @@ -379,14 +397,15 @@ { // SVDEBUG << "TextLayer::drawStart(" << e->x() << "," << e->y() << ")" << endl; - if (!m_model) { + auto model = ModelById::getAs(m_model); + if (!model) { SVDEBUG << "TextLayer::drawStart: no model" << endl; 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 height = getHeightForY(v, e->y()); @@ -394,7 +413,7 @@ m_originalPoint = m_editingPoint; if (m_editingCommand) finish(m_editingCommand); - m_editingCommand = new ChangeEventsCommand(m_model, "Add Label"); + m_editingCommand = new ChangeEventsCommand(m_model.untyped, "Add Label"); m_editingCommand->add(m_editingPoint); m_editing = true; @@ -405,11 +424,12 @@ { // SVDEBUG << "TextLayer::drawDrag(" << e->x() << "," << e->y() << ")" << endl; - if (!m_model || !m_editing) return; + auto model = ModelById::getAs(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 height = getHeightForY(v, e->y()); @@ -424,7 +444,8 @@ TextLayer::drawEnd(LayerGeometryProvider *v, QMouseEvent *) { // SVDEBUG << "TextLayer::drawEnd(" << e->x() << "," << e->y() << ")" << endl; - if (!m_model || !m_editing) return; + auto model = ModelById::getAs(m_model); + if (!model || !m_editing) return; bool ok = false; QString label = QInputDialog::getText(v->getView(), tr("Enter label"), @@ -447,7 +468,8 @@ void TextLayer::eraseStart(LayerGeometryProvider *v, QMouseEvent *e) { - if (!m_model) return; + auto model = ModelById::getAs(m_model); + if (!model) return; if (!getPointToDrag(v, e->x(), e->y(), m_editingPoint)) return; @@ -467,7 +489,8 @@ void TextLayer::eraseEnd(LayerGeometryProvider *v, QMouseEvent *e) { - if (!m_model || !m_editing) return; + auto model = ModelById::getAs(m_model); + if (!model || !m_editing) return; m_editing = false; @@ -476,7 +499,7 @@ if (p.getFrame() != m_editingPoint.getFrame() || p.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; @@ -488,7 +511,8 @@ { // SVDEBUG << "TextLayer::editStart(" << e->x() << "," << e->y() << ")" << endl; - if (!m_model) return; + auto model = ModelById::getAs(m_model); + if (!model) return; if (!getPointToDrag(v, e->x(), e->y(), m_editingPoint)) { return; @@ -508,7 +532,8 @@ void TextLayer::editDrag(LayerGeometryProvider *v, QMouseEvent *e) { - if (!m_model || !m_editing) return; + auto model = ModelById::getAs(m_model); + if (!model || !m_editing) return; sv_frame_t frameDiff = v->getFrameForX(e->x()) - v->getFrameForX(m_editOrigin.x()); @@ -519,10 +544,10 @@ double height = m_originalPoint.getValue() + heightDiff; if (frame < 0) frame = 0; - frame = (frame / m_model->getResolution()) * m_model->getResolution(); + frame = (frame / model->getResolution()) * model->getResolution(); if (!m_editingCommand) { - m_editingCommand = new ChangeEventsCommand(m_model, tr("Drag Label")); + m_editingCommand = new ChangeEventsCommand(m_model.untyped, tr("Drag Label")); } m_editingCommand->remove(m_editingPoint); @@ -536,7 +561,8 @@ TextLayer::editEnd(LayerGeometryProvider *, QMouseEvent *) { // SVDEBUG << "TextLayer::editEnd(" << e->x() << "," << e->y() << ")" << endl; - if (!m_model || !m_editing) return; + auto model = ModelById::getAs(m_model); + if (!model || !m_editing) return; if (m_editingCommand) { @@ -563,7 +589,8 @@ bool TextLayer::editOpen(LayerGeometryProvider *v, QMouseEvent *e) { - if (!m_model) return false; + auto model = ModelById::getAs(m_model); + if (!model) return false; Event text; if (!getPointToDrag(v, e->x(), e->y(), text)) return false; @@ -576,7 +603,7 @@ QLineEdit::Normal, label, &ok); if (ok && label != text.getLabel()) { ChangeEventsCommand *command = - new ChangeEventsCommand(m_model, tr("Re-Label Point")); + new ChangeEventsCommand(m_model.untyped, tr("Re-Label Point")); command->remove(text); command->add(text.withLabel(label)); finish(command); @@ -588,13 +615,14 @@ void TextLayer::moveSelection(Selection s, sv_frame_t newStartFrame) { - if (!m_model) return; + auto model = ModelById::getAs(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->getEventsStartingWithin(s.getStartFrame(), s.getDuration()); + model->getEventsStartingWithin(s.getStartFrame(), s.getDuration()); for (Event p: points) { command->remove(p); @@ -609,13 +637,14 @@ void TextLayer::resizeSelection(Selection s, Selection newSize) { - if (!m_model) return; + auto model = ModelById::getAs(m_model); + if (!model) return; ChangeEventsCommand *command = - new ChangeEventsCommand(m_model, tr("Resize Selection")); + new ChangeEventsCommand(m_model.untyped, tr("Resize Selection")); EventVector points = - m_model->getEventsStartingWithin(s.getStartFrame(), s.getDuration()); + model->getEventsStartingWithin(s.getStartFrame(), s.getDuration()); double ratio = double(newSize.getDuration()) / double(s.getDuration()); double oldStart = double(s.getStartFrame()); @@ -637,13 +666,14 @@ void TextLayer::deleteSelection(Selection s) { - if (!m_model) return; + auto model = ModelById::getAs(m_model); + if (!model) return; ChangeEventsCommand *command = - new ChangeEventsCommand(m_model, tr("Delete Selection")); + new ChangeEventsCommand(m_model.untyped, tr("Delete Selection")); EventVector points = - m_model->getEventsStartingWithin(s.getStartFrame(), s.getDuration()); + model->getEventsStartingWithin(s.getStartFrame(), s.getDuration()); for (Event p: points) { command->remove(p); @@ -655,10 +685,11 @@ void TextLayer::copy(LayerGeometryProvider *v, Selection s, Clipboard &to) { - if (!m_model) return; + auto model = ModelById::getAs(m_model); + if (!model) return; EventVector points = - m_model->getEventsStartingWithin(s.getStartFrame(), s.getDuration()); + model->getEventsStartingWithin(s.getStartFrame(), s.getDuration()); for (Event p: points) { to.addPoint(p.withReferenceFrame(alignToReference(v, p.getFrame()))); @@ -668,7 +699,8 @@ bool TextLayer::paste(LayerGeometryProvider *v, const Clipboard &from, sv_frame_t /* frameOffset */, bool /* interactive */) { - if (!m_model) return false; + auto model = ModelById::getAs(m_model); + if (!model) return false; const EventVector &points = from.getPoints(); @@ -692,7 +724,7 @@ } ChangeEventsCommand *command = - new ChangeEventsCommand(m_model, tr("Paste")); + new ChangeEventsCommand(m_model.untyped, tr("Paste")); double valueMin = 0.0, valueMax = 1.0; for (EventVector::const_iterator i = points.begin(); diff -r de41a11cabc2 -r ac0a8addabcf layer/TextLayer.h --- a/layer/TextLayer.h Thu Jun 13 15:35:01 2019 +0100 +++ b/layer/TextLayer.h Wed Jul 17 14:25:16 2019 +0100 @@ -62,8 +62,8 @@ bool editOpen(LayerGeometryProvider *, QMouseEvent *) override; // on double-click - const Model *getModel() const override { return m_model; } - void setModel(TextModel *model); + ModelId getModel() const override { return m_model; } + void setModel(ModelId model); // a TextModel PropertyList getProperties() const override; QString getPropertyLabel(const PropertyName &) const override; @@ -78,7 +78,7 @@ bool isLayerEditable() const override { return true; } - int getCompletion(LayerGeometryProvider *) const override { return m_model->getCompletion(); } + int getCompletion(LayerGeometryProvider *) const override; bool getValueExtents(double &min, double &max, bool &logarithmic, QString &unit) const override; @@ -100,7 +100,7 @@ bool getPointToDrag(LayerGeometryProvider *v, int x, int y, Event &) const; - TextModel *m_model; + ModelId m_model; bool m_editing; QPoint m_editOrigin; Event m_originalPoint; diff -r de41a11cabc2 -r ac0a8addabcf layer/TimeInstantLayer.cpp --- a/layer/TimeInstantLayer.cpp Thu Jun 13 15:35:01 2019 +0100 +++ b/layer/TimeInstantLayer.cpp Wed Jul 17 14:25:16 2019 +0100 @@ -41,7 +41,6 @@ TimeInstantLayer::TimeInstantLayer() : SingleColourLayer(), - m_model(nullptr), m_editing(false), m_editingPoint(0, tr("New Point")), m_editingCommand(nullptr), @@ -53,20 +52,30 @@ { } +int +TimeInstantLayer::getCompletion(LayerGeometryProvider *) const +{ + auto model = ModelById::get(m_model); + if (model) return model->getCompletion(); + else return 0; +} + void -TimeInstantLayer::setModel(SparseOneDimensionalModel *model) +TimeInstantLayer::setModel(ModelId modelId) { - if (m_model == model) return; - m_model = model; + auto newModel = ModelById::getAs(modelId); + if (!modelId.isNone() && !newModel) { + throw std::logic_error("Not a SparseOneDimensionalModel"); + } + + if (m_model == modelId) return; + m_model = modelId; - connectSignals(m_model); - -#ifdef DEBUG_TIME_INSTANT_LAYER - cerr << "TimeInstantLayer::setModel(" << model << ")" << endl; -#endif - - if (m_model && m_model->getRDFTypeURI().endsWith("Segment")) { - setPlotStyle(PlotSegmentation); + if (newModel) { + connectSignals(m_model); + if (newModel->getRDFTypeURI().endsWith("Segment")) { + setPlotStyle(PlotSegmentation); + } } emit modelReplaced(); @@ -149,6 +158,14 @@ } bool +TimeInstantLayer::needsTextLabelHeight() const +{ + auto model = ModelById::getAs(m_model); + if (model) return model->hasTextLabels(); + else return false; +} + +bool TimeInstantLayer::isLayerScrollable(const LayerGeometryProvider *v) const { QPoint discard; @@ -158,7 +175,8 @@ EventVector TimeInstantLayer::getLocalPoints(LayerGeometryProvider *v, int x) const { - if (!m_model) return {}; + auto model = ModelById::getAs(m_model); + if (!model) return {}; // Return a set of points that all have the same frame number, the // nearest to the given x coordinate, and that are within a @@ -166,12 +184,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; @@ -195,7 +213,7 @@ } if (have) { - return m_model->getEventsStartingAt(suitable); + return model->getEventsStartingAt(suitable); } else { return {}; } @@ -204,10 +222,11 @@ QString TimeInstantLayer::getLabelPreceding(sv_frame_t frame) const { - if (!m_model || !m_model->hasTextLabels()) return ""; + auto model = ModelById::getAs(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, @@ -223,12 +242,13 @@ { int x = pos.x(); - if (!m_model || !m_model->getSampleRate()) return ""; + auto model = ModelById::getAs(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"); @@ -237,7 +257,7 @@ sv_frame_t useFrame = points.begin()->getFrame(); - RealTime rt = RealTime::frame2RealTime(useFrame, m_model->getSampleRate()); + RealTime rt = RealTime::frame2RealTime(useFrame, model->getSampleRate()); QString text; @@ -259,7 +279,8 @@ int &resolution, SnapType snap) const { - if (!m_model) { + auto model = ModelById::getAs(m_model); + if (!model) { return Layer::snapToFeatureFrame(v, frame, resolution, snap); } @@ -270,7 +291,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)); @@ -280,7 +301,7 @@ } Event e; - if (m_model->getNearestEventMatching + if (model->getNearestEventMatching (frame, [](Event) { return true; }, snap == SnapLeft ? EventSeries::Backward : EventSeries::Forward, @@ -295,7 +316,8 @@ void TimeInstantLayer::paint(LayerGeometryProvider *v, QPainter &paint, QRect rect) const { - if (!m_model || !m_model->isOK()) return; + auto model = ModelById::getAs(m_model); + if (!model || !model->isOK()) return; // Profiler profiler("TimeInstantLayer::paint", true); @@ -311,12 +333,12 @@ overspill = 1; } - EventVector points(m_model->getEventsWithin(frame0, frame1 - frame0, + EventVector points(model->getEventsWithin(frame0, frame1 - frame0, overspill)); bool odd = false; if (m_plotStyle == PlotSegmentation && !points.empty()) { - int index = m_model->getRowForFrame(points.begin()->getFrame()); + int index = model->getRowForFrame(points.begin()->getFrame()); odd = ((index % 2) == 1); } @@ -337,13 +359,13 @@ } else if (getBaseQColor() == Qt::darkGreen) { oddBrushColour = Qt::green; } else { - oddBrushColour = oddBrushColour.light(150); + oddBrushColour = oddBrushColour.lighter(150); } oddBrushColour.setAlpha(100); } // SVDEBUG << "TimeInstantLayer::paint: resolution is " -// << m_model->getResolution() << " frames" << endl; +// << model->getResolution() << " frames" << endl; QPoint localPos; sv_frame_t illuminateFrame = -1; @@ -369,7 +391,7 @@ if (x == prevX && m_plotStyle == PlotInstants && p.getFrame() != illuminateFrame) continue; - int iw = v->getXForFrame(p.getFrame() + m_model->getResolution()) - x; + int iw = v->getXForFrame(p.getFrame() + model->getResolution()) - x; if (iw < 2) { if (iw < 1) { iw = 2; @@ -405,7 +427,7 @@ Event q(*j); nx = v->getXForFrame(q.getFrame()); } else { - nx = v->getXForFrame(m_model->getEndFrame()); + nx = v->getXForFrame(model->getEndFrame()); } if (nx >= x) { @@ -424,6 +446,11 @@ paint.setPen(getBaseQColor()); if (p.getLabel() != "") { + + // 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" // only draw if there's enough room from here to the next point @@ -454,16 +481,17 @@ cerr << "TimeInstantLayer::drawStart(" << e->x() << ")" << endl; #endif - if (!m_model) return; + auto model = ModelById::getAs(m_model); + if (!model) 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(); m_editingPoint = Event(frame, tr("New Point")); 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")); m_editingCommand->add(m_editingPoint); m_editing = true; @@ -476,11 +504,12 @@ cerr << "TimeInstantLayer::drawDrag(" << e->x() << ")" << endl; #endif - if (!m_model || !m_editing) return; + auto model = ModelById::getAs(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(); m_editingCommand->remove(m_editingPoint); m_editingPoint = m_editingPoint.withFrame(frame); m_editingCommand->add(m_editingPoint); @@ -492,10 +521,11 @@ #ifdef DEBUG_TIME_INSTANT_LAYER cerr << "TimeInstantLayer::drawEnd(" << e->x() << ")" << endl; #endif - if (!m_model || !m_editing) return; + auto model = ModelById::getAs(m_model); + if (!model || !m_editing) return; QString newName = tr("Add Point at %1 s") .arg(RealTime::frame2RealTime(m_editingPoint.getFrame(), - m_model->getSampleRate()) + model->getSampleRate()) .toText(false).c_str()); m_editingCommand->setName(newName); finish(m_editingCommand); @@ -506,7 +536,8 @@ void TimeInstantLayer::eraseStart(LayerGeometryProvider *v, QMouseEvent *e) { - if (!m_model) return; + auto model = ModelById::getAs(m_model); + if (!model) return; EventVector points = getLocalPoints(v, e->x()); if (points.empty()) return; @@ -529,7 +560,8 @@ void TimeInstantLayer::eraseEnd(LayerGeometryProvider *v, QMouseEvent *e) { - if (!m_model || !m_editing) return; + auto model = ModelById::getAs(m_model); + if (!model || !m_editing) return; m_editing = false; @@ -537,7 +569,7 @@ if (points.empty()) return; if (points.begin()->getFrame() != m_editingPoint.getFrame()) 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; @@ -551,7 +583,8 @@ cerr << "TimeInstantLayer::editStart(" << e->x() << ")" << endl; #endif - if (!m_model) return; + auto model = ModelById::getAs(m_model); + if (!model) return; EventVector points = getLocalPoints(v, e->x()); if (points.empty()) return; @@ -573,14 +606,15 @@ cerr << "TimeInstantLayer::editDrag(" << e->x() << ")" << endl; #endif - if (!m_model || !m_editing) return; + auto model = ModelById::getAs(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(); 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); @@ -594,11 +628,12 @@ #ifdef DEBUG_TIME_INSTANT_LAYER cerr << "TimeInstantLayer::editEnd(" << e->x() << ")" << endl; #endif - if (!m_model || !m_editing) return; + auto model = ModelById::getAs(m_model); + if (!model || !m_editing) return; if (m_editingCommand) { QString newName = tr("Move Point to %1 s") .arg(RealTime::frame2RealTime(m_editingPoint.getFrame(), - m_model->getSampleRate()) + model->getSampleRate()) .toText(false).c_str()); m_editingCommand->setName(newName); finish(m_editingCommand); @@ -610,7 +645,8 @@ bool TimeInstantLayer::editOpen(LayerGeometryProvider *v, QMouseEvent *e) { - if (!m_model) return false; + auto model = ModelById::getAs(m_model); + if (!model) return false; EventVector points = getLocalPoints(v, e->x()); if (points.empty()) return false; @@ -618,7 +654,7 @@ Event point = *points.begin(); ItemEditDialog *dialog = new ItemEditDialog - (m_model->getSampleRate(), + (model->getSampleRate(), ItemEditDialog::ShowTime | ItemEditDialog::ShowText); @@ -632,7 +668,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); @@ -645,13 +681,14 @@ void TimeInstantLayer::moveSelection(Selection s, sv_frame_t newStartFrame) { - if (!m_model) return; + auto model = ModelById::getAs(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 (auto p: points) { Event newPoint = p @@ -666,13 +703,14 @@ void TimeInstantLayer::resizeSelection(Selection s, Selection newSize) { - if (!m_model) return; + auto model = ModelById::getAs(m_model); + if (!model) 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()); @@ -694,13 +732,14 @@ void TimeInstantLayer::deleteSelection(Selection s) { - if (!m_model) return; + auto model = ModelById::getAs(m_model); + if (!model) return; ChangeEventsCommand *command = - new ChangeEventsCommand(m_model, tr("Delete Selection")); + new ChangeEventsCommand(m_model.untyped, tr("Delete Selection")); EventVector points = - m_model->getEventsWithin(s.getStartFrame(), s.getDuration()); + model->getEventsWithin(s.getStartFrame(), s.getDuration()); for (auto p: points) { command->remove(p); @@ -712,10 +751,11 @@ void TimeInstantLayer::copy(LayerGeometryProvider *v, Selection s, Clipboard &to) { - if (!m_model) return; + auto model = ModelById::getAs(m_model); + if (!model) return; EventVector points = - m_model->getEventsWithin(s.getStartFrame(), s.getDuration()); + model->getEventsWithin(s.getStartFrame(), s.getDuration()); for (auto p: points) { to.addPoint(p.withReferenceFrame(alignToReference(v, p.getFrame()))); @@ -725,7 +765,8 @@ bool TimeInstantLayer::paste(LayerGeometryProvider *v, const Clipboard &from, sv_frame_t frameOffset, bool) { - if (!m_model) return false; + auto model = ModelById::getAs(m_model); + if (!model) return false; EventVector points = from.getPoints(); @@ -749,7 +790,7 @@ } ChangeEventsCommand *command = - new ChangeEventsCommand(m_model, tr("Paste")); + new ChangeEventsCommand(m_model.untyped, tr("Paste")); for (EventVector::const_iterator i = points.begin(); i != points.end(); ++i) { diff -r de41a11cabc2 -r ac0a8addabcf layer/TimeInstantLayer.h --- a/layer/TimeInstantLayer.h Thu Jun 13 15:35:01 2019 +0100 +++ b/layer/TimeInstantLayer.h Wed Jul 17 14:25:16 2019 +0100 @@ -64,8 +64,8 @@ bool paste(LayerGeometryProvider *v, const Clipboard &from, sv_frame_t frameOffset, bool interactive) override; - const Model *getModel() const override { return m_model; } - void setModel(SparseOneDimensionalModel *model); + ModelId getModel() const override { return m_model; } + void setModel(ModelId model); // a SparseOneDimensionalModel PropertyList getProperties() const override; QString getPropertyLabel(const PropertyName &) const override; @@ -88,9 +88,9 @@ bool isLayerEditable() const override { return true; } - int getCompletion(LayerGeometryProvider *) const override { return m_model->getCompletion(); } + int getCompletion(LayerGeometryProvider *) const override; - bool needsTextLabelHeight() const override { return m_model->hasTextLabels(); } + bool needsTextLabelHeight() const override; bool getValueExtents(double &, double &, bool &, QString &) const override { return false; @@ -118,7 +118,7 @@ bool clipboardAlignmentDiffers(LayerGeometryProvider *v, const Clipboard &) const; - SparseOneDimensionalModel *m_model; + ModelId m_model; bool m_editing; Event m_editingPoint; ChangeEventsCommand *m_editingCommand; diff -r de41a11cabc2 -r ac0a8addabcf layer/TimeRulerLayer.cpp --- a/layer/TimeRulerLayer.cpp Thu Jun 13 15:35:01 2019 +0100 +++ b/layer/TimeRulerLayer.cpp Wed Jul 17 14:25:16 2019 +0100 @@ -36,14 +36,13 @@ TimeRulerLayer::TimeRulerLayer() : SingleColourLayer(), - m_model(nullptr), m_labelHeight(LabelTop) { } void -TimeRulerLayer::setModel(Model *model) +TimeRulerLayer::setModel(ModelId model) { if (m_model == model) return; m_model = model; @@ -54,7 +53,8 @@ TimeRulerLayer::snapToFeatureFrame(LayerGeometryProvider *v, sv_frame_t &frame, int &resolution, SnapType snap) const { - if (!m_model) { + auto model = ModelById::get(m_model); + if (!model) { resolution = 1; return false; } @@ -62,7 +62,7 @@ bool q; int64_t tickUSec = getMajorTickUSec(v, q); RealTime rtick = RealTime::fromMicroseconds(tickUSec); - sv_samplerate_t rate = m_model->getSampleRate(); + sv_samplerate_t rate = model->getSampleRate(); RealTime rt = RealTime::frame2RealTime(frame, rate); double ratio = rt / rtick; @@ -137,9 +137,10 @@ bool &quarterTicks) const { // return value is in microseconds - if (!m_model || !v) return 1000 * 1000; + auto model = ModelById::get(m_model); + if (!model || !v) return 1000 * 1000; - sv_samplerate_t sampleRate = m_model->getSampleRate(); + sv_samplerate_t sampleRate = model->getSampleRate(); if (!sampleRate) return 1000 * 1000; sv_frame_t startFrame = v->getStartFrame(); @@ -148,6 +149,11 @@ endFrame = startFrame + 1; } + // 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" + int exampleWidth = QFontMetrics(QFont()).width("10:42.987654"); int minPixelSpacing = v->getXForViewX(exampleWidth); @@ -210,7 +216,8 @@ int TimeRulerLayer::getXForUSec(LayerGeometryProvider *v, double us) const { - sv_samplerate_t sampleRate = m_model->getSampleRate(); + auto model = ModelById::get(m_model); + sv_samplerate_t sampleRate = model->getSampleRate(); double dframe = (us * sampleRate) / 1000000.0; double eps = 1e-7; sv_frame_t frame = sv_frame_t(floor(dframe + eps)); @@ -249,9 +256,10 @@ << ") [" << rect.width() << "x" << rect.height() << "]" << endl; #endif - if (!m_model || !m_model->isOK()) return; + auto model = ModelById::get(m_model); + if (!model || !model->isOK()) return; - sv_samplerate_t sampleRate = m_model->getSampleRate(); + sv_samplerate_t sampleRate = model->getSampleRate(); if (!sampleRate) return; sv_frame_t startFrame = v->getFrameForX(rect.x() - 50); diff -r de41a11cabc2 -r ac0a8addabcf layer/TimeRulerLayer.h --- a/layer/TimeRulerLayer.h Thu Jun 13 15:35:01 2019 +0100 +++ b/layer/TimeRulerLayer.h Wed Jul 17 14:25:16 2019 +0100 @@ -34,8 +34,8 @@ void paint(LayerGeometryProvider *v, QPainter &paint, QRect rect) const override; - void setModel(Model *); - const Model *getModel() const override { return m_model; } + void setModel(ModelId); + ModelId getModel() const override { return m_model; } enum LabelHeight { LabelTop, LabelMiddle, LabelBottom }; void setLabelHeight(LabelHeight h) { m_labelHeight = h; } @@ -63,7 +63,7 @@ bool canExistWithoutModel() const override { return true; } protected: - Model *m_model; + ModelId m_model; LabelHeight m_labelHeight; int getDefaultColourHint(bool dark, bool &impose) override; diff -r de41a11cabc2 -r ac0a8addabcf layer/TimeValueLayer.cpp --- 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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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) { diff -r de41a11cabc2 -r ac0a8addabcf layer/TimeValueLayer.h --- a/layer/TimeValueLayer.h Thu Jun 13 15:35:01 2019 +0100 +++ b/layer/TimeValueLayer.h Wed Jul 17 14:25:16 2019 +0100 @@ -74,8 +74,8 @@ bool paste(LayerGeometryProvider *v, const Clipboard &from, sv_frame_t frameOffset, bool interactive) override; - const Model *getModel() const override { return m_model; } - void setModel(SparseTimeValueModel *model); + ModelId getModel() const override { return m_model; } + void setModel(ModelId model); // a SparseTimeValueModel PropertyList getProperties() const override; QString getPropertyLabel(const PropertyName &) const override; @@ -124,11 +124,9 @@ bool isLayerEditable() const override { return true; } - int getCompletion(LayerGeometryProvider *) const override { return m_model->getCompletion(); } + int getCompletion(LayerGeometryProvider *) const override; - bool needsTextLabelHeight() const override { - return m_plotStyle == PlotSegmentation && m_model->hasTextLabels(); - } + bool needsTextLabelHeight() const override; bool getValueExtents(double &min, double &max, bool &logarithmic, QString &unit) const override; @@ -178,7 +176,7 @@ int getDefaultColourHint(bool dark, bool &impose) override; - SparseTimeValueModel *m_model; + ModelId m_model; bool m_editing; Event m_originalPoint; Event m_editingPoint; diff -r de41a11cabc2 -r ac0a8addabcf layer/WaveformLayer.cpp --- a/layer/WaveformLayer.cpp Thu Jun 13 15:35:01 2019 +0100 +++ b/layer/WaveformLayer.cpp Wed Jul 17 14:25:16 2019 +0100 @@ -41,7 +41,6 @@ WaveformLayer::WaveformLayer() : SingleColourLayer(), - m_model(nullptr), m_gain(1.0f), m_autoNormalize(false), m_showMeans(true), @@ -60,29 +59,47 @@ delete m_cache; } +const ZoomConstraint * +WaveformLayer::getZoomConstraint() const +{ + auto model = ModelById::get(m_model); + if (model) return model->getZoomConstraint(); + else return nullptr; +} + void -WaveformLayer::setModel(const RangeSummarisableTimeValueModel *model) +WaveformLayer::setModel(ModelId modelId) { + auto oldModel = ModelById::getAs(m_model); + auto newModel = ModelById::getAs(modelId); + + if (!modelId.isNone() && !newModel) { + throw std::logic_error("Not a RangeSummarisableTimeValueModel"); + } + + if (m_model == modelId) return; + m_model = modelId; + + m_cacheValid = false; + bool channelsChanged = false; if (m_channel == -1) { - if (!m_model) { - if (model) { + if (!oldModel) { + if (newModel) { channelsChanged = true; } } else { - if (model && - m_model->getChannelCount() != model->getChannelCount()) { + if (newModel && + oldModel->getChannelCount() != newModel->getChannelCount()) { channelsChanged = true; } } } - m_model = model; - m_cacheValid = false; - if (!m_model || !m_model->isOK()) return; - - connectSignals(m_model); - + if (newModel) { + connectSignals(m_model); + } + emit modelReplaced(); if (channelsChanged) emit layerParametersChanged(); @@ -96,7 +113,8 @@ list.push_back("Gain"); list.push_back("Normalize Visible Area"); - if (m_model && m_model->getChannelCount() > 1 && m_channel == -1) { + auto model = ModelById::getAs(m_model); + if (model && model->getChannelCount() > 1 && m_channel == -1) { list.push_back("Channels"); } @@ -323,8 +341,9 @@ WaveformLayer::getCompletion(LayerGeometryProvider *) const { int completion = 100; - if (!m_model || !m_model->isOK()) return completion; - if (m_model->isReady(&completion)) return 100; + auto model = ModelById::getAs(m_model); + if (!model || !model->isOK()) return completion; + if (model->isReady(&completion)) return 100; return completion; } @@ -361,9 +380,10 @@ bool &merging, bool &mixing) const { - if (!m_model || !m_model->isOK()) return 0; + auto model = ModelById::getAs(m_model); + if (!model || !model->isOK()) return 0; - int channels = m_model->getChannelCount(); + int channels = model->getChannelCount(); if (channels == 0) return 0; int rawChannels = channels; @@ -406,6 +426,9 @@ int x, int modelZoomLevel, sv_frame_t &f0, sv_frame_t &f1) const { + auto model = ModelById::getAs(m_model); + if (!model) return false; + sv_frame_t viewFrame = v->getFrameForX(x); if (viewFrame < 0) { f0 = 0; @@ -426,17 +449,20 @@ f1 = f1 * modelZoomLevel; } - return (f0 < m_model->getEndFrame()); + return (f0 < model->getEndFrame()); } float WaveformLayer::getNormalizeGain(LayerGeometryProvider *v, int channel) const { + auto model = ModelById::getAs(m_model); + if (!model) return 0.f; + sv_frame_t startFrame = v->getStartFrame(); sv_frame_t endFrame = v->getEndFrame(); - sv_frame_t modelStart = m_model->getStartFrame(); - sv_frame_t modelEnd = m_model->getEndFrame(); + sv_frame_t modelStart = model->getStartFrame(); + sv_frame_t modelEnd = model->getEndFrame(); sv_frame_t rangeStart, rangeEnd; @@ -450,7 +476,7 @@ if (rangeEnd < rangeStart) rangeEnd = rangeStart; RangeSummarisableTimeValueModel::Range range = - m_model->getSummary(channel, rangeStart, rangeEnd - rangeStart); + model->getSummary(channel, rangeStart, rangeEnd - rangeStart); int minChannel = 0, maxChannel = 0; bool mergingChannels = false, mixingChannels = false; @@ -460,7 +486,7 @@ if (mergingChannels || mixingChannels) { RangeSummarisableTimeValueModel::Range otherRange = - m_model->getSummary(1, rangeStart, rangeEnd - rangeStart); + model->getSummary(1, rangeStart, rangeEnd - rangeStart); range.setMax(std::max(range.max(), otherRange.max())); range.setMin(std::min(range.min(), otherRange.min())); range.setAbsmean(std::min(range.absmean(), otherRange.absmean())); @@ -472,7 +498,8 @@ void WaveformLayer::paint(LayerGeometryProvider *v, QPainter &viewPainter, QRect rect) const { - if (!m_model || !m_model->isOK()) { + auto model = ModelById::getAs(m_model); + if (!model || !model->isOK()) { return; } @@ -576,7 +603,7 @@ if (zoomLevel.zone == ZoomLevel::FramesPerPixel) { desiredBlockSize = zoomLevel.level; } - int blockSize = m_model->getSummaryBlockSize(desiredBlockSize); + int blockSize = model->getSummaryBlockSize(desiredBlockSize); sv_frame_t frame0; sv_frame_t frame1; @@ -625,7 +652,7 @@ } if (m_aggressive) { - if (m_model->isReady() && rect == v->getPaintRect()) { + if (model->isReady() && rect == v->getPaintRect()) { m_cacheValid = true; m_cacheZoomLevel = zoomLevel; } @@ -642,9 +669,12 @@ int blockSize, RangeVec &ranges) const { + auto model = ModelById::getAs(m_model); + if (!model) return; + for (int ch = minChannel; ch <= maxChannel; ++ch) { ranges.push_back({}); - m_model->getSummaries(ch, frame0, frame1 - frame0, + model->getSummaries(ch, frame0, frame1 - frame0, ranges[ch - minChannel], blockSize); #ifdef DEBUG_WAVEFORM_PAINT SVCERR << "channel " << ch << ": " << ranges[ch - minChannel].size() << " ranges from " << frame0 << " to " << frame1 << " at zoom level " << blockSize << endl; @@ -654,9 +684,9 @@ if (mixingOrMerging) { if (minChannel != 0 || maxChannel != 0) { throw std::logic_error("Internal error: min & max channels should be 0 when merging or mixing all channels"); - } else if (m_model->getChannelCount() > 1) { + } else if (model->getChannelCount() > 1) { ranges.push_back({}); - m_model->getSummaries + model->getSummaries (1, frame0, frame1 - frame0, ranges[1], blockSize); } } @@ -669,11 +699,14 @@ int oversampleBy, RangeVec &ranges) const { + auto model = ModelById::getAs(m_model); + if (!model) return; + if (mixingOrMerging) { if (minChannel != 0 || maxChannel != 0) { throw std::logic_error("Internal error: min & max channels should be 0 when merging or mixing all channels"); } - if (m_model->getChannelCount() > 1) { + if (model->getChannelCount() > 1) { // call back on self for the individual channels with // mixingOrMerging false getOversampledRanges @@ -686,8 +719,8 @@ // sample rate, not the oversampled rate sv_frame_t tail = 16; - sv_frame_t startFrame = m_model->getStartFrame(); - sv_frame_t endFrame = m_model->getEndFrame(); + sv_frame_t startFrame = model->getStartFrame(); + sv_frame_t endFrame = model->getEndFrame(); sv_frame_t rf0 = frame0 - tail; if (rf0 < startFrame) { @@ -706,7 +739,7 @@ for (int ch = minChannel; ch <= maxChannel; ++ch) { floatvec_t oversampled = WaveformOversampler::getOversampledData - (m_model, ch, frame0, frame1 - frame0, oversampleBy); + (*model, ch, frame0, frame1 - frame0, oversampleBy); RangeSummarisableTimeValueModel::RangeBlock rr; for (float v: oversampled) { RangeSummarisableTimeValueModel::Range r; @@ -738,6 +771,9 @@ sv_frame_t frame1) const { + auto model = ModelById::getAs(m_model); + if (!model) return; + int x0 = rect.left(); int y0 = rect.top(); @@ -759,9 +795,9 @@ if (midColour == Qt::black) { midColour = Qt::gray; } else if (v->hasLightBackground()) { - midColour = midColour.light(150); + midColour = midColour.lighter(150); } else { - midColour = midColour.light(50); + midColour = midColour.lighter(50); } double gain = m_effectiveGains[ch]; @@ -1033,7 +1069,7 @@ penWidth = 0.0; } - if (m_model->isReady()) { + if (model->isReady()) { paint->setPen(QPen(baseColour, penWidth)); } else { paint->setPen(QPen(midColour, penWidth)); @@ -1136,7 +1172,8 @@ { int x = pos.x(); - if (!m_model || !m_model->isOK()) return ""; + auto model = ModelById::getAs(m_model); + if (!model || !model->isOK()) return ""; ZoomLevel zoomLevel = v->getZoomLevel(); @@ -1145,15 +1182,15 @@ desiredBlockSize = zoomLevel.level; } - int blockSize = m_model->getSummaryBlockSize(desiredBlockSize); + int blockSize = model->getSummaryBlockSize(desiredBlockSize); sv_frame_t f0, f1; if (!getSourceFramesForX(v, x, blockSize, f0, f1)) return ""; QString text; - RealTime rt0 = RealTime::frame2RealTime(f0, m_model->getSampleRate()); - RealTime rt1 = RealTime::frame2RealTime(f1, m_model->getSampleRate()); + RealTime rt0 = RealTime::frame2RealTime(f0, model->getSampleRate()); + RealTime rt1 = RealTime::frame2RealTime(f1, model->getSampleRate()); if (f1 != f0 + 1 && (rt0.sec != rt1.sec || rt0.msec() != rt1.msec())) { text += tr("Time:\t%1 - %2") @@ -1174,7 +1211,7 @@ for (int ch = minChannel; ch <= maxChannel; ++ch) { RangeSummarisableTimeValueModel::RangeBlock ranges; - m_model->getSummaries(ch, f0, f1 - f0, ranges, blockSize); + model->getSummaries(ch, f0, f1 - f0, ranges, blockSize); if (ranges.empty()) continue; @@ -1374,6 +1411,11 @@ int WaveformLayer::getVerticalScaleWidth(LayerGeometryProvider *, bool, QPainter &paint) const { + // 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 (m_scale == LinearScale) { return paint.fontMetrics().width("0.0") + 13; } else { @@ -1385,7 +1427,8 @@ void WaveformLayer::paintVerticalScale(LayerGeometryProvider *v, bool, QPainter &paint, QRect rect) const { - if (!m_model || !m_model->isOK()) { + auto model = ModelById::getAs(m_model); + if (!model || !model->isOK()) { return; } diff -r de41a11cabc2 -r ac0a8addabcf layer/WaveformLayer.h --- a/layer/WaveformLayer.h Thu Jun 13 15:35:01 2019 +0100 +++ b/layer/WaveformLayer.h Wed Jul 17 14:25:16 2019 +0100 @@ -36,10 +36,8 @@ WaveformLayer(); ~WaveformLayer(); - const ZoomConstraint *getZoomConstraint() const override { - return m_model ? m_model->getZoomConstraint() : 0; - } - const Model *getModel() const override { return m_model; } + const ZoomConstraint *getZoomConstraint() const override; + ModelId getModel() const override { return m_model; } void paint(LayerGeometryProvider *v, QPainter &paint, QRect rect) const override; QString getFeatureDescription(LayerGeometryProvider *v, QPoint &) const override; @@ -51,7 +49,7 @@ int getVerticalScaleWidth(LayerGeometryProvider *v, bool detailed, QPainter &) const override; void paintVerticalScale(LayerGeometryProvider *v, bool detailed, QPainter &paint, QRect rect) const override; - void setModel(const RangeSummarisableTimeValueModel *model); + void setModel(ModelId model); // a RangeSummarisableTimeValueModel PropertyList getProperties() const override; QString getPropertyLabel(const PropertyName &) const override; @@ -196,7 +194,7 @@ protected: double dBscale(double sample, int m) const; - const RangeSummarisableTimeValueModel *m_model; // I do not own this + ModelId m_model; typedef std::vector RangeVec; diff -r de41a11cabc2 -r ac0a8addabcf view/AlignmentView.cpp --- a/view/AlignmentView.cpp Thu Jun 13 15:35:01 2019 +0100 +++ b/view/AlignmentView.cpp Wed Jul 17 14:25:16 2019 +0100 @@ -147,25 +147,26 @@ return getDefaultKeyFrames(); } - SparseOneDimensionalModel *m = nullptr; + ModelId m; // get the topmost such for (int i = 0; i < m_above->getLayerCount(); ++i) { if (qobject_cast(m_above->getLayer(i))) { - SparseOneDimensionalModel *mm = - qobject_cast - (m_above->getLayer(i)->getModel()); - if (mm) m = mm; + ModelId mm = m_above->getLayer(i)->getModel(); + if (ModelById::isa(mm)) { + m = mm; + } } } - if (!m) { + auto model = ModelById::getAs(m); + if (!model) { return getDefaultKeyFrames(); } vector keyFrames; - EventVector pp = m->getAllEvents(); + EventVector pp = model->getAllEvents(); for (EventVector::const_iterator pi = pp.begin(); pi != pp.end(); ++pi) { keyFrames.push_back(pi->getFrame()); } diff -r de41a11cabc2 -r ac0a8addabcf view/Overview.cpp --- a/view/Overview.cpp Thu Jun 13 15:35:01 2019 +0100 +++ b/view/Overview.cpp Wed Jul 17 14:25:16 2019 +0100 @@ -42,7 +42,7 @@ } void -Overview::modelChangedWithin(sv_frame_t startFrame, sv_frame_t endFrame) +Overview::modelChangedWithin(ModelId modelId, sv_frame_t startFrame, sv_frame_t endFrame) { using namespace std::rel_ops; @@ -60,9 +60,8 @@ if (m_modelTestTime.elapsed() < 1000) { for (LayerList::const_iterator i = m_layerStack.begin(); i != m_layerStack.end(); ++i) { - if ((*i)->getModel() && - (!(*i)->getModel()->isOK() || - !(*i)->getModel()->isReady())) { + auto model = ModelById::get((*i)->getModel()); + if (model && (!model->isOK() || !model->isReady())) { return; } } @@ -71,7 +70,7 @@ } } - View::modelChangedWithin(startFrame, endFrame); + View::modelChangedWithin(modelId, startFrame, endFrame); } void diff -r de41a11cabc2 -r ac0a8addabcf view/Overview.h --- a/view/Overview.h Thu Jun 13 15:35:01 2019 +0100 +++ b/view/Overview.h Wed Jul 17 14:25:16 2019 +0100 @@ -41,7 +41,7 @@ QString getPropertyContainerIconName() const override { return "panner"; } public slots: - void modelChangedWithin(sv_frame_t startFrame, sv_frame_t endFrame) override; + void modelChangedWithin(ModelId, sv_frame_t startFrame, sv_frame_t endFrame) override; void modelReplaced() override; void globalCentreFrameChanged(sv_frame_t) override; diff -r de41a11cabc2 -r ac0a8addabcf view/Pane.cpp --- a/view/Pane.cpp Thu Jun 13 15:35:01 2019 +0100 +++ b/view/Pane.cpp Wed Jul 17 14:25:16 2019 +0100 @@ -367,33 +367,49 @@ Layer *topLayer = getTopLayer(); bool haveSomeTimeXAxis = false; - const Model *waveformModel = nullptr; // just for reporting purposes - const Model *workModel = nullptr; - - for (LayerList::iterator vi = m_layerStack.end(); vi != m_layerStack.begin(); ) { + ModelId waveformModelId; // just for reporting purposes + ModelId workModelId; + + for (LayerList::iterator vi = m_layerStack.end(); + vi != m_layerStack.begin(); ) { + --vi; + if (!haveSomeTimeXAxis && (*vi)->hasTimeXAxis()) { haveSomeTimeXAxis = true; } - if (dynamic_cast(*vi)) { - waveformModel = (*vi)->getModel(); - workModel = waveformModel; - } else { - Model *m = (*vi)->getModel(); - if (dynamic_cast(m)) { - workModel = m; - } else if (m && dynamic_cast(m->getSourceModel())) { - workModel = m->getSourceModel(); + + ModelId modelId = (*vi)->getModel(); + if (!modelId.isNone()) { + if (dynamic_cast(*vi)) { + waveformModelId = modelId; + workModelId = modelId; + } else { + if (ModelById::isa(modelId)) { + workModelId = modelId; + } else { + auto model = ModelById::get(modelId); + if (model) { + ModelId sourceId = model->getSourceModel(); + if (ModelById::isa(sourceId)) { + workModelId = sourceId; + } + } + } } } - if (waveformModel && workModel && haveSomeTimeXAxis) break; + if (!waveformModelId.isNone() && + !workModelId.isNone() && + haveSomeTimeXAxis) { + break; + } } // Block off left and right extents so we can see where the main model ends - if (workModel && hasTopLayerTimeXAxis()) { - drawModelTimeExtents(r, paint, workModel); + if (!workModelId.isNone() && hasTopLayerTimeXAxis()) { + drawModelTimeExtents(r, paint, workModelId); } // Crosshairs for mouse movement in measure mode @@ -444,26 +460,26 @@ paint.setPen(QColor(50, 50, 50)); - if (waveformModel && + if (!waveformModelId.isNone() && sampleRate && m_manager && m_manager->shouldShowDuration()) { - drawDurationAndRate(r, waveformModel, sampleRate, paint); + drawDurationAndRate(r, waveformModelId, sampleRate, paint); } bool haveWorkTitle = false; - if (workModel && + if (!workModelId.isNone() && m_manager && m_manager->shouldShowWorkTitle()) { - drawWorkTitle(r, paint, workModel); + drawWorkTitle(r, paint, workModelId); haveWorkTitle = true; } - if (workModel && + if (!workModelId.isNone() && m_manager && m_manager->getAlignMode()) { - drawAlignmentStatus(r, paint, workModel, haveWorkTitle); + drawAlignmentStatus(r, paint, workModelId, haveWorkTitle); } if (m_manager && @@ -632,6 +648,11 @@ paint.save(); + // 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" + int tabStop = paint.fontMetrics().width(tr("Some lengthy prefix:")); @@ -750,8 +771,11 @@ } void -Pane::drawModelTimeExtents(QRect r, QPainter &paint, const Model *model) +Pane::drawModelTimeExtents(QRect r, QPainter &paint, ModelId modelId) { + auto model = ModelById::get(modelId); + if (!model) return; + paint.save(); QBrush brush; @@ -788,14 +812,17 @@ } void -Pane::drawAlignmentStatus(QRect r, QPainter &paint, const Model *model, +Pane::drawAlignmentStatus(QRect r, QPainter &paint, ModelId modelId, bool down) { - const Model *reference = model->getAlignmentReference(); + auto model = ModelById::get(modelId); + if (!model) return; + + ModelId reference = model->getAlignmentReference(); /* if (!reference) { cerr << "Pane[" << this << "]::drawAlignmentStatus: No reference" << endl; - } else if (reference == model) { + } else if (reference == model->getId()) { cerr << "Pane[" << this << "]::drawAlignmentStatus: This is the reference model" << endl; } else { cerr << "Pane[" << this << "]::drawAlignmentStatus: This is not the reference" << endl; @@ -804,9 +831,9 @@ QString text; int completion = 100; - if (reference == model) { + if (reference == modelId) { text = tr("Reference"); - } else if (!reference) { + } else if (reference.isNone()) { text = tr("Unaligned"); } else { completion = model->getAlignmentCompletion(); @@ -841,15 +868,18 @@ } void -Pane::modelAlignmentCompletionChanged() +Pane::modelAlignmentCompletionChanged(ModelId modelId) { - View::modelAlignmentCompletionChanged(); + View::modelAlignmentCompletionChanged(modelId); update(QRect(0, 0, 300, 100)); } void -Pane::drawWorkTitle(QRect r, QPainter &paint, const Model *model) +Pane::drawWorkTitle(QRect r, QPainter &paint, ModelId modelId) { + auto model = ModelById::get(modelId); + if (!model) return; + QString title = model->getTitle(); QString maker = model->getMaker(); //SVDEBUG << "Pane::drawWorkTitle: title=\"" << title//<< "\", maker=\"" << maker << "\"" << endl; @@ -1025,9 +1055,12 @@ } void -Pane::drawDurationAndRate(QRect r, const Model *waveformModel, +Pane::drawDurationAndRate(QRect r, ModelId waveformModelId, sv_samplerate_t sampleRate, QPainter &paint) { + auto waveformModel = ModelById::get(waveformModelId); + if (!waveformModel) return; + int fontHeight = paint.fontMetrics().height(); int fontAscent = paint.fontMetrics().ascent(); diff -r de41a11cabc2 -r ac0a8addabcf view/Pane.h --- a/view/Pane.h Thu Jun 13 15:35:01 2019 +0100 +++ b/view/Pane.h Wed Jul 17 14:25:16 2019 +0100 @@ -88,7 +88,7 @@ virtual void toolModeChanged() override; virtual void zoomWheelsEnabledChanged() override; virtual void viewZoomLevelChanged(View *, ZoomLevel, bool locked) override; - virtual void modelAlignmentCompletionChanged() override; + virtual void modelAlignmentCompletionChanged(ModelId) override; // local slots, not overrides virtual void horizontalThumbwheelMoved(int value); @@ -129,12 +129,12 @@ void drawVerticalScale(QRect r, Layer *, QPainter &); void drawFeatureDescription(Layer *, QPainter &); void drawCentreLine(sv_samplerate_t, QPainter &, bool omitLine); - void drawModelTimeExtents(QRect, QPainter &, const Model *); - void drawDurationAndRate(QRect, const Model *, sv_samplerate_t, QPainter &); - void drawWorkTitle(QRect, QPainter &, const Model *); + void drawModelTimeExtents(QRect, QPainter &, ModelId); + void drawDurationAndRate(QRect, ModelId, sv_samplerate_t, QPainter &); + void drawWorkTitle(QRect, QPainter &, ModelId); void drawLayerNames(QRect, QPainter &); void drawEditingSelection(QPainter &); - void drawAlignmentStatus(QRect, QPainter &, const Model *, bool down); + void drawAlignmentStatus(QRect, QPainter &, ModelId, bool down); virtual bool render(QPainter &paint, int x0, sv_frame_t f0, sv_frame_t f1) override; diff -r de41a11cabc2 -r ac0a8addabcf view/View.cpp --- a/view/View.cpp Thu Jun 13 15:35:01 2019 +0100 +++ b/view/View.cpp Wed Jul 17 14:25:16 2019 +0100 @@ -632,9 +632,9 @@ if (widgetLight == light) { if (widgetLight) { - return widgetbg.light(); + return widgetbg.lighter(); } else { - return widgetbg.dark(); + return widgetbg.darker(); } } else if (light) return Qt::white; @@ -706,14 +706,14 @@ this, SLOT(layerMeasurementRectsChanged())); connect(layer, SIGNAL(layerNameChanged()), this, SLOT(layerNameChanged())); - connect(layer, SIGNAL(modelChanged()), - this, SLOT(modelChanged())); - connect(layer, SIGNAL(modelCompletionChanged()), - this, SLOT(modelCompletionChanged())); - connect(layer, SIGNAL(modelAlignmentCompletionChanged()), - this, SLOT(modelAlignmentCompletionChanged())); - connect(layer, SIGNAL(modelChangedWithin(sv_frame_t, sv_frame_t)), - this, SLOT(modelChangedWithin(sv_frame_t, sv_frame_t))); + connect(layer, SIGNAL(modelChanged(ModelId)), + this, SLOT(modelChanged(ModelId))); + connect(layer, SIGNAL(modelCompletionChanged(ModelId)), + this, SLOT(modelCompletionChanged(ModelId))); + connect(layer, SIGNAL(modelAlignmentCompletionChanged(ModelId)), + this, SLOT(modelAlignmentCompletionChanged(ModelId))); + connect(layer, SIGNAL(modelChangedWithin(ModelId, sv_frame_t, sv_frame_t)), + this, SLOT(modelChangedWithin(ModelId, sv_frame_t, sv_frame_t))); connect(layer, SIGNAL(modelReplaced()), this, SLOT(modelReplaced())); @@ -761,14 +761,14 @@ this, SLOT(layerParameterRangesChanged())); disconnect(layer, SIGNAL(layerNameChanged()), this, SLOT(layerNameChanged())); - disconnect(layer, SIGNAL(modelChanged()), - this, SLOT(modelChanged())); - disconnect(layer, SIGNAL(modelCompletionChanged()), - this, SLOT(modelCompletionChanged())); - disconnect(layer, SIGNAL(modelAlignmentCompletionChanged()), - this, SLOT(modelAlignmentCompletionChanged())); - disconnect(layer, SIGNAL(modelChangedWithin(sv_frame_t, sv_frame_t)), - this, SLOT(modelChangedWithin(sv_frame_t, sv_frame_t))); + disconnect(layer, SIGNAL(modelChanged(ModelId)), + this, SLOT(modelChanged(ModelId))); + disconnect(layer, SIGNAL(modelCompletionChanged(ModelId)), + this, SLOT(modelCompletionChanged(ModelId))); + disconnect(layer, SIGNAL(modelAlignmentCompletionChanged(ModelId)), + this, SLOT(modelAlignmentCompletionChanged(ModelId))); + disconnect(layer, SIGNAL(modelChangedWithin(ModelId, sv_frame_t, sv_frame_t)), + this, SLOT(modelChangedWithin(ModelId, sv_frame_t, sv_frame_t))); disconnect(layer, SIGNAL(modelReplaced()), this, SLOT(modelReplaced())); @@ -922,14 +922,12 @@ } void -View::modelChanged() +View::modelChanged(ModelId modelId) { - QObject *obj = sender(); - #ifdef DEBUG_VIEW_WIDGET_PAINT cerr << "View(" << this << ")::modelChanged()" << endl; #endif - + // If the model that has changed is not used by any of the cached // layers, we won't need to recreate the cache @@ -939,7 +937,7 @@ LayerList scrollables = getScrollableBackLayers(false, discard); for (LayerList::const_iterator i = scrollables.begin(); i != scrollables.end(); ++i) { - if (*i == obj || (*i)->getModel() == obj) { + if ((*i)->getModel() == modelId) { recreate = true; break; } @@ -951,16 +949,15 @@ emit layerModelChanged(); - checkProgress(obj); + checkProgress(modelId); update(); } void -View::modelChangedWithin(sv_frame_t startFrame, sv_frame_t endFrame) +View::modelChangedWithin(ModelId modelId, + sv_frame_t startFrame, sv_frame_t endFrame) { - QObject *obj = sender(); - sv_frame_t myStartFrame = getStartFrame(); sv_frame_t myEndFrame = getEndFrame(); @@ -969,11 +966,11 @@ #endif if (myStartFrame > 0 && endFrame < myStartFrame) { - checkProgress(obj); + checkProgress(modelId); return; } if (startFrame > myEndFrame) { - checkProgress(obj); + checkProgress(modelId); return; } @@ -986,7 +983,7 @@ LayerList scrollables = getScrollableBackLayers(false, discard); for (LayerList::const_iterator i = scrollables.begin(); i != scrollables.end(); ++i) { - if (*i == obj || (*i)->getModel() == obj) { + if ((*i)->getModel() == modelId) { recreate = true; break; } @@ -999,27 +996,21 @@ if (startFrame < myStartFrame) startFrame = myStartFrame; if (endFrame > myEndFrame) endFrame = myEndFrame; - checkProgress(obj); + checkProgress(modelId); update(); } void -View::modelCompletionChanged() +View::modelCompletionChanged(ModelId modelId) { -// cerr << "View(" << this << ")::modelCompletionChanged()" << endl; - - QObject *obj = sender(); - checkProgress(obj); + checkProgress(modelId); } void -View::modelAlignmentCompletionChanged() +View::modelAlignmentCompletionChanged(ModelId modelId) { -// cerr << "View(" << this << ")::modelAlignmentCompletionChanged()" << endl; - - QObject *obj = sender(); - checkProgress(obj); + checkProgress(modelId); } void @@ -1270,11 +1261,13 @@ bool first = true; sv_frame_t startFrame = 0; - for (LayerList::const_iterator i = m_layerStack.begin(); i != m_layerStack.end(); ++i) { - - if ((*i)->getModel() && (*i)->getModel()->isOK()) { - - sv_frame_t thisStartFrame = (*i)->getModel()->getStartFrame(); + for (Layer *layer: m_layerStack) { + + auto model = ModelById::get(layer->getModel()); + + if (model && model->isOK()) { + + sv_frame_t thisStartFrame = model->getStartFrame(); if (first || thisStartFrame < startFrame) { startFrame = thisStartFrame; @@ -1282,6 +1275,7 @@ first = false; } } + return startFrame; } @@ -1291,11 +1285,13 @@ bool first = true; sv_frame_t endFrame = 0; - for (LayerList::const_iterator i = m_layerStack.begin(); i != m_layerStack.end(); ++i) { - - if ((*i)->getModel() && (*i)->getModel()->isOK()) { - - sv_frame_t thisEndFrame = (*i)->getModel()->getEndFrame(); + for (Layer *layer: m_layerStack) { + + auto model = ModelById::get(layer->getModel()); + + if (model && model->isOK()) { + + sv_frame_t thisEndFrame = model->getEndFrame(); if (first || thisEndFrame > endFrame) { endFrame = thisEndFrame; @@ -1317,11 +1313,15 @@ //!!! nah, this wants to always return the sr of the main model! - for (LayerList::const_iterator i = m_layerStack.begin(); i != m_layerStack.end(); ++i) { - if ((*i)->getModel() && (*i)->getModel()->isOK()) { - return (*i)->getModel()->getSampleRate(); + for (Layer *layer: m_layerStack) { + + auto model = ModelById::get(layer->getModel()); + + if (model && model->isOK()) { + return model->getSampleRate(); } } + return 0; } @@ -1338,52 +1338,50 @@ continue; } - if (layer && layer->getModel()) { - Model *model = layer->getModel(); - models.insert(model); + if (layer && !layer->getModel().isNone()) { + models.insert(layer->getModel()); } } return models; } -Model * +ModelId View::getAligningModel() const { if (!m_manager || !m_manager->getAlignMode() || - !m_manager->getPlaybackModel()) { - return nullptr; + m_manager->getPlaybackModel().isNone()) { + return {}; } - Model *anyModel = nullptr; - Model *alignedModel = nullptr; - Model *goodModel = nullptr; - - for (LayerList::const_iterator i = m_layerStack.begin(); - i != m_layerStack.end(); ++i) { - - Layer *layer = *i; + ModelId anyModel; + ModelId alignedModel; + ModelId goodModel; + + for (auto layer: m_layerStack) { if (!layer) continue; if (dynamic_cast(layer)) continue; - Model *model = (*i)->getModel(); + ModelId thisId = layer->getModel(); + auto model = ModelById::get(thisId); if (!model) continue; - anyModel = model; - - if (model->getAlignmentReference()) { - alignedModel = model; + anyModel = thisId; + + if (!model->getAlignmentReference().isNone()) { + alignedModel = thisId; if (layer->isLayerOpaque() || - dynamic_cast(model)) { - goodModel = model; + std::dynamic_pointer_cast + (model)) { + goodModel = thisId; } } } - if (goodModel) return goodModel; - else if (alignedModel) return alignedModel; + if (!goodModel.isNone()) return goodModel; + else if (!alignedModel.isNone()) return alignedModel; else return anyModel; } @@ -1391,7 +1389,7 @@ View::alignFromReference(sv_frame_t f) const { if (!m_manager || !m_manager->getAlignMode()) return f; - Model *aligningModel = getAligningModel(); + auto aligningModel = ModelById::get(getAligningModel()); if (!aligningModel) return f; return aligningModel->alignFromReference(f); } @@ -1400,7 +1398,7 @@ View::alignToReference(sv_frame_t f) const { if (!m_manager->getAlignMode()) return f; - Model *aligningModel = getAligningModel(); + auto aligningModel = ModelById::get(getAligningModel()); if (!aligningModel) return f; return aligningModel->alignToReference(f); } @@ -1412,7 +1410,7 @@ sv_frame_t pf = m_manager->getPlaybackFrame(); if (!m_manager->getAlignMode()) return pf; - Model *aligningModel = getAligningModel(); + auto aligningModel = ModelById::get(getAligningModel()); if (!aligningModel) return pf; sv_frame_t af = aligningModel->alignFromReference(pf); @@ -1721,25 +1719,27 @@ QPushButton *cancel = qobject_cast(sender()); if (!cancel) return; + Layer *layer = nullptr; + for (ProgressMap::iterator i = m_progressBars.begin(); i != m_progressBars.end(); ++i) { - if (i->second.cancel == cancel) { - - Layer *layer = i->first; - Model *model = layer->getModel(); - - if (model) model->abandon(); + layer = i->first; + break; } } + + if (layer) { + emit cancelButtonPressed(layer); + } } void -View::checkProgress(void *object) +View::checkProgress(ModelId modelId) { if (!m_showProgress) { #ifdef DEBUG_PROGRESS_STUFF - SVCERR << "View[" << this << "]::checkProgress(" << object << "): " + SVCERR << "View[" << this << "]::checkProgress(" << modelId << "): " << "m_showProgress is off" << endl; #endif return; @@ -1759,7 +1759,7 @@ QProgressBar *pb = i->second.bar; QPushButton *cancel = i->second.cancel; - if (i->first == object) { + if (i->first && i->first->getModel() == modelId) { found = true; @@ -1793,23 +1793,28 @@ m_lastError = error; } - Model *model = i->first->getModel(); - RangeSummarisableTimeValueModel *wfm = - dynamic_cast(model); + auto model = ModelById::get(modelId); + auto wfm = std::dynamic_pointer_cast + (model); if (completion > 0) { pb->setMaximum(100); // was 0, for indeterminate start } if (completion >= 100) { - - //!!! + if (wfm || (model && - (wfm = dynamic_cast + (wfm = ModelById::getAs (model->getSourceModel())))) { + completion = wfm->getAlignmentCompletion(); + // We don't allow cancelling alignment operations + // - they aren't usually all that expensive, and + // it would leave things in a very uncertain state + showCancelButton = false; + #ifdef DEBUG_PROGRESS_STUFF SVCERR << "View[" << this << "]::checkProgress(" << object << "): " << "alignment completion = " << completion << endl; @@ -2340,6 +2345,11 @@ (i->getEndFrame() - i->getStartFrame(), sampleRate) .toText(true))) .arg(i->getEndFrame() - i->getStartFrame()); + + // 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" int sw = metrics.width(startText), ew = metrics.width(endText), diff -r de41a11cabc2 -r ac0a8addabcf view/View.h --- a/view/View.h Thu Jun 13 15:35:01 2019 +0100 +++ b/view/View.h Wed Jul 17 14:25:16 2019 +0100 @@ -27,6 +27,8 @@ #include "base/XmlExportable.h" #include "base/BaseTypes.h" +#include "data/model/Model.h" + // #define DEBUG_VIEW_WIDGET_PAINT 1 class Layer; @@ -381,11 +383,11 @@ double scalePenWidth(double width) const override; QPen scalePen(QPen pen) const override; - typedef std::set ModelSet; + typedef std::set ModelSet; ModelSet getModels(); //!!! - Model *getAligningModel() const; + ModelId getAligningModel() const; sv_frame_t alignFromReference(sv_frame_t) const; sv_frame_t alignToReference(sv_frame_t) const; sv_frame_t getAlignedPlaybackFrame() const; @@ -406,6 +408,8 @@ void layerModelChanged(); + void cancelButtonPressed(Layer *); + void centreFrameChanged(sv_frame_t frame, bool globalScroll, PlaybackFollowMode followMode); @@ -415,10 +419,10 @@ void contextHelpChanged(const QString &); public slots: - virtual void modelChanged(); - virtual void modelChangedWithin(sv_frame_t startFrame, sv_frame_t endFrame); - virtual void modelCompletionChanged(); - virtual void modelAlignmentCompletionChanged(); + virtual void modelChanged(ModelId); + virtual void modelChangedWithin(ModelId, sv_frame_t startFrame, sv_frame_t endFrame); + virtual void modelCompletionChanged(ModelId); + virtual void modelAlignmentCompletionChanged(ModelId); virtual void modelReplaced(); virtual void layerParametersChanged(); virtual void layerParameterRangesChanged(); @@ -502,7 +506,7 @@ void movePlayPointer(sv_frame_t f); - void checkProgress(void *object); + void checkProgress(ModelId); int getProgressBarWidth() const; // if visible int effectiveDevicePixelRatio() const; diff -r de41a11cabc2 -r ac0a8addabcf view/ViewManager.cpp --- a/view/ViewManager.cpp Thu Jun 13 15:35:01 2019 +0100 +++ b/view/ViewManager.cpp Wed Jul 17 14:25:16 2019 +0100 @@ -35,7 +35,6 @@ m_globalCentreFrame(0), m_globalZoom(ZoomLevel::FramesPerPixel, 1024), m_playbackFrame(0), - m_playbackModel(nullptr), m_mainModelSampleRate(0), m_lastLeft(0), m_lastRight(0), @@ -194,14 +193,14 @@ } } -Model * +ModelId ViewManager::getPlaybackModel() const { return m_playbackModel; } void -ViewManager::setPlaybackModel(Model *model) +ViewManager::setPlaybackModel(ModelId model) { m_playbackModel = model; } @@ -212,10 +211,14 @@ #ifdef DEBUG_VIEW_MANAGER cerr << "ViewManager::alignPlaybackFrameToReference(" << frame << "): playback model is " << m_playbackModel << endl; #endif - if (!m_playbackModel || !m_alignMode) { + if (m_playbackModel.isNone() || !m_alignMode) { return frame; } else { - sv_frame_t f = m_playbackModel->alignToReference(frame); + auto playbackModel = ModelById::get(m_playbackModel); + if (!playbackModel) { + return frame; + } + sv_frame_t f = playbackModel->alignToReference(frame); #ifdef DEBUG_VIEW_MANAGER cerr << "aligned frame = " << f << endl; #endif @@ -229,10 +232,14 @@ #ifdef DEBUG_VIEW_MANAGER cerr << "ViewManager::alignReferenceToPlaybackFrame(" << frame << "): playback model is " << m_playbackModel << endl; #endif - if (!m_playbackModel || !m_alignMode) { + if (m_playbackModel.isNone() || !m_alignMode) { return frame; } else { - sv_frame_t f = m_playbackModel->alignFromReference(frame); + auto playbackModel = ModelById::get(m_playbackModel); + if (!playbackModel) { + return frame; + } + sv_frame_t f = playbackModel->alignFromReference(frame); #ifdef DEBUG_VIEW_MANAGER cerr << "aligned frame = " << f << endl; #endif diff -r de41a11cabc2 -r ac0a8addabcf view/ViewManager.h --- a/view/ViewManager.h Thu Jun 13 15:35:01 2019 +0100 +++ b/view/ViewManager.h Wed Jul 17 14:25:16 2019 +0100 @@ -29,6 +29,8 @@ #include "base/BaseTypes.h" #include "base/ZoomLevel.h" +#include "data/model/Model.h" + class AudioPlaySource; class AudioRecordTarget; class Model; @@ -93,8 +95,8 @@ sv_frame_t getPlaybackFrame() const; // the set method is a slot // Only meaningful in solo mode, and used for optional alignment feature - Model *getPlaybackModel() const; - void setPlaybackModel(Model *); + ModelId getPlaybackModel() const; + void setPlaybackModel(ModelId); sv_frame_t alignPlaybackFrameToReference(sv_frame_t) const override; sv_frame_t alignReferenceToPlaybackFrame(sv_frame_t) const override; @@ -347,7 +349,7 @@ sv_frame_t m_globalCentreFrame; ZoomLevel m_globalZoom; mutable sv_frame_t m_playbackFrame; - Model *m_playbackModel; //!!! + ModelId m_playbackModel; sv_samplerate_t m_mainModelSampleRate; float m_lastLeft; diff -r de41a11cabc2 -r ac0a8addabcf widgets/AudioDial.cpp --- a/widgets/AudioDial.cpp Thu Jun 13 15:35:01 2019 +0100 +++ b/widgets/AudioDial.cpp Wed Jul 17 14:25:16 2019 +0100 @@ -132,7 +132,7 @@ QColor knobColor(m_knobColor); if (knobColor == Qt::black) { - knobColor = palette().window().color().light(150); + knobColor = palette().window().color().lighter(150); } bool knobIsDark = (knobColor.red() + knobColor.green() + knobColor.blue() <= 384); @@ -183,9 +183,9 @@ int darkWidth = (width-2*indent) * 3 / 4; while (darkWidth) { if (knobIsDark) { - c = c.dark(102); + c = c.darker(102); } else { - c = c.light(102); + c = c.lighter(102); } pen.setColor(c); paint.setPen(pen); @@ -238,9 +238,9 @@ int shadowAngle = -720; if (knobIsDark) { - c = knobColor.light(); + c = knobColor.lighter(); } else { - c = knobColor.dark(); + c = knobColor.darker(); } for (int arc = 120; arc < 2880; arc += 240) { pen.setColor(c); @@ -250,9 +250,9 @@ paint.drawArc(indent, indent, width-2*indent, width-2*indent, shadowAngle - arc, 240); if (knobIsDark) { - c = c.dark(110); + c = c.darker(110); } else { - c = c.light(110); + c = c.lighter(110); } } @@ -266,7 +266,7 @@ int arc = i * 240 + 120; paint.drawArc(scale/2, scale/2, width-scale, width-scale, shadowAngle + arc, 240); - c = c.light(110); + c = c.lighter(110); } c = palette().shadow().color(); for (int i = 0; i < 12; ++i) { @@ -275,7 +275,7 @@ int arc = i * 240 + 120; paint.drawArc(scale/2, scale/2, width-scale, width-scale, shadowAngle - arc, 240); - c = c.light(110); + c = c.lighter(110); } // Scale ends... @@ -310,9 +310,9 @@ c = notchColor; if (isEnabled()) { if (knobIsDark) { - c = c.light(130); + c = c.lighter(130); } else { - c = c.dark(130); + c = c.darker(130); } } pen.setColor(c); diff -r de41a11cabc2 -r ac0a8addabcf widgets/InteractiveFileFinder.cpp --- a/widgets/InteractiveFileFinder.cpp Thu Jun 13 15:35:01 2019 +0100 +++ b/widgets/InteractiveFileFinder.cpp Wed Jul 17 14:25:16 2019 +0100 @@ -388,7 +388,7 @@ dialog.setDirectory(lastPath); dialog.setAcceptMode(QFileDialog::AcceptSave); dialog.setFileMode(QFileDialog::AnyFile); - dialog.setConfirmOverwrite(false); // we'll do that + dialog.setOption(QFileDialog::DontConfirmOverwrite, true); // we'll do that QString defaultSuffix; if (type == SessionFile) { diff -r de41a11cabc2 -r ac0a8addabcf widgets/KeyReference.cpp --- a/widgets/KeyReference.cpp Thu Jun 13 15:35:01 2019 +0100 +++ b/widgets/KeyReference.cpp Wed Jul 17 14:25:16 2019 +0100 @@ -21,7 +21,7 @@ #include #include #include -#include +#include KeyReference::KeyReference() : m_text(nullptr), @@ -185,9 +185,9 @@ layout->addWidget(bb); m_dialog->show(); - - QDesktopWidget *desktop = QApplication::desktop(); - QRect available = desktop->availableGeometry(); + + QScreen *screen = QGuiApplication::primaryScreen(); + QRect available = screen->availableGeometry(); int width = available.width() * 3 / 5; int height = available.height() * 2 / 3; diff -r de41a11cabc2 -r ac0a8addabcf widgets/LEDButton.cpp --- a/widgets/LEDButton.cpp Thu Jun 13 15:35:01 2019 +0100 +++ b/widgets/LEDButton.cpp Wed Jul 17 14:25:16 2019 +0100 @@ -49,7 +49,7 @@ QColor col(Qt::green); d = new LEDButton::LEDButtonPrivate; d->dark_factor = 300; - d->offcolor = col.dark(300); + d->offcolor = col.darker(300); setColor(col); } @@ -61,7 +61,7 @@ { d = new LEDButton::LEDButtonPrivate; d->dark_factor = 300; - d->offcolor = col.dark(300); + d->offcolor = col.darker(300); setColor(col); } @@ -72,7 +72,7 @@ { d = new LEDButton::LEDButtonPrivate; d->dark_factor = 300; - d->offcolor = col.dark(300); + d->offcolor = col.darker(300); setColor(col); } @@ -160,7 +160,7 @@ // Now draw the bright spot on the LED: while (light_width) { - color = color.light( light_quote ); // make color lighter + color = color.lighter( light_quote ); // make color lighter pen.setColor( color ); // set color as pen color paint.setPen( pen ); // select the pen for drawing paint.drawEllipse( pos, pos, light_width, light_width ); // draw the ellipse (circle) @@ -197,7 +197,7 @@ int w = width - pen.width()/2; paint.drawArc(pen.width()/2 + 1, pen.width()/2 + 1, w - 2, w - 2, angle + arc, 240); paint.drawArc(pen.width()/2 + 1, pen.width()/2 + 1, w - 2, w - 2, angle - arc, 240); - color = color.dark(110); //FIXME: this should somehow use the contrast value + color = color.darker(110); //FIXME: this should somehow use the contrast value } // end for ( angle = 720; angle < 6480; angle += 160 ) paint.end(); @@ -238,7 +238,7 @@ { if(led_color!=col) { led_color = col; - d->offcolor = col.dark(d->dark_factor); + d->offcolor = col.darker(d->dark_factor); update(); } } @@ -248,7 +248,7 @@ { if (d->dark_factor != darkfactor) { d->dark_factor = darkfactor; - d->offcolor = led_color.dark(darkfactor); + d->offcolor = led_color.darker(darkfactor); update(); } } diff -r de41a11cabc2 -r ac0a8addabcf widgets/LayerTree.cpp --- a/widgets/LayerTree.cpp Thu Jun 13 15:35:01 2019 +0100 +++ b/widgets/LayerTree.cpp Wed Jul 17 14:25:16 2019 +0100 @@ -77,7 +77,7 @@ void ModelMetadataModel::rebuildModelSet() { - std::set unfound = m_models; + std::set unfound = m_models; for (int i = 0; i < m_stack->getPaneCount(); ++i) { @@ -89,26 +89,23 @@ Layer *layer = pane->getLayer(j); if (!layer) continue; - Model *model = layer->getModel(); - if (!model) continue; + ModelId modelId = layer->getModel(); + if (modelId.isNone()) continue; if (m_waveModelsOnly) { - if (!dynamic_cast(model)) continue; + if (!ModelById::getAs(modelId)) continue; } - if (m_models.find(model) == m_models.end()) { - connect(model, SIGNAL(aboutToBeDeleted()), - this, SLOT(rebuildModelSet())); - m_models.insert(model); + if (m_models.find(modelId) == m_models.end()) { + m_models.insert(modelId); } else { - unfound.erase(model); + unfound.erase(modelId); } } } - for (std::set::iterator i = unfound.begin(); - i != unfound.end(); ++i) { - m_models.erase(*i); + for (ModelId m: unfound) { + m_models.erase(m); } SVDEBUG << "ModelMetadataModel::rebuildModelSet: " << m_models.size() << " models" << endl; @@ -173,11 +170,12 @@ int row = index.row(), col = index.column(); //!!! not exactly the ideal use of a std::set - std::set::iterator itr = m_models.begin(); + std::set::iterator itr = m_models.begin(); for (int i = 0; i < row && itr != m_models.end(); ++i, ++itr); if (itr == m_models.end()) return QVariant(); - Model *model = *itr; + auto model = ModelById::get(*itr); + if (!model) return QVariant(); if (role != Qt::DisplayRole) { if (m_waveModelsOnly && col == m_modelNameColumn && @@ -298,9 +296,9 @@ for (int j = 0; j < pane->getLayerCount(); ++j) { Layer *layer = pane->getLayer(j); if (!layer) continue; - PlayParameters *params = layer->getPlayParameters(); + auto params = layer->getPlayParameters(); if (!params) continue; - connect(params, SIGNAL(playAudibleChanged(bool)), + connect(params.get(), SIGNAL(playAudibleChanged(bool)), this, SLOT(playParametersAudibilityChanged(bool))); } } @@ -380,7 +378,7 @@ for (int j = 0; j < pane->getLayerCount(); ++j) { Layer *layer = pane->getLayer(j); if (!layer) continue; - if (layer->getPlayParameters() == params) { + if (layer->getPlayParameters().get() == params) { // ugh SVDEBUG << "LayerTreeModel::playParametersAudibilityChanged(" << params << "," << a << "): row " << pane->getLayerCount() - j - 1 << ", col " << 2 << endl; @@ -436,7 +434,7 @@ } } else if (col == m_layerPlayedColumn) { if (role == Qt::CheckStateRole) { - PlayParameters *params = layer->getPlayParameters(); + auto params = layer->getPlayParameters(); if (params) return QVariant(params->isPlayMuted() ? Qt::Unchecked : Qt::Checked); else return QVariant(); @@ -444,7 +442,7 @@ return QVariant(Qt::AlignHCenter); } } else if (col == m_modelNameColumn) { - Model *model = layer->getModel(); + auto model = ModelById::get(layer->getModel()); if (model && role == Qt::DisplayRole) { return QVariant(model->objectName()); } @@ -477,7 +475,7 @@ } } else if (col == m_layerPlayedColumn) { if (role == Qt::CheckStateRole) { - PlayParameters *params = layer->getPlayParameters(); + auto params = layer->getPlayParameters(); if (params) { params->setPlayMuted(value.toInt() == Qt::Unchecked); emit dataChanged(index, index); diff -r de41a11cabc2 -r ac0a8addabcf widgets/LayerTree.h --- a/widgets/LayerTree.h Thu Jun 13 15:35:01 2019 +0100 +++ b/widgets/LayerTree.h Wed Jul 17 14:25:16 2019 +0100 @@ -19,6 +19,8 @@ #include +#include "data/model/Model.h" + #include class PaneStack; @@ -26,7 +28,6 @@ class Pane; class Layer; class PropertyContainer; -class Model; class ModelMetadataModel : public QAbstractItemModel { @@ -73,7 +74,7 @@ int m_modelSourceColumn; int m_columnCount; - std::set m_models; + std::set m_models; }; class LayerTreeModel : public QAbstractItemModel diff -r de41a11cabc2 -r ac0a8addabcf widgets/LayerTreeDialog.cpp --- a/widgets/LayerTreeDialog.cpp Thu Jun 13 15:35:01 2019 +0100 +++ b/widgets/LayerTreeDialog.cpp Wed Jul 17 14:25:16 2019 +0100 @@ -25,7 +25,7 @@ #include #include #include -#include +#include LayerTreeDialog::LayerTreeDialog(PaneStack *stack, QWidget *parent) : QDialog(parent), @@ -89,8 +89,8 @@ grid->addWidget(bb, 2, 0); grid->setRowStretch(2, 0); - QDesktopWidget *desktop = QApplication::desktop(); - QRect available = desktop->availableGeometry(); + QScreen *screen = QGuiApplication::primaryScreen(); + QRect available = screen->availableGeometry(); int width = available.width() / 2; int height = available.height() / 3; diff -r de41a11cabc2 -r ac0a8addabcf widgets/ModelDataTableDialog.cpp --- a/widgets/ModelDataTableDialog.cpp Thu Jun 13 15:35:01 2019 +0100 +++ b/widgets/ModelDataTableDialog.cpp Wed Jul 17 14:25:16 2019 +0100 @@ -30,13 +30,13 @@ #include #include #include -#include +#include #include #include #include -ModelDataTableDialog::ModelDataTableDialog(TabularModel *model, +ModelDataTableDialog::ModelDataTableDialog(ModelId tabularModelId, QString title, QWidget *parent) : QMainWindow(parent), m_currentRow(0), @@ -119,7 +119,7 @@ m_tableView->setSortingEnabled(true); m_tableView->sortByColumn(0, Qt::AscendingOrder); - m_table = new ModelDataTableModel(model); + m_table = new ModelDataTableModel(tabularModelId); m_tableView->setModel(m_table); m_tableView->horizontalHeader()->setStretchLastSection(true); @@ -144,8 +144,8 @@ grid->addWidget(bb, 2, 0); grid->setRowStretch(2, 0); - QDesktopWidget *desktop = QApplication::desktop(); - QRect available = desktop->availableGeometry(); + QScreen *screen = QGuiApplication::primaryScreen(); + QRect available = screen->availableGeometry(); int width = available.width() / 3; int height = available.height() / 2; diff -r de41a11cabc2 -r ac0a8addabcf widgets/ModelDataTableDialog.h --- a/widgets/ModelDataTableDialog.h Thu Jun 13 15:35:01 2019 +0100 +++ b/widgets/ModelDataTableDialog.h Wed Jul 17 14:25:16 2019 +0100 @@ -20,7 +20,8 @@ #include "base/BaseTypes.h" -class TabularModel; +#include "data/model/Model.h" + class ModelDataTableModel; class QTableView; class QModelIndex; @@ -33,7 +34,7 @@ Q_OBJECT public: - ModelDataTableDialog(TabularModel *model, + ModelDataTableDialog(ModelId tabularModelId, QString title, QWidget *parent =0); ~ModelDataTableDialog(); diff -r de41a11cabc2 -r ac0a8addabcf widgets/Panner.cpp --- a/widgets/Panner.cpp Thu Jun 13 15:35:01 2019 +0100 +++ b/widgets/Panner.cpp Wed Jul 17 14:25:16 2019 +0100 @@ -162,7 +162,7 @@ QPainter paint(this); paint.setRenderHint(QPainter::Antialiasing, false); - QColor bg(palette().background().color()); + QColor bg(palette().window().color()); bg.setAlpha(m_backgroundAlpha); int penWidth = WidgetScale::scalePixelSize(1); diff -r de41a11cabc2 -r ac0a8addabcf widgets/PluginReviewDialog.cpp --- a/widgets/PluginReviewDialog.cpp Thu Jun 13 15:35:01 2019 +0100 +++ b/widgets/PluginReviewDialog.cpp Wed Jul 17 14:25:16 2019 +0100 @@ -19,7 +19,7 @@ #include #include #include -#include +#include #include #include "plugin/FeatureExtractionPluginFactory.h" @@ -129,8 +129,8 @@ int twidth = m_table->horizontalHeader()->length(); int theight = m_table->verticalHeader()->length(); - QDesktopWidget *desktop = QApplication::desktop(); - QRect available = desktop->availableGeometry(); + QScreen *screen = QGuiApplication::primaryScreen(); + QRect available = screen->availableGeometry(); int width = std::min(twidth + 30, (available.width() * 3) / 4); int height = std::min(theight + 30, (available.height() * 3) / 4); diff -r de41a11cabc2 -r ac0a8addabcf widgets/PropertyBox.cpp --- a/widgets/PropertyBox.cpp Thu Jun 13 15:35:01 2019 +0100 +++ b/widgets/PropertyBox.cpp Wed Jul 17 14:25:16 2019 +0100 @@ -142,7 +142,7 @@ this, SLOT(populateViewPlayFrame())); } - PlayParameters *params = m_container->getPlayParameters(); + auto params = m_container->getPlayParameters(); if (!params && !layer) return; m_viewPlayFrame = new QFrame; @@ -175,7 +175,7 @@ this, SLOT(mouseEnteredWidget())); connect(m_playButton, SIGNAL(mouseLeft()), this, SLOT(mouseLeftWidget())); - connect(params, SIGNAL(playAudibleChanged(bool)), + connect(params.get(), SIGNAL(playAudibleChanged(bool)), this, SLOT(playAudibleChanged(bool))); LevelPanToolButton *levelPan = new LevelPanToolButton; @@ -186,9 +186,9 @@ this, SLOT(playGainControlChanged(float))); connect(levelPan, SIGNAL(panChanged(float)), this, SLOT(playPanControlChanged(float))); - connect(params, SIGNAL(playGainChanged(float)), + connect(params.get(), SIGNAL(playGainChanged(float)), levelPan, SLOT(setLevel(float))); - connect(params, SIGNAL(playPanChanged(float)), + connect(params.get(), SIGNAL(playPanChanged(float)), levelPan, SLOT(setPan(float))); connect(levelPan, SIGNAL(mouseEntered()), this, SLOT(mouseEnteredWidget())); @@ -674,7 +674,7 @@ void PropertyBox::playAudibleButtonChanged(bool audible) { - PlayParameters *params = m_container->getPlayParameters(); + auto params = m_container->getPlayParameters(); if (!params) return; if (params->isPlayAudible() != audible) { @@ -690,7 +690,7 @@ { QObject *obj = sender(); - PlayParameters *params = m_container->getPlayParameters(); + auto params = m_container->getPlayParameters(); if (!params) return; if (params->getPlayGain() != gain) { @@ -708,7 +708,7 @@ { QObject *obj = sender(); - PlayParameters *params = m_container->getPlayParameters(); + auto params = m_container->getPlayParameters(); if (!params) return; if (params->getPlayPan() != pan) { @@ -724,7 +724,7 @@ void PropertyBox::editPlayParameters() { - PlayParameters *params = m_container->getPlayParameters(); + auto params = m_container->getPlayParameters(); if (!params) return; QString clip = params->getPlayClipId(); @@ -774,7 +774,7 @@ void PropertyBox::playClipChanged(QString id) { - PlayParameters *params = m_container->getPlayParameters(); + auto params = m_container->getPlayParameters(); if (!params) return; params->setPlayClipId(id); @@ -823,7 +823,7 @@ } else if (wname == "playParamButton") { - PlayParameters *params = m_container->getPlayParameters(); + auto params = m_container->getPlayParameters(); if (params) { help = tr("Change sound used for playback (currently \"%1\")") .arg(params->getPlayClipId()); diff -r de41a11cabc2 -r ac0a8addabcf widgets/TextAbbrev.cpp --- a/widgets/TextAbbrev.cpp Thu Jun 13 15:35:01 2019 +0100 +++ b/widgets/TextAbbrev.cpp Wed Jul 17 14:25:16 2019 +0100 @@ -38,6 +38,11 @@ int TextAbbrev::getFuzzWidth(const QFontMetrics &metrics, QString ellipsis) { + // 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" + int width = metrics.width(ellipsis); return width * 2; } diff -r de41a11cabc2 -r ac0a8addabcf widgets/Thumbwheel.cpp --- a/widgets/Thumbwheel.cpp Thu Jun 13 15:35:01 2019 +0100 +++ b/widgets/Thumbwheel.cpp Wed Jul 17 14:25:16 2019 +0100 @@ -466,7 +466,7 @@ QPainter paint(&m_cache); paint.setClipRect(m_cache.rect()); - paint.fillRect(subclip, palette().background().color()); + paint.fillRect(subclip, palette().window().color()); paint.setRenderHint(QPainter::Antialiasing, true); @@ -564,7 +564,7 @@ } paint.setPen(fc); - paint.setBrush(palette().background().color()); + paint.setBrush(palette().window().color()); if (m_orientation == Qt::Horizontal) { paint.drawRect(QRectF(x0, bw, x1 - x0, h - bw*2)); diff -r de41a11cabc2 -r ac0a8addabcf widgets/TransformFinder.cpp --- a/widgets/TransformFinder.cpp Thu Jun 13 15:35:01 2019 +0100 +++ b/widgets/TransformFinder.cpp Wed Jul 17 14:25:16 2019 +0100 @@ -26,7 +26,7 @@ #include #include #include -#include +#include #include #include @@ -92,8 +92,8 @@ connect(down, SIGNAL(triggered()), this, SLOT(down())); addAction(down); - QDesktopWidget *desktop = QApplication::desktop(); - QRect available = desktop->availableGeometry(); + QScreen *screen = QApplication::primaryScreen(); + QRect available = screen->availableGeometry(); int width = available.width() / 2; int height = available.height() / 2; diff -r de41a11cabc2 -r ac0a8addabcf widgets/WindowShapePreview.cpp --- a/widgets/WindowShapePreview.cpp Thu Jun 13 15:35:01 2019 +0100 +++ b/widgets/WindowShapePreview.cpp Wed Jul 17 14:25:16 2019 +0100 @@ -113,6 +113,11 @@ path.addRect(0, 0, w, h + 1); timePainter.drawPath(path); + // 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" + QFont font; font.setPixelSize(int(10 * scaleRatio)); font.setItalic(true);