# HG changeset patch # User Chris Cannam # Date 1193239298 0 # Node ID 3ff8f571da090e3ad07a560ce56bf0c947848861 # Parent 7a4bd2c8585c1655c21b0b3683f2ac39764aead5 * 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 diff -r 7a4bd2c8585c -r 3ff8f571da09 data/model/Model.cpp --- 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 @@ -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 { diff -r 7a4bd2c8585c -r 3ff8f571da09 data/model/Model.h --- 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 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 diff -r 7a4bd2c8585c -r 3ff8f571da09 data/model/RangeSummarisableTimeValueModel.cpp --- 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 - -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; -} - diff -r 7a4bd2c8585c -r 3ff8f571da09 data/model/RangeSummarisableTimeValueModel.h --- 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