changeset 319:3ff8f571da09

* Hoist alignment model set/query up to Model, so any models can be aligned * Add Model::aboutToDelete and aboutToBeDeleted for management of models that are contained by or referred to by other models instead of only the document
author Chris Cannam
date Wed, 24 Oct 2007 15:21:38 +0000
parents 7a4bd2c8585c
children 32e50b620a6c
files data/model/Model.cpp data/model/Model.h data/model/RangeSummarisableTimeValueModel.cpp data/model/RangeSummarisableTimeValueModel.h
diffstat 4 files changed, 153 insertions(+), 65 deletions(-) [+]
line wrap: on
line diff
--- a/data/model/Model.cpp	Mon Oct 22 09:45:35 2007 +0000
+++ b/data/model/Model.cpp	Wed Oct 24 15:21:38 2007 +0000
@@ -14,6 +14,7 @@
 */
 
 #include "Model.h"
+#include "AlignmentModel.h"
 #include "base/PlayParameterRepository.h"
 
 #include <QTextStream>
@@ -26,6 +27,17 @@
 {
 //    std::cerr << "Model::~Model(" << this << ")" << std::endl;
 
+    if (!m_aboutToDelete) {
+        std::cerr << "NOTE: Model::~Model(" << this << ", \""
+                  << objectName().toStdString() << "\"): Model deleted "
+                  << "with no aboutToDelete notification" << std::endl;
+    }
+
+    if (m_alignment) {
+        m_alignment->aboutToDelete();
+        delete m_alignment;
+    }
+
     // Subclasses have to handle adding themselves to the repository,
     // if they want to be played.  We can't do it from here because
     // the repository would be unable to tell whether we were playable
@@ -34,6 +46,86 @@
 }
 
 void
