Mercurial > hg > svcore
comparison data/model/AlignmentModel.cpp @ 1766:85b9b466a59f
Merge from branch by-id
author | Chris Cannam |
---|---|
date | Wed, 17 Jul 2019 14:24:51 +0100 |
parents | 9945ad04c174 |
children | f19711ab7074 |
comparison
equal
deleted
inserted
replaced
1730:649ac57c5a2d | 1766:85b9b466a59f |
---|---|
17 | 17 |
18 #include "SparseTimeValueModel.h" | 18 #include "SparseTimeValueModel.h" |
19 | 19 |
20 //#define DEBUG_ALIGNMENT_MODEL 1 | 20 //#define DEBUG_ALIGNMENT_MODEL 1 |
21 | 21 |
22 AlignmentModel::AlignmentModel(Model *reference, | 22 AlignmentModel::AlignmentModel(ModelId reference, |
23 Model *aligned, | 23 ModelId aligned, |
24 SparseTimeValueModel *path) : | 24 ModelId pathSource) : |
25 m_reference(reference), | 25 m_reference(reference), |
26 m_aligned(aligned), | 26 m_aligned(aligned), |
27 m_rawPath(path), | 27 m_pathSource(pathSource), |
28 m_path(nullptr), | 28 m_path(nullptr), |
29 m_reversePath(nullptr), | 29 m_reversePath(nullptr), |
30 m_pathBegun(false), | 30 m_pathBegun(false), |
31 m_pathComplete(false) | 31 m_pathComplete(false) |
32 { | 32 { |
33 if (m_rawPath) { | 33 setPathFrom(pathSource); |
34 | |
35 connect(m_rawPath, SIGNAL(modelChanged()), | |
36 this, SLOT(pathChanged())); | |
37 | |
38 connect(m_rawPath, SIGNAL(modelChangedWithin(sv_frame_t, sv_frame_t)), | |
39 this, SLOT(pathChangedWithin(sv_frame_t, sv_frame_t))); | |
40 | |
41 connect(m_rawPath, SIGNAL(completionChanged()), | |
42 this, SLOT(pathCompletionChanged())); | |
43 | |
44 constructPath(); | |
45 constructReversePath(); | |
46 } | |
47 | |
48 if (m_rawPath && m_rawPath->isReady()) { | |
49 pathCompletionChanged(); | |
50 } | |
51 | 34 |
52 if (m_reference == m_aligned) { | 35 if (m_reference == m_aligned) { |
53 // Trivial alignment, e.g. of main model to itself, which we | 36 // Trivial alignment, e.g. of main model to itself, which we |
54 // record so that we can distinguish the reference model for | 37 // record so that we can distinguish the reference model for |
55 // alignments from an unaligned model. No path required | 38 // alignments from an unaligned model. No path required |
60 AlignmentModel::~AlignmentModel() | 43 AlignmentModel::~AlignmentModel() |
61 { | 44 { |
62 #ifdef DEBUG_ALIGNMENT_MODEL | 45 #ifdef DEBUG_ALIGNMENT_MODEL |
63 SVCERR << "AlignmentModel(" << this << ")::~AlignmentModel()" << endl; | 46 SVCERR << "AlignmentModel(" << this << ")::~AlignmentModel()" << endl; |
64 #endif | 47 #endif |
65 | |
66 if (m_rawPath) m_rawPath->aboutToDelete(); | |
67 delete m_rawPath; | |
68 | |
69 if (m_path) m_path->aboutToDelete(); | |
70 delete m_path; | |
71 | |
72 if (m_reversePath) m_reversePath->aboutToDelete(); | |
73 delete m_reversePath; | |
74 } | 48 } |
75 | 49 |
76 bool | 50 bool |
77 AlignmentModel::isOK() const | 51 AlignmentModel::isOK() const |
78 { | 52 { |
79 if (m_error != "") return false; | 53 if (m_error != "") return false; |
80 if (m_rawPath) return m_rawPath->isOK(); | 54 if (m_pathSource.isNone()) return true; |
55 auto pathSourceModel = | |
56 ModelById::getAs<SparseTimeValueModel>(m_pathSource); | |
57 if (pathSourceModel) { | |
58 return pathSourceModel->isOK(); | |
59 } | |
81 return true; | 60 return true; |
82 } | 61 } |
83 | 62 |
84 sv_frame_t | 63 sv_frame_t |
85 AlignmentModel::getStartFrame() const | 64 AlignmentModel::getStartFrame() const |
86 { | 65 { |
87 sv_frame_t a = m_reference->getStartFrame(); | 66 auto reference = ModelById::get(m_reference); |
88 sv_frame_t b = m_aligned->getStartFrame(); | 67 auto aligned = ModelById::get(m_aligned); |
89 return std::min(a, b); | 68 |
69 if (reference && aligned) { | |
70 sv_frame_t a = reference->getStartFrame(); | |
71 sv_frame_t b = aligned->getStartFrame(); | |
72 return std::min(a, b); | |
73 } else { | |
74 return 0; | |
75 } | |
90 } | 76 } |
91 | 77 |
92 sv_frame_t | 78 sv_frame_t |
93 AlignmentModel::getTrueEndFrame() const | 79 AlignmentModel::getTrueEndFrame() const |
94 { | 80 { |
95 sv_frame_t a = m_reference->getEndFrame(); | 81 auto reference = ModelById::get(m_reference); |
96 sv_frame_t b = m_aligned->getEndFrame(); | 82 auto aligned = ModelById::get(m_aligned); |
97 return std::max(a, b); | 83 |
84 if (reference && aligned) { | |
85 sv_frame_t a = reference->getEndFrame(); | |
86 sv_frame_t b = aligned->getEndFrame(); | |
87 return std::max(a, b); | |
88 } else { | |
89 return 0; | |
90 } | |
98 } | 91 } |
99 | 92 |
100 sv_samplerate_t | 93 sv_samplerate_t |
101 AlignmentModel::getSampleRate() const | 94 AlignmentModel::getSampleRate() const |
102 { | 95 { |
103 return m_reference->getSampleRate(); | 96 auto reference = ModelById::get(m_reference); |
97 if (reference) { | |
98 return reference->getSampleRate(); | |
99 } else { | |
100 return 0; | |
101 } | |
104 } | 102 } |
105 | 103 |
106 bool | 104 bool |
107 AlignmentModel::isReady(int *completion) const | 105 AlignmentModel::isReady(int *completion) const |
108 { | 106 { |
109 if (!m_pathBegun && m_rawPath) { | 107 if (!m_pathBegun && !m_pathSource.isNone()) { |
110 if (completion) *completion = 0; | 108 if (completion) *completion = 0; |
111 #ifdef DEBUG_ALIGNMENT_MODEL | 109 #ifdef DEBUG_ALIGNMENT_MODEL |
112 SVCERR << "AlignmentModel::isReady: path not begun" << endl; | 110 SVCERR << "AlignmentModel::isReady: path not begun" << endl; |
113 #endif | 111 #endif |
114 return false; | 112 return false; |
118 #ifdef DEBUG_ALIGNMENT_MODEL | 116 #ifdef DEBUG_ALIGNMENT_MODEL |
119 SVCERR << "AlignmentModel::isReady: path complete" << endl; | 117 SVCERR << "AlignmentModel::isReady: path complete" << endl; |
120 #endif | 118 #endif |
121 return true; | 119 return true; |
122 } | 120 } |
123 if (!m_rawPath) { | 121 if (m_pathSource.isNone()) { |
124 // lack of raw path could mean path is complete (in which case | 122 // lack of raw path could mean path is complete (in which case |
125 // m_pathComplete true above) or else no alignment has been | 123 // m_pathComplete true above) or else no path source has been |
126 // set at all yet (this case) | 124 // set at all yet (this case) |
127 if (completion) *completion = 0; | 125 if (completion) *completion = 0; |
128 #ifdef DEBUG_ALIGNMENT_MODEL | 126 #ifdef DEBUG_ALIGNMENT_MODEL |
129 SVCERR << "AlignmentModel::isReady: no raw path" << endl; | 127 SVCERR << "AlignmentModel::isReady: no raw path" << endl; |
130 #endif | 128 #endif |
131 return false; | 129 return false; |
132 } | 130 } |
133 return m_rawPath->isReady(completion); | 131 auto pathSourceModel = |
132 ModelById::getAs<SparseTimeValueModel>(m_pathSource); | |
133 if (pathSourceModel) { | |
134 return pathSourceModel->isReady(completion); | |
135 } else { | |
136 return true; // there is no meaningful answer here | |
137 } | |
134 } | 138 } |
135 | 139 |
136 const ZoomConstraint * | 140 const ZoomConstraint * |
137 AlignmentModel::getZoomConstraint() const | 141 AlignmentModel::getZoomConstraint() const |
138 { | 142 { |
139 return nullptr; | 143 return nullptr; |
140 } | 144 } |
141 | 145 |
142 const Model * | 146 ModelId |
143 AlignmentModel::getReferenceModel() const | 147 AlignmentModel::getReferenceModel() const |
144 { | 148 { |
145 return m_reference; | 149 return m_reference; |
146 } | 150 } |
147 | 151 |
148 const Model * | 152 ModelId |
149 AlignmentModel::getAlignedModel() const | 153 AlignmentModel::getAlignedModel() const |
150 { | 154 { |
151 return m_aligned; | 155 return m_aligned; |
152 } | 156 } |
153 | 157 |
156 { | 160 { |
157 #ifdef DEBUG_ALIGNMENT_MODEL | 161 #ifdef DEBUG_ALIGNMENT_MODEL |
158 cerr << "AlignmentModel::toReference(" << frame << ")" << endl; | 162 cerr << "AlignmentModel::toReference(" << frame << ")" << endl; |
159 #endif | 163 #endif |
160 if (!m_path) { | 164 if (!m_path) { |
161 if (!m_rawPath) return frame; | 165 if (m_pathSource.isNone()) { |
166 return frame; | |
167 } | |
162 constructPath(); | 168 constructPath(); |
163 } | 169 } |
164 return align(m_path, frame); | 170 if (!m_path) { |
171 return frame; | |
172 } | |
173 | |
174 return performAlignment(*m_path, frame); | |
165 } | 175 } |
166 | 176 |
167 sv_frame_t | 177 sv_frame_t |
168 AlignmentModel::fromReference(sv_frame_t frame) const | 178 AlignmentModel::fromReference(sv_frame_t frame) const |
169 { | 179 { |
170 #ifdef DEBUG_ALIGNMENT_MODEL | 180 #ifdef DEBUG_ALIGNMENT_MODEL |
171 cerr << "AlignmentModel::fromReference(" << frame << ")" << endl; | 181 cerr << "AlignmentModel::fromReference(" << frame << ")" << endl; |
172 #endif | 182 #endif |
173 if (!m_reversePath) { | 183 if (!m_reversePath) { |
174 if (!m_rawPath) return frame; | 184 if (m_pathSource.isNone()) { |
185 return frame; | |
186 } | |
175 constructReversePath(); | 187 constructReversePath(); |
176 } | 188 } |
177 return align(m_reversePath, frame); | 189 if (!m_reversePath) { |
178 } | 190 return frame; |
179 | 191 } |
180 void | 192 |
181 AlignmentModel::pathChanged() | 193 return performAlignment(*m_reversePath, frame); |
182 { | 194 } |
183 if (m_pathComplete) { | 195 |
184 cerr << "AlignmentModel: deleting raw path model" << endl; | 196 void |
185 if (m_rawPath) m_rawPath->aboutToDelete(); | 197 AlignmentModel::pathSourceChangedWithin(ModelId, sv_frame_t, sv_frame_t) |
186 delete m_rawPath; | |
187 m_rawPath = nullptr; | |
188 } | |
189 } | |
190 | |
191 void | |
192 AlignmentModel::pathChangedWithin(sv_frame_t, sv_frame_t) | |
193 { | 198 { |
194 if (!m_pathComplete) return; | 199 if (!m_pathComplete) return; |
195 constructPath(); | 200 constructPath(); |
196 constructReversePath(); | 201 constructReversePath(); |
197 } | 202 } |
198 | 203 |
199 void | 204 void |
200 AlignmentModel::pathCompletionChanged() | 205 AlignmentModel::pathSourceCompletionChanged(ModelId) |
201 { | 206 { |
202 if (!m_rawPath) return; | 207 auto pathSourceModel = |
208 ModelById::getAs<SparseTimeValueModel>(m_pathSource); | |
209 if (!pathSourceModel) return; | |
210 | |
203 m_pathBegun = true; | 211 m_pathBegun = true; |
204 | 212 |
205 if (!m_pathComplete) { | 213 if (!m_pathComplete) { |
206 | 214 |
207 int completion = 0; | 215 int completion = 0; |
208 m_rawPath->isReady(&completion); | 216 pathSourceModel->isReady(&completion); |
209 | 217 |
210 #ifdef DEBUG_ALIGNMENT_MODEL | 218 #ifdef DEBUG_ALIGNMENT_MODEL |
211 SVCERR << "AlignmentModel::pathCompletionChanged: completion = " | 219 SVCERR << "AlignmentModel::pathCompletionChanged: completion = " |
212 << completion << endl; | 220 << completion << endl; |
213 #endif | 221 #endif |
223 SVCERR << "AlignmentModel: path complete" << endl; | 231 SVCERR << "AlignmentModel: path complete" << endl; |
224 #endif | 232 #endif |
225 } | 233 } |
226 } | 234 } |
227 | 235 |
228 emit completionChanged(); | 236 emit completionChanged(getId()); |
229 } | 237 } |
230 | 238 |
231 void | 239 void |
232 AlignmentModel::constructPath() const | 240 AlignmentModel::constructPath() const |
233 { | 241 { |
242 auto alignedModel = ModelById::get(m_aligned); | |
243 if (!alignedModel) return; | |
244 | |
245 auto pathSourceModel = | |
246 ModelById::getAs<SparseTimeValueModel>(m_pathSource); | |
234 if (!m_path) { | 247 if (!m_path) { |
235 if (!m_rawPath) { | 248 if (!pathSourceModel) { |
236 cerr << "ERROR: AlignmentModel::constructPath: " | 249 cerr << "ERROR: AlignmentModel::constructPath: " |
237 << "No raw path available" << endl; | 250 << "No raw path available (id is " << m_pathSource |
251 << ")" << endl; | |
238 return; | 252 return; |
239 } | 253 } |
240 m_path = new PathModel | 254 m_path.reset(new Path |
241 (m_rawPath->getSampleRate(), m_rawPath->getResolution(), false); | 255 (pathSourceModel->getSampleRate(), |
242 } else { | 256 pathSourceModel->getResolution())); |
243 if (!m_rawPath) return; | 257 } else { |
258 if (!pathSourceModel) return; | |
244 } | 259 } |
245 | 260 |
246 m_path->clear(); | 261 m_path->clear(); |
247 | 262 |
248 EventVector points = m_rawPath->getAllEvents(); | 263 EventVector points = pathSourceModel->getAllEvents(); |
249 | 264 |
250 for (const auto &p: points) { | 265 for (const auto &p: points) { |
251 sv_frame_t frame = p.getFrame(); | 266 sv_frame_t frame = p.getFrame(); |
252 double value = p.getValue(); | 267 double value = p.getValue(); |
253 sv_frame_t rframe = lrint(value * m_aligned->getSampleRate()); | 268 sv_frame_t rframe = lrint(value * alignedModel->getSampleRate()); |
254 m_path->add(PathPoint(frame, rframe)); | 269 m_path->add(PathPoint(frame, rframe)); |
255 } | 270 } |
256 | 271 |
257 #ifdef DEBUG_ALIGNMENT_MODEL | 272 #ifdef DEBUG_ALIGNMENT_MODEL |
258 cerr << "AlignmentModel::constructPath: " << m_path->getPointCount() << " points, at least " << (2 * m_path->getPointCount() * (3 * sizeof(void *) + sizeof(int) + sizeof(PathPoint))) << " bytes" << endl; | 273 cerr << "AlignmentModel::constructPath: " << m_path->getPointCount() << " points, at least " << (2 * m_path->getPointCount() * (3 * sizeof(void *) + sizeof(int) + sizeof(PathPoint))) << " bytes" << endl; |
266 if (!m_path) { | 281 if (!m_path) { |
267 cerr << "ERROR: AlignmentModel::constructReversePath: " | 282 cerr << "ERROR: AlignmentModel::constructReversePath: " |
268 << "No forward path available" << endl; | 283 << "No forward path available" << endl; |
269 return; | 284 return; |
270 } | 285 } |
271 m_reversePath = new PathModel | 286 m_reversePath.reset(new Path |
272 (m_path->getSampleRate(), m_path->getResolution(), false); | 287 (m_path->getSampleRate(), |
288 m_path->getResolution())); | |
273 } else { | 289 } else { |
274 if (!m_path) return; | 290 if (!m_path) return; |
275 } | 291 } |
276 | 292 |
277 m_reversePath->clear(); | 293 m_reversePath->clear(); |
278 | 294 |
279 PathModel::PointList points = m_path->getPoints(); | 295 Path::Points points = m_path->getPoints(); |
280 | 296 |
281 for (PathModel::PointList::const_iterator i = points.begin(); | 297 for (auto p: points) { |
282 i != points.end(); ++i) { | 298 sv_frame_t frame = p.frame; |
283 sv_frame_t frame = i->frame; | 299 sv_frame_t rframe = p.mapframe; |
284 sv_frame_t rframe = i->mapframe; | |
285 m_reversePath->add(PathPoint(rframe, frame)); | 300 m_reversePath->add(PathPoint(rframe, frame)); |
286 } | 301 } |
287 | 302 |
288 #ifdef DEBUG_ALIGNMENT_MODEL | 303 #ifdef DEBUG_ALIGNMENT_MODEL |
289 cerr << "AlignmentModel::constructReversePath: " << m_reversePath->getPointCount() << " points, at least " << (2 * m_reversePath->getPointCount() * (3 * sizeof(void *) + sizeof(int) + sizeof(PathPoint))) << " bytes" << endl; | 304 cerr << "AlignmentModel::constructReversePath: " << m_reversePath->getPointCount() << " points, at least " << (2 * m_reversePath->getPointCount() * (3 * sizeof(void *) + sizeof(int) + sizeof(PathPoint))) << " bytes" << endl; |
290 #endif | 305 #endif |
291 } | 306 } |
292 | 307 |
293 sv_frame_t | 308 sv_frame_t |
294 AlignmentModel::align(PathModel *path, sv_frame_t frame) const | 309 AlignmentModel::performAlignment(const Path &path, sv_frame_t frame) const |
295 { | 310 { |
296 if (!path) return frame; | |
297 | |
298 // The path consists of a series of points, each with frame equal | 311 // The path consists of a series of points, each with frame equal |
299 // to the frame on the source model and mapframe equal to the | 312 // to the frame on the source model and mapframe equal to the |
300 // frame on the target model. Both should be monotonically | 313 // frame on the target model. Both should be monotonically |
301 // increasing. | 314 // increasing. |
302 | 315 |
303 const PathModel::PointList &points = path->getPoints(); | 316 const Path::Points &points = path.getPoints(); |
304 | 317 |
305 if (points.empty()) { | 318 if (points.empty()) { |
306 #ifdef DEBUG_ALIGNMENT_MODEL | 319 #ifdef DEBUG_ALIGNMENT_MODEL |
307 cerr << "AlignmentModel::align: No points" << endl; | 320 cerr << "AlignmentModel::align: No points" << endl; |
308 #endif | 321 #endif |
312 #ifdef DEBUG_ALIGNMENT_MODEL | 325 #ifdef DEBUG_ALIGNMENT_MODEL |
313 cerr << "AlignmentModel::align: frame " << frame << " requested" << endl; | 326 cerr << "AlignmentModel::align: frame " << frame << " requested" << endl; |
314 #endif | 327 #endif |
315 | 328 |
316 PathPoint point(frame); | 329 PathPoint point(frame); |
317 PathModel::PointList::const_iterator i = points.lower_bound(point); | 330 Path::Points::const_iterator i = points.lower_bound(point); |
318 if (i == points.end()) { | 331 if (i == points.end()) { |
319 #ifdef DEBUG_ALIGNMENT_MODEL | 332 #ifdef DEBUG_ALIGNMENT_MODEL |
320 cerr << "Note: i == points.end()" << endl; | 333 cerr << "Note: i == points.end()" << endl; |
321 #endif | 334 #endif |
322 --i; | 335 --i; |
323 } | 336 } |
324 while (i != points.begin() && i->frame > frame) --i; | 337 while (i != points.begin() && i->frame > frame) { |
338 --i; | |
339 } | |
325 | 340 |
326 sv_frame_t foundFrame = i->frame; | 341 sv_frame_t foundFrame = i->frame; |
327 sv_frame_t foundMapFrame = i->mapframe; | 342 sv_frame_t foundMapFrame = i->mapframe; |
328 | 343 |
329 sv_frame_t followingFrame = foundFrame; | 344 sv_frame_t followingFrame = foundFrame; |
345 cerr << "foundFrame = " << foundFrame << ", foundMapFrame = " << foundMapFrame | 360 cerr << "foundFrame = " << foundFrame << ", foundMapFrame = " << foundMapFrame |
346 << ", followingFrame = " << followingFrame << ", followingMapFrame = " | 361 << ", followingFrame = " << followingFrame << ", followingMapFrame = " |
347 << followingMapFrame << endl; | 362 << followingMapFrame << endl; |
348 #endif | 363 #endif |
349 | 364 |
350 if (foundMapFrame < 0) return 0; | 365 if (foundMapFrame < 0) { |
366 return 0; | |
367 } | |
351 | 368 |
352 sv_frame_t resultFrame = foundMapFrame; | 369 sv_frame_t resultFrame = foundMapFrame; |
353 | 370 |
354 if (followingFrame != foundFrame && frame > foundFrame) { | 371 if (followingFrame != foundFrame && frame > foundFrame) { |
355 double interp = | 372 double interp = |
364 | 381 |
365 return resultFrame; | 382 return resultFrame; |
366 } | 383 } |
367 | 384 |
368 void | 385 void |
369 AlignmentModel::setPathFrom(SparseTimeValueModel *rawpath) | 386 AlignmentModel::setPathFrom(ModelId pathSource) |
370 { | 387 { |
371 if (m_rawPath) m_rawPath->aboutToDelete(); | 388 m_pathSource = pathSource; |
372 delete m_rawPath; | 389 |
373 | 390 auto pathSourceModel = |
374 m_rawPath = rawpath; | 391 ModelById::getAs<SparseTimeValueModel>(m_pathSource); |
375 | 392 |
376 if (!m_rawPath) { | 393 if (pathSourceModel) { |
377 return; | 394 |
378 } | 395 connect(pathSourceModel.get(), |
379 | 396 SIGNAL(modelChangedWithin(ModelId, sv_frame_t, sv_frame_t)), |
380 connect(m_rawPath, SIGNAL(modelChanged()), | 397 this, SLOT(pathSourceChangedWithin(ModelId, sv_frame_t, sv_frame_t))); |
381 this, SLOT(pathChanged())); | |
382 | |
383 connect(m_rawPath, SIGNAL(modelChangedWithin(sv_frame_t, sv_frame_t)), | |
384 this, SLOT(pathChangedWithin(sv_frame_t, sv_frame_t))); | |
385 | 398 |
386 connect(m_rawPath, SIGNAL(completionChanged()), | 399 connect(pathSourceModel.get(), SIGNAL(completionChanged(ModelId)), |
387 this, SLOT(pathCompletionChanged())); | 400 this, SLOT(pathSourceCompletionChanged(ModelId))); |
388 | 401 |
389 constructPath(); | 402 constructPath(); |
403 constructReversePath(); | |
404 | |
405 if (pathSourceModel->isReady()) { | |
406 pathSourceCompletionChanged(m_pathSource); | |
407 } | |
408 } | |
409 } | |
410 | |
411 void | |
412 AlignmentModel::setPath(const Path &path) | |
413 { | |
414 m_path.reset(new Path(path)); | |
415 m_pathComplete = true; | |
390 constructReversePath(); | 416 constructReversePath(); |
391 | |
392 if (m_rawPath->isReady()) { | |
393 pathCompletionChanged(); | |
394 } | |
395 } | |
396 | |
397 void | |
398 AlignmentModel::setPath(PathModel *path) | |
399 { | |
400 if (m_path) m_path->aboutToDelete(); | |
401 delete m_path; | |
402 m_path = path; | |
403 m_pathComplete = true; | |
404 #ifdef DEBUG_ALIGNMENT_MODEL | |
405 cerr << "AlignmentModel::setPath: path = " << m_path << endl; | |
406 #endif | |
407 constructReversePath(); | |
408 #ifdef DEBUG_ALIGNMENT_MODEL | |
409 cerr << "AlignmentModel::setPath: after construction path = " | |
410 << m_path << ", rpath = " << m_reversePath << endl; | |
411 #endif | |
412 } | 417 } |
413 | 418 |
414 void | 419 void |
415 AlignmentModel::toXml(QTextStream &stream, | 420 AlignmentModel::toXml(QTextStream &stream, |
416 QString indent, | 421 QString indent, |
423 | 428 |
424 m_path->toXml(stream, indent, ""); | 429 m_path->toXml(stream, indent, ""); |
425 | 430 |
426 Model::toXml(stream, indent, | 431 Model::toXml(stream, indent, |
427 QString("type=\"alignment\" reference=\"%1\" aligned=\"%2\" path=\"%3\" %4") | 432 QString("type=\"alignment\" reference=\"%1\" aligned=\"%2\" path=\"%3\" %4") |
428 .arg(m_reference->getExportId()) | 433 .arg(ModelById::getExportId(m_reference)) |
429 .arg(m_aligned->getExportId()) | 434 .arg(ModelById::getExportId(m_aligned)) |
430 .arg(m_path->getExportId()) | 435 .arg(m_path->getExportId()) |
431 .arg(extraAttributes)); | 436 .arg(extraAttributes)); |
432 } | 437 } |
433 | |
434 |