# HG changeset patch # User Chris Cannam # Date 1553261529 0 # Node ID 628ffbb0585682917a9220f44a10d02ebe5c13f0 # Parent 353a2d15f2136ac13118bafe59166db74695114d Update PathModel - doesn't use new EventSeries, but doesn't use SparseModel either - it's simpler than that diff -r 353a2d15f213 -r 628ffbb05856 data/model/AlignmentModel.cpp --- a/data/model/AlignmentModel.cpp Fri Mar 22 11:04:51 2019 +0000 +++ b/data/model/AlignmentModel.cpp Fri Mar 22 13:32:09 2019 +0000 @@ -244,7 +244,7 @@ sv_frame_t frame = p.getFrame(); double value = p.getValue(); sv_frame_t rframe = lrint(value * m_aligned->getSampleRate()); - m_path->addPoint(PathPoint(frame, rframe)); + m_path->add(PathPoint(frame, rframe)); } #ifdef DEBUG_ALIGNMENT_MODEL @@ -275,7 +275,7 @@ i != points.end(); ++i) { sv_frame_t frame = i->frame; sv_frame_t rframe = i->mapframe; - m_reversePath->addPoint(PathPoint(rframe, frame)); + m_reversePath->add(PathPoint(rframe, frame)); } #ifdef DEBUG_ALIGNMENT_MODEL @@ -306,7 +306,7 @@ cerr << "AlignmentModel::align: frame " << frame << " requested" << endl; #endif - PathModel::Point point(frame); + PathPoint point(frame); PathModel::PointList::const_iterator i = points.lower_bound(point); if (i == points.end()) { #ifdef DEBUG_ALIGNMENT_MODEL diff -r 353a2d15f213 -r 628ffbb05856 data/model/PathModel.h --- a/data/model/PathModel.h Fri Mar 22 11:04:51 2019 +0000 +++ b/data/model/PathModel.h Fri Mar 22 13:32:09 2019 +0000 @@ -17,26 +17,26 @@ #define SV_PATH_MODEL_H #include "Model.h" -#include "SparseModel.h" +#include "DeferredNotifier.h" #include "base/RealTime.h" #include "base/BaseTypes.h" +#include "base/XmlExportable.h" +#include "base/RealTime.h" + #include - +#include struct PathPoint { - PathPoint(sv_frame_t _frame) : frame(_frame), mapframe(_frame) { } + PathPoint(sv_frame_t _frame) : + frame(_frame), mapframe(_frame) { } PathPoint(sv_frame_t _frame, sv_frame_t _mapframe) : frame(_frame), mapframe(_mapframe) { } - int getDimensions() const { return 2; } - sv_frame_t frame; sv_frame_t mapframe; - QString getLabel() const { return ""; } - void toXml(QTextStream &stream, QString indent = "", QString extraAttributes = "") const { stream << QString("%1\n") @@ -51,44 +51,147 @@ return list.join(delimiter); } - struct Comparator { - bool operator()(const PathPoint &p1, const PathPoint &p2) const { - if (p1.frame != p2.frame) return p1.frame < p2.frame; - return p1.mapframe < p2.mapframe; - } - }; - - struct OrderComparator { - bool operator()(const PathPoint &p1, const PathPoint &p2) const { - return p1.frame < p2.frame; - } - }; + bool operator<(const PathPoint &p2) const { + if (frame != p2.frame) return frame < p2.frame; + return mapframe < p2.mapframe; + } }; -class PathModel : public SparseModel +class PathModel : public Model { public: - PathModel(sv_samplerate_t sampleRate, int resolution, bool notify = true) : - SparseModel(sampleRate, resolution, notify) { } + typedef std::set PointList; - void toXml(QTextStream &out, - QString indent = "", - QString extraAttributes = "") const override - { - SparseModel::toXml - (out, - indent, - QString("%1 subtype=\"path\"") - .arg(extraAttributes)); + PathModel(sv_samplerate_t sampleRate, + int resolution, + bool notifyOnAdd = true) : + m_sampleRate(sampleRate), + m_resolution(resolution), + m_notifier(this, + notifyOnAdd ? + DeferredNotifier::NOTIFY_ALWAYS : + DeferredNotifier::NOTIFY_DEFERRED), + m_completion(100), + m_start(0), + m_end(0) { + } + + QString getTypeName() const override { return tr("Text"); } + bool isSparse() const { return true; } + bool isOK() const override { return true; } + + sv_frame_t getStartFrame() const override { + return m_start; + } + sv_frame_t getEndFrame() const override { + return m_end; + } + + sv_samplerate_t getSampleRate() const override { return m_sampleRate; } + int getResolution() const { return m_resolution; } + + int getCompletion() const { return m_completion; } + + void setCompletion(int completion, bool update = true) { + + { QMutexLocker locker(&m_mutex); + if (m_completion == completion) return; + m_completion = completion; + } + + if (update) { + m_notifier.makeDeferredNotifications(); + } + + emit completionChanged(); + + if (completion == 100) { + // henceforth: + m_notifier.switchMode(DeferredNotifier::NOTIFY_ALWAYS); + emit modelChanged(); + } } /** - * TabularModel is inherited via SparseModel, but we don't need it here. + * Query methods. */ - QString getHeading(int) const override { return ""; } - bool isColumnTimeValue(int) const override { return false; } - SortType getSortType(int) const override { return SortNumeric; } + const PointList &getPoints() const { + return m_points; + } + /** + * Editing methods. + */ + void add(PathPoint p) { + + { QMutexLocker locker(&m_mutex); + m_points.insert(p); + + if (m_start == m_end) { + m_start = p.frame; + m_end = m_start + m_resolution; + } else { + if (p.frame < m_start) { + m_start = p.frame; + } + if (p.frame + m_resolution > m_end) { + m_end = p.frame + m_resolution; + } + } + } + + m_notifier.update(p.frame, m_resolution); + } + + void remove(PathPoint p) { + { QMutexLocker locker(&m_mutex); + m_points.erase(p); + } + + emit modelChangedWithin(p.frame, p.frame + m_resolution); + } + + void clear() { + { QMutexLocker locker(&m_mutex); + m_start = m_end = 0; + m_points.clear(); + } + } + + /** + * XmlExportable methods. + */ + void toXml(QTextStream &out, + QString indent = "", + QString extraAttributes = "") const override { + + Model::toXml + (out, + indent, + QString("type=\"sparse\" dimensions=\"2\" resolution=\"%1\" " + "notifyOnAdd=\"%2\" dataset=\"%3\" subtype=\"path\" %4") + .arg(m_resolution) + .arg("true") // always true after model reaches 100% - + // subsequent points are always notified + .arg(getObjectExportId(&m_points)) + .arg(extraAttributes)); + + + } + + +protected: + sv_samplerate_t m_sampleRate; + int m_resolution; + + DeferredNotifier m_notifier; + int m_completion; + + sv_frame_t m_start; + sv_frame_t m_end; + PointList m_points; + + mutable QMutex m_mutex; }; diff -r 353a2d15f213 -r 628ffbb05856 data/model/SparseModel.h --- a/data/model/SparseModel.h Fri Mar 22 11:04:51 2019 +0000 +++ b/data/model/SparseModel.h Fri Mar 22 13:32:09 2019 +0000 @@ -38,7 +38,6 @@ * Model containing sparse data (points with some properties). The * properties depend on the point type. */ - template class SparseModel : public Model, public TabularModel @@ -996,7 +995,6 @@ MacroCommand::addCommand(command); } - #endif diff -r 353a2d15f213 -r 628ffbb05856 data/model/test/TestSparseModels.h --- a/data/model/test/TestSparseModels.h Fri Mar 22 11:04:51 2019 +0000 +++ b/data/model/test/TestSparseModels.h Fri Mar 22 13:32:09 2019 +0000 @@ -18,6 +18,7 @@ #include "../SparseOneDimensionalModel.h" #include "../NoteModel.h" #include "../TextModel.h" +#include "../PathModel.h" #include #include @@ -246,6 +247,34 @@ } QCOMPARE(xml, expected); } + + void path_xml() { + PathModel m(100, 10, false); + PathPoint p1(20, 30); + PathPoint p2(40, 60); + PathPoint p3(50, 49); + m.addPoint(p1); + m.addPoint(p2); + m.addPoint(p3); + QString xml; + QTextStream str(&xml, QIODevice::WriteOnly); + m.toXml(str); + str.flush(); + + QString expected = + "\n" + "\n" + " \n" + " \n" + " \n" + "\n"; + expected.replace("\'", "\""); + if (xml != expected) { + cerr << "Obtained xml:\n" << xml + << "\nExpected:\n" << expected << endl; + } + QCOMPARE(xml, expected); + } };