Mercurial > hg > svcore
comparison data/model/PathModel.h @ 1662:628ffbb05856 single-point
Update PathModel - doesn't use new EventSeries, but doesn't use SparseModel either - it's simpler than that
author | Chris Cannam |
---|---|
date | Fri, 22 Mar 2019 13:32:09 +0000 |
parents | ad5f892c0c4d |
children | a77a7e8c085c |
comparison
equal
deleted
inserted
replaced
1661:353a2d15f213 | 1662:628ffbb05856 |
---|---|
15 | 15 |
16 #ifndef SV_PATH_MODEL_H | 16 #ifndef SV_PATH_MODEL_H |
17 #define SV_PATH_MODEL_H | 17 #define SV_PATH_MODEL_H |
18 | 18 |
19 #include "Model.h" | 19 #include "Model.h" |
20 #include "SparseModel.h" | 20 #include "DeferredNotifier.h" |
21 #include "base/RealTime.h" | 21 #include "base/RealTime.h" |
22 #include "base/BaseTypes.h" | 22 #include "base/BaseTypes.h" |
23 | 23 |
24 #include "base/XmlExportable.h" | |
25 #include "base/RealTime.h" | |
26 | |
24 #include <QStringList> | 27 #include <QStringList> |
25 | 28 #include <set> |
26 | 29 |
27 struct PathPoint | 30 struct PathPoint |
28 { | 31 { |
29 PathPoint(sv_frame_t _frame) : frame(_frame), mapframe(_frame) { } | 32 PathPoint(sv_frame_t _frame) : |
33 frame(_frame), mapframe(_frame) { } | |
30 PathPoint(sv_frame_t _frame, sv_frame_t _mapframe) : | 34 PathPoint(sv_frame_t _frame, sv_frame_t _mapframe) : |
31 frame(_frame), mapframe(_mapframe) { } | 35 frame(_frame), mapframe(_mapframe) { } |
32 | 36 |
33 int getDimensions() const { return 2; } | |
34 | |
35 sv_frame_t frame; | 37 sv_frame_t frame; |
36 sv_frame_t mapframe; | 38 sv_frame_t mapframe; |
37 | |
38 QString getLabel() const { return ""; } | |
39 | 39 |
40 void toXml(QTextStream &stream, QString indent = "", | 40 void toXml(QTextStream &stream, QString indent = "", |
41 QString extraAttributes = "") const { | 41 QString extraAttributes = "") const { |
42 stream << QString("%1<point frame=\"%2\" mapframe=\"%3\" %4/>\n") | 42 stream << QString("%1<point frame=\"%2\" mapframe=\"%3\" %4/>\n") |
43 .arg(indent).arg(frame).arg(mapframe).arg(extraAttributes); | 43 .arg(indent).arg(frame).arg(mapframe).arg(extraAttributes); |
49 list << RealTime::frame2RealTime(frame, sampleRate).toString().c_str(); | 49 list << RealTime::frame2RealTime(frame, sampleRate).toString().c_str(); |
50 list << QString("%1").arg(mapframe); | 50 list << QString("%1").arg(mapframe); |
51 return list.join(delimiter); | 51 return list.join(delimiter); |
52 } | 52 } |
53 | 53 |
54 struct Comparator { | 54 bool operator<(const PathPoint &p2) const { |
55 bool operator()(const PathPoint &p1, const PathPoint &p2) const { | 55 if (frame != p2.frame) return frame < p2.frame; |
56 if (p1.frame != p2.frame) return p1.frame < p2.frame; | 56 return mapframe < p2.mapframe; |
57 return p1.mapframe < p2.mapframe; | 57 } |
58 } | |
59 }; | |
60 | |
61 struct OrderComparator { | |
62 bool operator()(const PathPoint &p1, const PathPoint &p2) const { | |
63 return p1.frame < p2.frame; | |
64 } | |
65 }; | |
66 }; | 58 }; |
67 | 59 |
68 class PathModel : public SparseModel<PathPoint> | 60 class PathModel : public Model |
69 { | 61 { |
70 public: | 62 public: |
71 PathModel(sv_samplerate_t sampleRate, int resolution, bool notify = true) : | 63 typedef std::set<PathPoint> PointList; |
72 SparseModel<PathPoint>(sampleRate, resolution, notify) { } | |
73 | 64 |
74 void toXml(QTextStream &out, | 65 PathModel(sv_samplerate_t sampleRate, |
75 QString indent = "", | 66 int resolution, |
76 QString extraAttributes = "") const override | 67 bool notifyOnAdd = true) : |
77 { | 68 m_sampleRate(sampleRate), |
78 SparseModel<PathPoint>::toXml | 69 m_resolution(resolution), |
79 (out, | 70 m_notifier(this, |
80 indent, | 71 notifyOnAdd ? |
81 QString("%1 subtype=\"path\"") | 72 DeferredNotifier::NOTIFY_ALWAYS : |
82 .arg(extraAttributes)); | 73 DeferredNotifier::NOTIFY_DEFERRED), |
74 m_completion(100), | |
75 m_start(0), | |
76 m_end(0) { | |
77 } | |
78 | |
79 QString getTypeName() const override { return tr("Text"); } | |
80 bool isSparse() const { return true; } | |
81 bool isOK() const override { return true; } | |
82 | |
83 sv_frame_t getStartFrame() const override { | |
84 return m_start; | |
85 } | |
86 sv_frame_t getEndFrame() const override { | |
87 return m_end; | |
88 } | |
89 | |
90 sv_samplerate_t getSampleRate() const override { return m_sampleRate; } | |
91 int getResolution() const { return m_resolution; } | |
92 | |
93 int getCompletion() const { return m_completion; } | |
94 | |
95 void setCompletion(int completion, bool update = true) { | |
96 | |
97 { QMutexLocker locker(&m_mutex); | |
98 if (m_completion == completion) return; | |
99 m_completion = completion; | |
100 } | |
101 | |
102 if (update) { | |
103 m_notifier.makeDeferredNotifications(); | |
104 } | |
105 | |
106 emit completionChanged(); | |
107 | |
108 if (completion == 100) { | |
109 // henceforth: | |
110 m_notifier.switchMode(DeferredNotifier::NOTIFY_ALWAYS); | |
111 emit modelChanged(); | |
112 } | |
83 } | 113 } |
84 | 114 |
85 /** | 115 /** |
86 * TabularModel is inherited via SparseModel, but we don't need it here. | 116 * Query methods. |
87 */ | 117 */ |
88 QString getHeading(int) const override { return ""; } | 118 const PointList &getPoints() const { |
89 bool isColumnTimeValue(int) const override { return false; } | 119 return m_points; |
90 SortType getSortType(int) const override { return SortNumeric; } | 120 } |
91 | 121 |
122 /** | |
123 * Editing methods. | |
124 */ | |
125 void add(PathPoint p) { | |
126 | |
127 { QMutexLocker locker(&m_mutex); | |
128 m_points.insert(p); | |
129 | |
130 if (m_start == m_end) { | |
131 m_start = p.frame; | |
132 m_end = m_start + m_resolution; | |
133 } else { | |
134 if (p.frame < m_start) { | |
135 m_start = p.frame; | |
136 } | |
137 if (p.frame + m_resolution > m_end) { | |
138 m_end = p.frame + m_resolution; | |
139 } | |
140 } | |
141 } | |
142 | |
143 m_notifier.update(p.frame, m_resolution); | |
144 } | |
145 | |
146 void remove(PathPoint p) { | |
147 { QMutexLocker locker(&m_mutex); | |
148 m_points.erase(p); | |
149 } | |
150 | |
151 emit modelChangedWithin(p.frame, p.frame + m_resolution); | |
152 } | |
153 | |
154 void clear() { | |
155 { QMutexLocker locker(&m_mutex); | |
156 m_start = m_end = 0; | |
157 m_points.clear(); | |
158 } | |
159 } | |
160 | |
161 /** | |
162 * XmlExportable methods. | |
163 */ | |
164 void toXml(QTextStream &out, | |
165 QString indent = "", | |
166 QString extraAttributes = "") const override { | |
167 | |
168 Model::toXml | |
169 (out, | |
170 indent, | |
171 QString("type=\"sparse\" dimensions=\"2\" resolution=\"%1\" " | |
172 "notifyOnAdd=\"%2\" dataset=\"%3\" subtype=\"path\" %4") | |
173 .arg(m_resolution) | |
174 .arg("true") // always true after model reaches 100% - | |
175 // subsequent points are always notified | |
176 .arg(getObjectExportId(&m_points)) | |
177 .arg(extraAttributes)); | |
178 | |
179 | |
180 } | |
181 | |
182 | |
183 protected: | |
184 sv_samplerate_t m_sampleRate; | |
185 int m_resolution; | |
186 | |
187 DeferredNotifier m_notifier; | |
188 int m_completion; | |
189 | |
190 sv_frame_t m_start; | |
191 sv_frame_t m_end; | |
192 PointList m_points; | |
193 | |
194 mutable QMutex m_mutex; | |
92 }; | 195 }; |
93 | 196 |
94 | 197 |
95 #endif | 198 #endif |