+Model::setSourceModel(Model *model)
+{
+    if (m_sourceModel) {
+        disconnect(m_sourceModel, SIGNAL(aboutToBeDeleted()),
+                   this, SLOT(sourceModelAboutToBeDeleted()));
+    }
+
+    m_sourceModel = model;
+
+    if (m_sourceModel) {
+        connect(m_sourceModel, SIGNAL(aboutToBeDeleted()),
+                this, SLOT(sourceModelAboutToBeDeleted()));
+    }
+}
+
+void
+Model::aboutToDelete()
+{
+    if (m_aboutToDelete) {
+        std::cerr << "WARNING: Model(" << this << ", \""
+                  << objectName().toStdString() << "\")::aboutToDelete: "
+                  << "aboutToDelete called more than once for the same model"
+                  << std::endl;
+    }
+
+    emit aboutToBeDeleted();
+    m_aboutToDelete = true;
+}
+
+void
+Model::sourceModelAboutToBeDeleted()
+{
+    m_sourceModel = 0;
+}
+
+void
+Model::setAlignment(AlignmentModel *alignment)
+{
+    if (m_alignment) {
+        m_alignment->aboutToDelete();
+        delete m_alignment;
+    }
+    m_alignment = alignment;
+    connect(m_alignment, SIGNAL(completionChanged()),
+            this, SIGNAL(alignmentCompletionChanged()));
+}
+
+const Model *
+Model::getAlignmentReference() const
+{
+    if (!m_alignment) return 0;
+    return m_alignment->getReferenceModel();
+}
+
+size_t
+Model::alignToReference(size_t frame) const
+{
+    if (!m_alignment) return frame;
+    return m_alignment->toReference(frame);
+}
+
+size_t
+Model::alignFromReference(size_t refFrame) const
+{
+    if (!m_alignment) return refFrame;
+    return m_alignment->fromReference(refFrame);
+}
+
+int
+Model::getAlignmentCompletion() const
+{
+    std::cerr << "Model::getAlignmentCompletion" << std::endl;
+    if (!m_alignment) return 100;
+    int completion = 0;
+    (void)m_alignment->isReady(&completion);
+    std::cerr << " -> " << completion << std::endl;
+    return completion;
+}
+
+void
 Model::toXml(QTextStream &stream, QString indent,
              QString extraAttributes) const
 {
--- a/data/model/Model.h	Mon Oct 22 09:45:35 2007 +0000
+++ b/data/model/Model.h	Wed Oct 24 15:21:38 2007 +0000
@@ -24,6 +24,7 @@
 typedef std::vector<float> SampleBlock;
 
 class ZoomConstraint;
+class AlignmentModel;
 
 /** 
  * Model is the base class for all data models that represent any sort
@@ -114,7 +115,8 @@
      * If this model was derived from another, return the model it was
      * derived from.  The assumption is that the source model's
      * alignment will also apply to this model, unless some other
-     * property indicates otherwise.
+     * property (such as a specific alignment model set on this model)
+     * indicates otherwise.
      */
     virtual Model *getSourceModel() const {
         return m_sourceModel;
@@ -123,10 +125,40 @@
     /**
      * Set the source model for this model.
      */
-     //!!! No way to handle source model deletion &c yet
-    virtual void setSourceModel(Model *model) {
-        m_sourceModel = model;
-    }
+    virtual void setSourceModel(Model *model);
+
+    /**
+     * Specify an aligment between this model's timeline and that of a
+     * reference model.  The alignment model records both the
+     * reference and the alignment.  This model takes ownership of the
+     * alignment model.
+     */
+    virtual void setAlignment(AlignmentModel *alignment);
+
+    /**
+     * Return the reference model for the current alignment timeline,
+     * if any.
+     */
+    virtual const Model *getAlignmentReference() const;
+
+    /**
+     * Return the frame number of the reference model that corresponds
+     * to the given frame number in this model.
+     */
+    virtual size_t alignToReference(size_t frame) const;
+
+    /**
+     * Return the frame number in this model that corresponds to the
+     * given frame number of the reference model.
+     */
+    virtual size_t alignFromReference(size_t referenceFrame) const;
+
+    /**
+     * Return the completion percentage for the alignment model: 100
+     * if there is no alignment model or it has been entirely
+     * calculated, or less than 100 if it is still being calculated.
+     */
+    virtual int getAlignmentCompletion() const;
 
     virtual void toXml(QTextStream &stream,
                        QString indent = "",
@@ -134,6 +166,10 @@
 
     virtual QString toDelimitedDataString(QString) const { return ""; }
 
+public slots:
+    void aboutToDelete();
+    void sourceModelAboutToBeDeleted();
+
 signals:
     /**
      * Emitted when a model has been edited (or more data retrieved
@@ -155,14 +191,32 @@
      */
     void completionChanged();
 
+    /**
+     * Emitted when the completion percentage changes for the
+     * calculation of this model's alignment model.
+     */
+    void alignmentCompletionChanged();
+
+    /**
+     * Emitted when something notifies this model (through calling
+     * aboutToDelete() that it is about to delete it.  Note that this
+     * depends on an external agent such as a Document object or
+     * owning model telling the model that it is about to delete it;
+     * there is nothing in the model to guarantee that this signal
+     * will be emitted before the actual deletion.
+     */
+    void aboutToBeDeleted();
+
 protected:
-    Model() : m_sourceModel(0) { }
+    Model() : m_sourceModel(0), m_alignment(0), m_aboutToDelete(false) { }
 
     // Not provided.
     Model(const Model &);
     Model &operator=(const Model &); 
 
     Model *m_sourceModel;
+    AlignmentModel *m_alignment;
+    bool m_aboutToDelete;
 };
 
 #endif
--- a/data/model/RangeSummarisableTimeValueModel.cpp	Mon Oct 22 09:45:35 2007 +0000
+++ b/data/model/RangeSummarisableTimeValueModel.cpp	Wed Oct 24 15:21:38 2007 +0000
@@ -15,48 +15,4 @@
 
 #include "RangeSummarisableTimeValueModel.h"
 
-#include "AlignmentModel.h"
-
 #include <iostream>
-
-void
-RangeSummarisableTimeValueModel::setAlignment(AlignmentModel *alignment)
-{
-    delete m_alignment;
-    m_alignment = alignment;
-    connect(m_alignment, SIGNAL(completionChanged()),
-            this, SIGNAL(alignmentCompletionChanged()));
-}
-
-const Model *
-RangeSummarisableTimeValueModel::getAlignmentReference() const
-{
-    if (!m_alignment) return 0;
-    return m_alignment->getReferenceModel();
-}
-
-size_t
-RangeSummarisableTimeValueModel::alignToReference(size_t frame) const
-{
-    if (!m_alignment) return frame;
-    return m_alignment->toReference(frame);
-}
-
-size_t
-RangeSummarisableTimeValueModel::alignFromReference(size_t refFrame) const
-{
-    if (!m_alignment) return refFrame;
-    return m_alignment->fromReference(refFrame);
-}
-
-int
-RangeSummarisableTimeValueModel::getAlignmentCompletion() const
-{
-    std::cerr << "RangeSummarisableTimeValueModel::getAlignmentCompletion" << std::endl;
-    if (!m_alignment) return 100;
-    int completion = 0;
-    (void)m_alignment->isReady(&completion);
-    std::cerr << " -> " << completion << std::endl;
-    return completion;
-}
-
--- a/data/model/RangeSummarisableTimeValueModel.h	Mon Oct 22 09:45:35 2007 +0000
+++ b/data/model/RangeSummarisableTimeValueModel.h	Wed Oct 24 15:21:38 2007 +0000
@@ -21,8 +21,6 @@
 #include "DenseTimeValueModel.h"
 #include "base/ZoomConstraint.h"
 
-class AlignmentModel;
-
 /**
  * Base class for models containing dense two-dimensional data (value
  * against time) that may be meaningfully represented in a zoomed view
@@ -35,7 +33,7 @@
     Q_OBJECT
 
 public:
-    RangeSummarisableTimeValueModel() : m_alignment(0) { }
+    RangeSummarisableTimeValueModel() { }
 
     struct Range
     {
@@ -73,18 +71,6 @@
      * block size equal to the distance between start and end frames.
      */
     virtual Range getSummary(size_t channel, size_t start, size_t count) const = 0;
-
-    virtual void setAlignment(AlignmentModel *alignment); // I take ownership
-    virtual const Model *getAlignmentReference() const;
-    virtual size_t alignToReference(size_t frame) const;
-    virtual size_t alignFromReference(size_t referenceFrame) const;
-    virtual int getAlignmentCompletion() const;
-
-signals:
-    void alignmentCompletionChanged();
-
-protected:
-    AlignmentModel *m_alignment;
 };
 
 #endif