annotate data/model/Model.h @ 1455:ec9e65fcf749

The use of the begin/end pairs here just seems to cause too many rows to be deleted (from the visual representation, not the underlying model). Things apparently work better if we just modify the underlying model and let the change signals percolate back up again. To that end, update the change handlers so as to cover their proper ranges with dataChanged signals.
author Chris Cannam
date Mon, 23 Apr 2018 16:03:35 +0100
parents 6e9615bde1f9
children 9d37c8cf9686
rev   line source
Chris@150 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@150 2
Chris@150 3 /*
Chris@150 4 Sonic Visualiser
Chris@150 5 An audio file viewer and annotation editor.
Chris@150 6 Centre for Digital Music, Queen Mary, University of London.
Chris@150 7 This file copyright 2006 Chris Cannam.
Chris@150 8
Chris@150 9 This program is free software; you can redistribute it and/or
Chris@150 10 modify it under the terms of the GNU General Public License as
Chris@150 11 published by the Free Software Foundation; either version 2 of the
Chris@150 12 License, or (at your option) any later version. See the file
Chris@150 13 COPYING included with this distribution for more information.
Chris@150 14 */
Chris@150 15
Chris@150 16 #ifndef _MODEL_H_
Chris@150 17 #define _MODEL_H_
Chris@150 18
Chris@150 19 #include <vector>
Chris@150 20 #include <QObject>
Chris@150 21
Chris@150 22 #include "base/XmlExportable.h"
Chris@391 23 #include "base/Playable.h"
Chris@1038 24 #include "base/BaseTypes.h"
Chris@1060 25 #include "base/DataExportOptions.h"
Chris@150 26
Chris@179 27 class ZoomConstraint;
Chris@319 28 class AlignmentModel;
Chris@179 29
Chris@150 30 /**
Chris@150 31 * Model is the base class for all data models that represent any sort
Chris@150 32 * of data on a time scale based on an audio frame rate.
Chris@150 33 */
Chris@150 34
Chris@179 35 class Model : public QObject,
Chris@1429 36 public XmlExportable,
Chris@391 37 public Playable
Chris@150 38 {
Chris@150 39 Q_OBJECT
Chris@150 40
Chris@150 41 public:
Chris@150 42 virtual ~Model();
Chris@150 43
Chris@150 44 /**
Chris@150 45 * Return true if the model was constructed successfully. Classes
Chris@150 46 * that refer to the model should always test this before use.
Chris@150 47 */
Chris@150 48 virtual bool isOK() const = 0;
Chris@150 49
Chris@150 50 /**
Chris@150 51 * Return the first audio frame spanned by the model.
Chris@150 52 */
Chris@1038 53 virtual sv_frame_t getStartFrame() const = 0;
Chris@150 54
Chris@150 55 /**
Chris@1451 56 * Return the audio frame at the end of the model, i.e. 1 more
Chris@1451 57 * than the final frame contained within the model. The end frame
Chris@1451 58 * minus the start frame should yield the total duration in frames
Chris@1451 59 * spanned by the model. This is consistent with the definition of
Chris@1451 60 * the end frame of a Selection object.
Chris@150 61 */
Chris@1038 62 virtual sv_frame_t getEndFrame() const = 0;
Chris@150 63
Chris@150 64 /**
Chris@150 65 * Return the frame rate in frames per second.
Chris@150 66 */
Chris@1040 67 virtual sv_samplerate_t getSampleRate() const = 0;
Chris@150 68
Chris@150 69 /**
Chris@297 70 * Return the frame rate of the underlying material, if the model
Chris@297 71 * itself has already been resampled.
Chris@297 72 */
Chris@1040 73 virtual sv_samplerate_t getNativeRate() const { return getSampleRate(); }
Chris@297 74
Chris@297 75 /**
Chris@333 76 * Return the "work title" of the model, if known.
Chris@333 77 */
Chris@333 78 virtual QString getTitle() const;
Chris@333 79
Chris@333 80 /**
Chris@333 81 * Return the "artist" or "maker" of the model, if known.
Chris@333 82 */
Chris@333 83 virtual QString getMaker() const;
Chris@333 84
Chris@333 85 /**
Chris@345 86 * Return the location of the data in this model (e.g. source
Chris@345 87 * URL). This should not normally be returned for editable models
Chris@345 88 * that have been edited.
Chris@345 89 */
Chris@345 90 virtual QString getLocation() const;
Chris@345 91
Chris@345 92 /**
Chris@345 93 * Return the type of the model. For display purposes only.
Chris@345 94 */
Chris@345 95 virtual QString getTypeName() const = 0;
Chris@345 96
Chris@345 97 /**
cannam@1452 98 * Return true if this is a sparse model.
cannam@1452 99 */
cannam@1452 100 virtual bool isSparse() const { return false; }
cannam@1452 101
cannam@1452 102 /**
Chris@923 103 * Mark the model as abandoning. This means that the application
Chris@923 104 * no longer needs it, so it can stop doing any background
Chris@923 105 * calculations it may be involved in. Note that as far as the
Chris@923 106 * model API is concerned, this does nothing more than tell the
Chris@923 107 * model to return true from isAbandoning(). The actual response
Chris@923 108 * to this will depend on the model's context -- it's possible
Chris@923 109 * nothing at all will change.
Chris@923 110 */
Chris@923 111 virtual void abandon() {
Chris@923 112 m_abandoning = true;
Chris@923 113 }
Chris@923 114
Chris@923 115 /**
Chris@923 116 * Query whether the model has been marked as abandoning.
Chris@923 117 */
Chris@923 118 virtual bool isAbandoning() const {
Chris@923 119 return m_abandoning;
Chris@923 120 }
Chris@923 121
Chris@150 122 /**
Chris@150 123 * Return true if the model has finished loading or calculating
Chris@150 124 * all its data, for a model that is capable of calculating in a
Chris@150 125 * background thread. The default implementation is appropriate
Chris@150 126 * for a thread that does not background any work but carries out
Chris@150 127 * all its calculation from the constructor or accessors.
Chris@150 128 *
Chris@150 129 * If "completion" is non-NULL, this function should return
Chris@150 130 * through it an estimated percentage value showing how far
Chris@150 131 * through the background operation it thinks it is (for progress
Chris@150 132 * reporting). If it has no way to calculate progress, it may
Chris@1133 133 * return the special value COMPLETION_UNKNOWN. See also
Chris@1133 134 * getCompletion().
Chris@150 135 */
Chris@150 136 virtual bool isReady(int *completion = 0) const {
Chris@1429 137 bool ok = isOK();
Chris@1429 138 if (completion) *completion = (ok ? 100 : 0);
Chris@1429 139 return ok;
Chris@150 140 }
Chris@150 141 static const int COMPLETION_UNKNOWN;
Chris@150 142
Chris@179 143 /**
Chris@179 144 * If this model imposes a zoom constraint, i.e. some limit to the
Chris@179 145 * set of resolutions at which its data can meaningfully be
Chris@179 146 * displayed, then return it.
Chris@179 147 */
Chris@179 148 virtual const ZoomConstraint *getZoomConstraint() const {
Chris@179 149 return 0;
Chris@179 150 }
Chris@179 151
Chris@297 152 /**
Chris@297 153 * If this model was derived from another, return the model it was
Chris@297 154 * derived from. The assumption is that the source model's
Chris@297 155 * alignment will also apply to this model, unless some other
Chris@319 156 * property (such as a specific alignment model set on this model)
Chris@319 157 * indicates otherwise.
Chris@297 158 */
Chris@297 159 virtual Model *getSourceModel() const {
Chris@297 160 return m_sourceModel;
Chris@297 161 }
Chris@297 162
Chris@297 163 /**
Chris@297 164 * Set the source model for this model.
Chris@297 165 */
Chris@319 166 virtual void setSourceModel(Model *model);
Chris@319 167
Chris@319 168 /**
Chris@319 169 * Specify an aligment between this model's timeline and that of a
Chris@319 170 * reference model. The alignment model records both the
Chris@319 171 * reference and the alignment. This model takes ownership of the
Chris@319 172 * alignment model.
Chris@319 173 */
Chris@319 174 virtual void setAlignment(AlignmentModel *alignment);
Chris@319 175
Chris@319 176 /**
Chris@407 177 * Retrieve the alignment model for this model. This is not a
Chris@407 178 * generally useful function, as the alignment you really want may
Chris@407 179 * be performed by the source model instead. You should normally
Chris@407 180 * use getAlignmentReference, alignToReference and
Chris@407 181 * alignFromReference instead of this. The main intended
Chris@407 182 * application for this function is in streaming out alignments to
Chris@407 183 * the session file.
Chris@407 184 */
Chris@407 185 virtual const AlignmentModel *getAlignment() const;
Chris@407 186
Chris@407 187 /**
Chris@319 188 * Return the reference model for the current alignment timeline,
Chris@319 189 * if any.
Chris@319 190 */
Chris@319 191 virtual const Model *getAlignmentReference() const;
Chris@319 192
Chris@319 193 /**
Chris@319 194 * Return the frame number of the reference model that corresponds
Chris@319 195 * to the given frame number in this model.
Chris@319 196 */
Chris@1038 197 virtual sv_frame_t alignToReference(sv_frame_t frame) const;
Chris@319 198
Chris@319 199 /**
Chris@319 200 * Return the frame number in this model that corresponds to the
Chris@319 201 * given frame number of the reference model.
Chris@319 202 */
Chris@1038 203 virtual sv_frame_t alignFromReference(sv_frame_t referenceFrame) const;
Chris@319 204
Chris@319 205 /**
Chris@319 206 * Return the completion percentage for the alignment model: 100
Chris@319 207 * if there is no alignment model or it has been entirely
Chris@319 208 * calculated, or less than 100 if it is still being calculated.
Chris@319 209 */
Chris@319 210 virtual int getAlignmentCompletion() const;
Chris@297 211
Chris@558 212 /**
Chris@558 213 * Set the event, feature, or signal type URI for the features
Chris@558 214 * contained in this model, according to the Audio Features RDF
Chris@558 215 * ontology.
Chris@558 216 */
Chris@558 217 void setRDFTypeURI(QString uri) { m_typeUri = uri; }
Chris@558 218
Chris@558 219 /**
Chris@558 220 * Retrieve the event, feature, or signal type URI for the
Chris@558 221 * features contained in this model, if previously set with
Chris@558 222 * setRDFTypeURI.
Chris@558 223 */
Chris@558 224 QString getRDFTypeURI() const { return m_typeUri; }
Chris@558 225
Chris@150 226 virtual void toXml(QTextStream &stream,
Chris@150 227 QString indent = "",
Chris@150 228 QString extraAttributes = "") const;
Chris@150 229
Chris@838 230 virtual QString toDelimitedDataString(QString delimiter) const {
Chris@1072 231 return toDelimitedDataStringSubset
Chris@1451 232 (delimiter, getStartFrame(), getEndFrame());
Chris@838 233 }
Chris@1060 234 virtual QString toDelimitedDataStringWithOptions(QString delimiter, DataExportOptions opts) const {
Chris@1072 235 return toDelimitedDataStringSubsetWithOptions
Chris@1451 236 (delimiter, opts, getStartFrame(), getEndFrame());
Chris@1060 237 }
Chris@1038 238 virtual QString toDelimitedDataStringSubset(QString, sv_frame_t /* f0 */, sv_frame_t /* f1 */) const {
Chris@838 239 return "";
Chris@838 240 }
Chris@1060 241 virtual QString toDelimitedDataStringSubsetWithOptions(QString delimiter, DataExportOptions, sv_frame_t f0, sv_frame_t f1) const {
Chris@1060 242 // Default implementation supports no options
Chris@1060 243 return toDelimitedDataStringSubset(delimiter, f0, f1);
Chris@1060 244 }
Chris@150 245
Chris@319 246 public slots:
Chris@319 247 void aboutToDelete();
Chris@319 248 void sourceModelAboutToBeDeleted();
Chris@319 249
Chris@150 250 signals:
Chris@150 251 /**
Chris@150 252 * Emitted when a model has been edited (or more data retrieved
Chris@150 253 * from cache, in the case of a cached model that generates slowly)
Chris@150 254 */
Chris@150 255 void modelChanged();
Chris@150 256
Chris@150 257 /**
Chris@150 258 * Emitted when a model has been edited (or more data retrieved
Chris@150 259 * from cache, in the case of a cached model that generates slowly)
Chris@150 260 */
Chris@1038 261 void modelChangedWithin(sv_frame_t startFrame, sv_frame_t endFrame);
Chris@150 262
Chris@150 263 /**
Chris@150 264 * Emitted when some internal processing has advanced a stage, but
Chris@150 265 * the model has not changed externally. Views should respond by
Chris@150 266 * updating any progress meters or other monitoring, but not
Chris@150 267 * refreshing the actual view.
Chris@150 268 */
Chris@150 269 void completionChanged();
Chris@150 270
Chris@319 271 /**
Chris@411 272 * Emitted when internal processing is complete (i.e. when
Chris@411 273 * isReady() would return true, with completion at 100).
Chris@411 274 */
Chris@411 275 void ready();
Chris@411 276
Chris@411 277 /**
Chris@319 278 * Emitted when the completion percentage changes for the
Chris@319 279 * calculation of this model's alignment model.
Chris@319 280 */
Chris@319 281 void alignmentCompletionChanged();
Chris@319 282
Chris@319 283 /**
Chris@319 284 * Emitted when something notifies this model (through calling
Chris@319 285 * aboutToDelete() that it is about to delete it. Note that this
Chris@319 286 * depends on an external agent such as a Document object or
Chris@319 287 * owning model telling the model that it is about to delete it;
Chris@319 288 * there is nothing in the model to guarantee that this signal
Chris@319 289 * will be emitted before the actual deletion.
Chris@319 290 */
Chris@319 291 void aboutToBeDeleted();
Chris@319 292
Chris@150 293 protected:
Chris@923 294 Model() :
Chris@923 295 m_sourceModel(0),
Chris@923 296 m_alignment(0),
Chris@923 297 m_abandoning(false),
Chris@923 298 m_aboutToDelete(false) { }
Chris@150 299
Chris@150 300 // Not provided.
Chris@150 301 Model(const Model &);
Chris@150 302 Model &operator=(const Model &);
Chris@297 303
Chris@297 304 Model *m_sourceModel;
Chris@319 305 AlignmentModel *m_alignment;
Chris@558 306 QString m_typeUri;
Chris@923 307 bool m_abandoning;
Chris@319 308 bool m_aboutToDelete;
Chris@150 309 };
Chris@150 310
Chris@150 311 #endif