changeset 1470:696e569ff21b by-id

Further layer updates for ById
author Chris Cannam
date Fri, 28 Jun 2019 17:37:22 +0100
parents 11a150e65ee1
children f2525e6cbdf1
files layer/FlexiNoteLayer.cpp layer/FlexiNoteLayer.h layer/ImageLayer.cpp layer/ImageLayer.h layer/Layer.cpp layer/NoteLayer.cpp layer/NoteLayer.h layer/RegionLayer.cpp layer/RegionLayer.h layer/SliceLayer.h layer/SpectrogramLayer.h layer/SpectrumLayer.h layer/TextLayer.cpp layer/TextLayer.h layer/TimeInstantLayer.cpp layer/TimeInstantLayer.h layer/TimeRulerLayer.h layer/TimeValueLayer.cpp layer/TimeValueLayer.h layer/WaveformLayer.cpp layer/WaveformLayer.h
diffstat 21 files changed, 185 insertions(+), 118 deletions(-) [+]
line wrap: on
line diff
--- a/layer/FlexiNoteLayer.cpp	Thu Jun 27 13:16:25 2019 +0100
+++ b/layer/FlexiNoteLayer.cpp	Fri Jun 28 17:37:22 2019 +0100
@@ -961,7 +961,7 @@
     m_originalPoint = m_editingPoint;
 
     if (m_editingCommand) finish(m_editingCommand);
-    m_editingCommand = new ChangeEventsCommand<Model>(m_model, tr("Draw Point"));
+    m_editingCommand = new ChangeEventsCommand(m_model.untyped, tr("Draw Point"));
     m_editingCommand->add(m_editingPoint);
 
     m_editing = true;
@@ -1041,7 +1041,7 @@
     if (p.getFrame() != m_editingPoint.getFrame() ||
         p.getValue() != m_editingPoint.getValue()) return;
 
-    m_editingCommand = new ChangeEventsCommand<Model>(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;
@@ -1128,7 +1128,7 @@
 
     if (!m_editingCommand) {
         m_editingCommand =
-            new ChangeEventsCommand<Model>(m_model, tr("Drag Point"));
+            new ChangeEventsCommand(m_model.untyped, tr("Drag Point"));
     }
     m_editingCommand->remove(m_editingPoint);
 
@@ -1310,7 +1310,7 @@
     
     Event note(*onPoints.begin());
 
-    auto command = new ChangeEventsCommand<Model>(m_model, tr("Edit Point"));
+    auto command = new ChangeEventsCommand(m_model.untyped, tr("Edit Point"));
     command->remove(note);
 
     if (!e || !(e->modifiers() & Qt::ShiftModifier)) {
@@ -1374,7 +1374,7 @@
     if (!m_intelligentActions || 
         (model->getEventsCovering(frame).empty() && duration > 0)) {
         Event newNote(frame, float(value), duration, 100.f, tr("new note"));
-        auto command = new ChangeEventsCommand<Model>(m_model, tr("Add Point"));
+        auto command = new ChangeEventsCommand(m_model.untyped, tr("Add Point"));
         command->add(newNote);
         finish(command);
     }
@@ -1413,7 +1413,7 @@
     EventVector points =
         model->getEventsStartingWithin(s.getStartFrame(), s.getDuration());
 
-    auto command = new ChangeEventsCommand<Model>(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;
 
@@ -1458,7 +1458,7 @@
     EventVector::iterator i = points.begin();
     if (i == points.end()) return;
 
-    auto command = new ChangeEventsCommand<Model>(m_model, tr("Merge Notes"));
+    auto command = new ChangeEventsCommand(m_model.untyped, tr("Merge Notes"));
 
     Event newNote(*i);
 
@@ -1623,7 +1623,7 @@
             .withDuration(dialog->getFrameDuration())
             .withLabel(dialog->getText());
         
-        auto command = new ChangeEventsCommand<Model>(m_model, tr("Edit Point"));
+        auto command = new ChangeEventsCommand(m_model.untyped, tr("Edit Point"));
         command->remove(note);
         command->add(newNote);
         finish(command);
@@ -1639,7 +1639,7 @@
     auto model = ModelById::getAs<NoteModel>(m_model);
     if (!model) return;
     
-    auto command = new ChangeEventsCommand<Model>(m_model, tr("Drag Selection"));
+    auto command = new ChangeEventsCommand(m_model.untyped, tr("Drag Selection"));
 
     EventVector points =
         model->getEventsStartingWithin(s.getStartFrame(), s.getDuration());
@@ -1660,7 +1660,7 @@
     auto model = ModelById::getAs<NoteModel>(m_model);
     if (!model || !s.getDuration()) return;
 
-    auto command = new ChangeEventsCommand<Model>(m_model, tr("Resize Selection"));
+    auto command = new ChangeEventsCommand(m_model.untyped, tr("Resize Selection"));
 
     EventVector points =
         model->getEventsStartingWithin(s.getStartFrame(), s.getDuration());
@@ -1691,7 +1691,7 @@
     if (!model) return;
 
     auto command =
-        new ChangeEventsCommand<Model>(m_model, tr("Delete Selected Points"));
+        new ChangeEventsCommand(m_model.untyped, tr("Delete Selected Points"));
 
     EventVector points =
         model->getEventsStartingWithin(s.getStartFrame(), s.getDuration());
@@ -1710,7 +1710,7 @@
     if (!model) return;
 
     auto command =
-        new ChangeEventsCommand<Model>(m_model, tr("Delete Selected Points"));
+        new ChangeEventsCommand(m_model.untyped, tr("Delete Selected Points"));
 
     EventVector points =
         model->getEventsSpanning(s.getStartFrame(), s.getDuration());
@@ -1763,7 +1763,7 @@
         }
     }
 
-    auto command = new ChangeEventsCommand<Model>(m_model, tr("Paste"));
+    auto command = new ChangeEventsCommand(m_model.untyped, tr("Paste"));
 
     for (EventVector::const_iterator i = points.begin();
          i != points.end(); ++i) {
@@ -1831,8 +1831,8 @@
         if (lrintf(p.getValue()) == pitch) {
             m_pendingNoteOns.erase(i);
             Event note = p.withDuration(frame - p.getFrame());
-            auto c = new ChangeEventsCommand<Model>
-                (m_model, tr("Record Note"));
+            auto c = new ChangeEventsCommand
+                (m_model.untyped, tr("Record Note"));
             c->add(note);
             // execute and bundle:
             CommandHistory::getInstance()->addCommand(c, true, true);
--- a/layer/FlexiNoteLayer.h	Thu Jun 27 13:16:25 2019 +0100
+++ b/layer/FlexiNoteLayer.h	Fri Jun 28 17:37:22 2019 +0100
@@ -191,7 +191,7 @@
     Event m_editingPoint;
     sv_frame_t m_greatestLeftNeighbourFrame;
     sv_frame_t m_smallestRightNeighbourFrame;
-    ChangeEventsCommand<Model> *m_editingCommand;
+    ChangeEventsCommand *m_editingCommand;
     VerticalScale m_verticalScale;
     EditMode m_editMode;
 
@@ -203,7 +203,7 @@
 
     bool shouldAutoAlign() const;
 
-    void finish(ChangeEventsCommand<Model> *command) {
+    void finish(ChangeEventsCommand *command) {
         Command *c = command->finish();
         if (c) CommandHistory::getInstance()->addCommand(c, false);
     }
--- a/layer/ImageLayer.cpp	Thu Jun 27 13:16:25 2019 +0100
+++ b/layer/ImageLayer.cpp	Fri Jun 28 17:37:22 2019 +0100
@@ -541,7 +541,7 @@
     m_originalPoint = m_editingPoint;
 
     if (m_editingCommand) finish(m_editingCommand);
-    m_editingCommand = new ChangeEventsCommand<Model>(m_model, "Add Image");
+    m_editingCommand = new ChangeEventsCommand(m_model.untyped, "Add Image");
     m_editingCommand->add(m_editingPoint);
 
     m_editing = true;
@@ -604,7 +604,7 @@
 
     Event point = Event(frame).withURI(url);
     auto command =
-        new ChangeEventsCommand<Model>(m_model, "Add Image");
+        new ChangeEventsCommand(m_model.untyped, "Add Image");
     command->add(point);
     finish(command);
     return true;
@@ -646,7 +646,7 @@
     frame = (frame / model->getResolution()) * model->getResolution();
 
     if (!m_editingCommand) {
-        m_editingCommand = new ChangeEventsCommand<Model>(m_model, tr("Move Image"));
+        m_editingCommand = new ChangeEventsCommand(m_model.untyped, tr("Move Image"));
     }
 
     m_editingCommand->remove(m_editingPoint);
@@ -691,7 +691,7 @@
         checkAddSource(dialog.getImage());
 
         auto command =
-            new ChangeEventsCommand<Model>(m_model, tr("Edit Image"));
+            new ChangeEventsCommand(m_model.untyped, tr("Edit Image"));
         command->remove(*points.begin());
         command->add(points.begin()->
                      withURI(dialog.getImage()).withLabel(dialog.getLabel()));
@@ -708,7 +708,7 @@
     if (!model) return;
 
     auto command =
-        new ChangeEventsCommand<Model>(m_model, tr("Drag Selection"));
+        new ChangeEventsCommand(m_model.untyped, tr("Drag Selection"));
 
     EventVector points =
         model->getEventsStartingWithin(s.getStartFrame(), s.getDuration());
@@ -730,7 +730,7 @@
     if (!model) return;
 
     auto command =
-        new ChangeEventsCommand<Model>(m_model, tr("Resize Selection"));
+        new ChangeEventsCommand(m_model.untyped, tr("Resize Selection"));
 
     EventVector points =
         model->getEventsStartingWithin(s.getStartFrame(), s.getDuration());
@@ -759,7 +759,7 @@
     if (!model) return;
 
     auto command =
-        new ChangeEventsCommand<Model>(m_model, tr("Delete Selection"));
+        new ChangeEventsCommand(m_model.untyped, tr("Delete Selection"));
 
     EventVector points =
         model->getEventsStartingWithin(s.getStartFrame(), s.getDuration());
@@ -812,7 +812,7 @@
         }
     }
 
-    auto command = new ChangeEventsCommand<Model>(m_model, tr("Paste"));
+    auto command = new ChangeEventsCommand(m_model.untyped, tr("Paste"));
 
     for (EventVector::const_iterator i = points.begin();
          i != points.end(); ++i) {
--- a/layer/ImageLayer.h	Thu Jun 27 13:16:25 2019 +0100
+++ b/layer/ImageLayer.h	Fri Jun 28 17:37:22 2019 +0100
@@ -132,9 +132,9 @@
     QPoint m_editOrigin;
     Event m_originalPoint;
     Event m_editingPoint;
-    ChangeEventsCommand<Model> *m_editingCommand;
+    ChangeEventsCommand *m_editingCommand;
 
-    void finish(ChangeEventsCommand<Model> *command) {
+    void finish(ChangeEventsCommand *command) {
         Command *c = command->finish();
         if (c) CommandHistory::getInstance()->addCommand(c, false);
     }
--- a/layer/Layer.cpp	Thu Jun 27 13:16:25 2019 +0100
+++ b/layer/Layer.cpp	Fri Jun 28 17:37:22 2019 +0100
@@ -111,10 +111,8 @@
 Layer::getPlayParameters() 
 {
 //    cerr << "Layer (" << this << ", " << objectName() << ")::getPlayParameters: model is "<< getModel() << endl;
-    auto model = ModelById::get(getModel());
-    if (model) {
-        return PlayParameterRepository::getInstance()->getPlayParameters(model);
-    }
+    return PlayParameterRepository::getInstance()->getPlayParameters
+        (getModel().untyped);
     return nullptr;
 }
 
--- a/layer/NoteLayer.cpp	Thu Jun 27 13:16:25 2019 +0100
+++ b/layer/NoteLayer.cpp	Fri Jun 28 17:37:22 2019 +0100
@@ -65,8 +65,16 @@
     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)
+NoteLayer::setModel(ModelId model)
 {        
     if (m_model == model) return;
     m_model = model;
--- a/layer/NoteLayer.h	Thu Jun 27 13:16:25 2019 +0100
+++ b/layer/NoteLayer.h	Fri Jun 28 17:37:22 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;
--- a/layer/RegionLayer.cpp	Thu Jun 27 13:16:25 2019 +0100
+++ b/layer/RegionLayer.cpp	Fri Jun 28 17:37:22 2019 +0100
@@ -63,6 +63,14 @@
     
 }
 
+int
+RegionLayer::getCompletion(LayerGeometryProvider *) const
+{
+    auto model = ModelById::get(m_model);
+    if (model) return model->getCompletion();
+    else return 0;
+}
+
 void
 RegionLayer::setModel(RegionModel *model)
 {
--- a/layer/RegionLayer.h	Thu Jun 27 13:16:25 2019 +0100
+++ b/layer/RegionLayer.h	Fri Jun 28 17:37:22 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;
--- a/layer/SliceLayer.h	Thu Jun 27 13:16:25 2019 +0100
+++ b/layer/SliceLayer.h	Fri Jun 28 17:37:22 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<int>          m_scalePoints;
-    mutable int                       m_scalePaintHeight;
-    mutable std::map<int, int>        m_xorigins; // LayerGeometryProvider id -> x
-    mutable std::map<int, int>        m_yorigins; // LayerGeometryProvider id -> y
-    mutable std::map<int, int>        m_heights;  // LayerGeometryProvider id -> h
-    mutable sv_frame_t                m_currentf0;
-    mutable sv_frame_t                m_currentf1;
-    mutable std::vector<float>        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<int>    m_scalePoints;
+    mutable int                 m_scalePaintHeight;
+    mutable std::map<int, int>  m_xorigins; // LayerGeometryProvider id -> x
+    mutable std::map<int, int>  m_yorigins; // LayerGeometryProvider id -> y
+    mutable std::map<int, int>  m_heights;  // LayerGeometryProvider id -> h
+    mutable sv_frame_t          m_currentf0;
+    mutable sv_frame_t          m_currentf1;
+    mutable std::vector<float>  m_values;
 };
 
 #endif
--- a/layer/SpectrogramLayer.h	Thu Jun 27 13:16:25 2019 +0100
+++ b/layer/SpectrogramLayer.h	Fri Jun 28 17:37:22 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,7 +234,7 @@
     void setVerticalZoomStep(int) override;
     RangeMapper *getNewVerticalZoomRangeMapper() const override;
 
-    const Model *getSliceableModel() const override;
+    ModelId getSliceableModel() const override;
 
 protected slots:
     void cacheInvalid();
@@ -243,7 +243,7 @@
     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,8 +306,7 @@
 
     int getFFTSize() const; // m_windowSize * getOversampling()
 
-    FFTModel *m_fftModel;
-    FFTModel *getFFTModel() const { return m_fftModel; }
+    ModelId m_fftModel;
     Dense3DModelPeakCache *m_wholeCache;
     Dense3DModelPeakCache *m_peakCache;
     Dense3DModelPeakCache *getPeakCache() const { return m_peakCache; }
--- a/layer/SpectrumLayer.h	Thu Jun 27 13:16:25 2019 +0100
+++ b/layer/SpectrumLayer.h	Fri Jun 28 17:37:22 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<QRect> &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;
--- a/layer/TextLayer.cpp	Thu Jun 27 13:16:25 2019 +0100
+++ b/layer/TextLayer.cpp	Fri Jun 28 17:37:22 2019 +0100
@@ -43,8 +43,16 @@
     
 }
 
+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 model)
 {
     if (m_model == model) return;
     m_model = model;
--- a/layer/TextLayer.h	Thu Jun 27 13:16:25 2019 +0100
+++ b/layer/TextLayer.h	Fri Jun 28 17:37:22 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;
--- a/layer/TimeInstantLayer.cpp	Thu Jun 27 13:16:25 2019 +0100
+++ b/layer/TimeInstantLayer.cpp	Fri Jun 28 17:37:22 2019 +0100
@@ -53,19 +53,29 @@
 {
 }
 
+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;
+    if (m_model == modelId) return;
+    m_model = modelId;
 
+    auto newModel = ModelById::getAs<SparseOneDimensionalModel>(modelId);
+    
     connectSignals(m_model);
 
 #ifdef DEBUG_TIME_INSTANT_LAYER
-    cerr << "TimeInstantLayer::setModel(" << model << ")" << endl;
+    cerr << "TimeInstantLayer::setModel(" << modelId << ")" << endl;
 #endif
 
-    if (m_model && m_model->getRDFTypeURI().endsWith("Segment")) {
+    if (newModel && newModel->getRDFTypeURI().endsWith("Segment")) {
         setPlotStyle(PlotSegmentation);
     }
 
@@ -149,6 +159,14 @@
 }
 
 bool
+TimeInstantLayer::needsTextLabelHeight() const
+{
+    auto model = ModelById::getAs<SparseOneDimensionalModel>(m_model);
+    if (model) return m_model->hasTextLabels();
+    else return false;
+}
+
+bool
 TimeInstantLayer::isLayerScrollable(const LayerGeometryProvider *v) const
 {
     QPoint discard;
--- a/layer/TimeInstantLayer.h	Thu Jun 27 13:16:25 2019 +0100
+++ b/layer/TimeInstantLayer.h	Fri Jun 28 17:37:22 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;
--- a/layer/TimeRulerLayer.h	Thu Jun 27 13:16:25 2019 +0100
+++ b/layer/TimeRulerLayer.h	Fri Jun 28 17:37:22 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;
--- a/layer/TimeValueLayer.cpp	Thu Jun 27 13:16:25 2019 +0100
+++ b/layer/TimeValueLayer.cpp	Fri Jun 28 17:37:22 2019 +0100
@@ -71,21 +71,31 @@
     
 }
 
+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;
+    if (m_model == modelId) return;
+    m_model = modelId;
+
+    auto newModel = ModelById::getAs<SparseOneDimensionalModel>(modelId);
 
     connectSignals(m_model);
 
     m_scaleMinimum = 0;
     m_scaleMaximum = 0;
 
-    if (m_model && m_model->getRDFTypeURI().endsWith("Segment")) {
+    if (newModel && newModel->getRDFTypeURI().endsWith("Segment")) {
         setPlotStyle(PlotSegmentation);
     }
-    if (m_model && m_model->getRDFTypeURI().endsWith("Change")) {
+    if (newModel && m_model->getRDFTypeURI().endsWith("Change")) {
         setPlotStyle(PlotSegmentation);
     }
 
@@ -152,6 +162,14 @@
     return SingleColourLayer::getPropertyGroupName(name);
 }
 
+bool
+TimeValueLayer::needsTextLabelHeight() const
+{
+    auto model = ModelById::get(m_model);
+    if (!model) return false;
+    return m_plotStyle == PlotSegmentation && model->hasTextLabels();
+}
+
 QString
 TimeValueLayer::getScaleUnits() const
 {
--- a/layer/TimeValueLayer.h	Thu Jun 27 13:16:25 2019 +0100
+++ b/layer/TimeValueLayer.h	Fri Jun 28 17:37:22 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;
--- a/layer/WaveformLayer.cpp	Thu Jun 27 13:16:25 2019 +0100
+++ b/layer/WaveformLayer.cpp	Fri Jun 28 17:37:22 2019 +0100
@@ -60,26 +60,41 @@
     delete m_cache;
 }
 
+const ZoomConstraint *
+WaveformLayer::getZoomConstraint() const
+{
+    auto model = ModelById::get(m_model);
+    if (model) return m_model->getZoomConstraint();
+    else return nullptr;
+}
+
 void
-WaveformLayer::setModel(const RangeSummarisableTimeValueModel *model)
+WaveformLayer::setModel(ModelId modelId)
 {
+    auto oldModel = ModelById::getAs<RangeSummarisableTimeValueModel>(m_model);
+    auto newModel = ModelById::getAs<RangeSummarisableTimeValueModel>(modelId);
+
+    if (!newModel) {
+        SVCERR << "WARNING: WaveformLayer::setModel: Model is not a RangeSummarisableTimeValueModel" << endl;
+    }
+    
     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_model = modelId;
     m_cacheValid = false;
-    if (!m_model || !m_model->isOK()) return;
+    if (!newModel || !newModel->isOK()) return;
 
     connectSignals(m_model);
 
--- a/layer/WaveformLayer.h	Thu Jun 27 13:16:25 2019 +0100
+++ b/layer/WaveformLayer.h	Fri Jun 28 17:37:22 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<RangeSummarisableTimeValueModel::RangeBlock> RangeVec;