Mercurial > hg > sonic-visualiser
comparison document/Document.cpp @ 0:cd5d7ff8ef38
* Reorganising code base. This revision will not compile.
author | Chris Cannam |
---|---|
date | Mon, 31 Jul 2006 12:03:45 +0000 |
parents | |
children | 40116f709d3b |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:cd5d7ff8ef38 |
---|---|
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ | |
2 | |
3 /* | |
4 Sonic Visualiser | |
5 An audio file viewer and annotation editor. | |
6 Centre for Digital Music, Queen Mary, University of London. | |
7 This file copyright 2006 Chris Cannam. | |
8 | |
9 This program is free software; you can redistribute it and/or | |
10 modify it under the terms of the GNU General Public License as | |
11 published by the Free Software Foundation; either version 2 of the | |
12 License, or (at your option) any later version. See the file | |
13 COPYING included with this distribution for more information. | |
14 */ | |
15 | |
16 #include "Document.h" | |
17 | |
18 #include "model/WaveFileModel.h" | |
19 #include "base/Layer.h" | |
20 #include "base/CommandHistory.h" | |
21 #include "base/Command.h" | |
22 #include "base/View.h" | |
23 #include "base/PlayParameterRepository.h" | |
24 #include "base/PlayParameters.h" | |
25 #include "transform/TransformFactory.h" | |
26 #include <iostream> | |
27 | |
28 //!!! still need to handle command history, documentRestored/documentModified | |
29 | |
30 Document::Document() : | |
31 m_mainModel(0) | |
32 { | |
33 } | |
34 | |
35 Document::~Document() | |
36 { | |
37 //!!! Document should really own the command history. atm we | |
38 //still refer to it in various places that don't have access to | |
39 //the document, be nice to fix that | |
40 | |
41 // std::cerr << "\n\nDocument::~Document: about to clear command history" << std::endl; | |
42 CommandHistory::getInstance()->clear(); | |
43 | |
44 // std::cerr << "Document::~Document: about to delete layers" << std::endl; | |
45 while (!m_layers.empty()) { | |
46 deleteLayer(*m_layers.begin(), true); | |
47 } | |
48 | |
49 if (!m_models.empty()) { | |
50 std::cerr << "Document::~Document: WARNING: " | |
51 << m_models.size() << " model(s) still remain -- " | |
52 << "should have been garbage collected when deleting layers" | |
53 << std::endl; | |
54 while (!m_models.empty()) { | |
55 if (m_models.begin()->first == m_mainModel) { | |
56 // just in case! | |
57 std::cerr << "Document::~Document: WARNING: Main model is also" | |
58 << " in models list!" << std::endl; | |
59 } else { | |
60 emit modelAboutToBeDeleted(m_models.begin()->first); | |
61 delete m_models.begin()->first; | |
62 } | |
63 m_models.erase(m_models.begin()); | |
64 } | |
65 } | |
66 | |
67 // std::cerr << "Document::~Document: About to get rid of main model" | |
68 // << std::endl; | |
69 emit modelAboutToBeDeleted(m_mainModel); | |
70 emit mainModelChanged(0); | |
71 delete m_mainModel; | |
72 | |
73 } | |
74 | |
75 Layer * | |
76 Document::createLayer(LayerFactory::LayerType type) | |
77 { | |
78 Layer *newLayer = LayerFactory::getInstance()->createLayer(type); | |
79 if (!newLayer) return 0; | |
80 | |
81 newLayer->setObjectName(getUniqueLayerName(newLayer->objectName())); | |
82 | |
83 m_layers.insert(newLayer); | |
84 emit layerAdded(newLayer); | |
85 | |
86 return newLayer; | |
87 } | |
88 | |
89 Layer * | |
90 Document::createMainModelLayer(LayerFactory::LayerType type) | |
91 { | |
92 Layer *newLayer = createLayer(type); | |
93 if (!newLayer) return 0; | |
94 setModel(newLayer, m_mainModel); | |
95 return newLayer; | |
96 } | |
97 | |
98 Layer * | |
99 Document::createImportedLayer(Model *model) | |
100 { | |
101 LayerFactory::LayerTypeSet types = | |
102 LayerFactory::getInstance()->getValidLayerTypes(model); | |
103 | |
104 if (types.empty()) { | |
105 std::cerr << "WARNING: Document::importLayer: no valid display layer for model" << std::endl; | |
106 return 0; | |
107 } | |
108 | |
109 //!!! for now, just use the first suitable layer type | |
110 LayerFactory::LayerType type = *types.begin(); | |
111 | |
112 Layer *newLayer = LayerFactory::getInstance()->createLayer(type); | |
113 if (!newLayer) return 0; | |
114 | |
115 newLayer->setObjectName(getUniqueLayerName(newLayer->objectName())); | |
116 | |
117 addImportedModel(model); | |
118 setModel(newLayer, model); | |
119 | |
120 //!!! and all channels | |
121 setChannel(newLayer, -1); | |
122 | |
123 m_layers.insert(newLayer); | |
124 emit layerAdded(newLayer); | |
125 return newLayer; | |
126 } | |
127 | |
128 Layer * | |
129 Document::createEmptyLayer(LayerFactory::LayerType type) | |
130 { | |
131 Model *newModel = | |
132 LayerFactory::getInstance()->createEmptyModel(type, m_mainModel); | |
133 if (!newModel) return 0; | |
134 | |
135 Layer *newLayer = createLayer(type); | |
136 if (!newLayer) { | |
137 delete newModel; | |
138 return 0; | |
139 } | |
140 | |
141 addImportedModel(newModel); | |
142 setModel(newLayer, newModel); | |
143 | |
144 return newLayer; | |
145 } | |
146 | |
147 Layer * | |
148 Document::createDerivedLayer(LayerFactory::LayerType type, | |
149 TransformName transform) | |
150 { | |
151 Layer *newLayer = createLayer(type); | |
152 if (!newLayer) return 0; | |
153 | |
154 newLayer->setObjectName(getUniqueLayerName | |
155 (TransformFactory::getInstance()-> | |
156 getTransformFriendlyName(transform))); | |
157 | |
158 return newLayer; | |
159 } | |
160 | |
161 Layer * | |
162 Document::createDerivedLayer(TransformName transform, | |
163 Model *inputModel, | |
164 int channel, | |
165 QString configurationXml) | |
166 { | |
167 Model *newModel = createModelForTransform(transform, inputModel, | |
168 channel, configurationXml); | |
169 if (!newModel) { | |
170 // error already printed to stderr by createModelForTransform | |
171 emit modelGenerationFailed(transform); | |
172 return 0; | |
173 } | |
174 | |
175 LayerFactory::LayerTypeSet types = | |
176 LayerFactory::getInstance()->getValidLayerTypes(newModel); | |
177 | |
178 if (types.empty()) { | |
179 std::cerr << "WARNING: Document::createLayerForTransform: no valid display layer for output of transform " << transform.toStdString() << std::endl; | |
180 delete newModel; | |
181 return 0; | |
182 } | |
183 | |
184 //!!! for now, just use the first suitable layer type | |
185 | |
186 Layer *newLayer = createLayer(*types.begin()); | |
187 setModel(newLayer, newModel); | |
188 | |
189 //!!! We need to clone the model when adding the layer, so that it | |
190 //can be edited without affecting other layers that are based on | |
191 //the same model. Unfortunately we can't just clone it now, | |
192 //because it probably hasn't been completed yet -- the transform | |
193 //runs in the background. Maybe the transform has to handle | |
194 //cloning and cacheing models itself. | |
195 // | |
196 // Once we do clone models here, of course, we'll have to avoid | |
197 // leaking them too. | |
198 // | |
199 // We want the user to be able to add a model to a second layer | |
200 // _while it's still being calculated in the first_ and have it | |
201 // work quickly. That means we need to put the same physical | |
202 // model pointer in both layers, so they can't actually be cloned. | |
203 | |
204 if (newLayer) { | |
205 newLayer->setObjectName(getUniqueLayerName | |
206 (TransformFactory::getInstance()-> | |
207 getTransformFriendlyName(transform))); | |
208 } | |
209 | |
210 emit layerAdded(newLayer); | |
211 return newLayer; | |
212 } | |
213 | |
214 void | |
215 Document::setMainModel(WaveFileModel *model) | |
216 { | |
217 Model *oldMainModel = m_mainModel; | |
218 m_mainModel = model; | |
219 | |
220 emit modelAdded(m_mainModel); | |
221 | |
222 std::vector<Layer *> obsoleteLayers; | |
223 std::set<QString> failedTransforms; | |
224 | |
225 // We need to ensure that no layer is left using oldMainModel or | |
226 // any of the old derived models as its model. Either replace the | |
227 // model, or delete the layer for each layer that is currently | |
228 // using one of these. Carry out this replacement before we | |
229 // delete any of the models. | |
230 | |
231 for (LayerSet::iterator i = m_layers.begin(); i != m_layers.end(); ++i) { | |
232 | |
233 Layer *layer = *i; | |
234 Model *model = layer->getModel(); | |
235 | |
236 if (model == oldMainModel) { | |
237 LayerFactory::getInstance()->setModel(layer, m_mainModel); | |
238 continue; | |
239 } | |
240 | |
241 if (m_models.find(model) == m_models.end()) { | |
242 std::cerr << "WARNING: Document::setMainModel: Unknown model " | |
243 << model << " in layer " << layer << std::endl; | |
244 // get rid of this hideous degenerate | |
245 obsoleteLayers.push_back(layer); | |
246 continue; | |
247 } | |
248 | |
249 if (m_models[model].source == oldMainModel) { | |
250 | |
251 // This model was derived from the previous main | |
252 // model: regenerate it. | |
253 | |
254 TransformName transform = m_models[model].transform; | |
255 int channel = m_models[model].channel; | |
256 | |
257 Model *replacementModel = | |
258 createModelForTransform(transform, | |
259 m_mainModel, | |
260 channel, | |
261 m_models[model].configurationXml); | |
262 | |
263 if (!replacementModel) { | |
264 std::cerr << "WARNING: Document::setMainModel: Failed to regenerate model for transform \"" | |
265 << transform.toStdString() << "\"" << " in layer " << layer << std::endl; | |
266 if (failedTransforms.find(transform) == failedTransforms.end()) { | |
267 emit modelRegenerationFailed(layer->objectName(), | |
268 transform); | |
269 failedTransforms.insert(transform); | |
270 } | |
271 obsoleteLayers.push_back(layer); | |
272 } else { | |
273 setModel(layer, replacementModel); | |
274 } | |
275 } | |
276 } | |
277 | |
278 for (size_t k = 0; k < obsoleteLayers.size(); ++k) { | |
279 deleteLayer(obsoleteLayers[k], true); | |
280 } | |
281 | |
282 emit mainModelChanged(m_mainModel); | |
283 | |
284 // we already emitted modelAboutToBeDeleted for this | |
285 delete oldMainModel; | |
286 } | |
287 | |
288 void | |
289 Document::addDerivedModel(TransformName transform, | |
290 Model *inputModel, | |
291 int channel, | |
292 Model *outputModelToAdd, | |
293 QString configurationXml) | |
294 { | |
295 if (m_models.find(outputModelToAdd) != m_models.end()) { | |
296 std::cerr << "WARNING: Document::addDerivedModel: Model already added" | |
297 << std::endl; | |
298 return; | |
299 } | |
300 | |
301 ModelRecord rec; | |
302 rec.source = inputModel; | |
303 rec.transform = transform; | |
304 rec.channel = channel; | |
305 rec.configurationXml = configurationXml; | |
306 rec.refcount = 0; | |
307 | |
308 m_models[outputModelToAdd] = rec; | |
309 | |
310 emit modelAdded(outputModelToAdd); | |
311 } | |
312 | |
313 | |
314 void | |
315 Document::addImportedModel(Model *model) | |
316 { | |
317 if (m_models.find(model) != m_models.end()) { | |
318 std::cerr << "WARNING: Document::addImportedModel: Model already added" | |
319 << std::endl; | |
320 return; | |
321 } | |
322 | |
323 ModelRecord rec; | |
324 rec.source = 0; | |
325 rec.transform = ""; | |
326 rec.channel = -1; | |
327 rec.refcount = 0; | |
328 | |
329 m_models[model] = rec; | |
330 | |
331 emit modelAdded(model); | |
332 } | |
333 | |
334 Model * | |
335 Document::createModelForTransform(TransformName transform, | |
336 Model *inputModel, | |
337 int channel, | |
338 QString configurationXml) | |
339 { | |
340 Model *model = 0; | |
341 | |
342 for (ModelMap::iterator i = m_models.begin(); i != m_models.end(); ++i) { | |
343 if (i->second.transform == transform && | |
344 i->second.source == inputModel && | |
345 i->second.channel == channel && | |
346 i->second.configurationXml == configurationXml) { | |
347 return i->first; | |
348 } | |
349 } | |
350 | |
351 model = TransformFactory::getInstance()->transform | |
352 (transform, inputModel, channel, configurationXml); | |
353 | |
354 if (!model) { | |
355 std::cerr << "WARNING: Document::createModelForTransform: no output model for transform " << transform.toStdString() << std::endl; | |
356 } else { | |
357 addDerivedModel(transform, inputModel, channel, model, configurationXml); | |
358 } | |
359 | |
360 return model; | |
361 } | |
362 | |
363 void | |
364 Document::releaseModel(Model *model) // Will _not_ release main model! | |
365 { | |
366 if (model == 0) { | |
367 return; | |
368 } | |
369 | |
370 if (model == m_mainModel) { | |
371 return; | |
372 } | |
373 | |
374 bool toDelete = false; | |
375 | |
376 if (m_models.find(model) != m_models.end()) { | |
377 | |
378 if (m_models[model].refcount == 0) { | |
379 std::cerr << "WARNING: Document::releaseModel: model " << model | |
380 << " reference count is zero already!" << std::endl; | |
381 } else { | |
382 if (--m_models[model].refcount == 0) { | |
383 toDelete = true; | |
384 } | |
385 } | |
386 } else { | |
387 std::cerr << "WARNING: Document::releaseModel: Unfound model " | |
388 << model << std::endl; | |
389 toDelete = true; | |
390 } | |
391 | |
392 if (toDelete) { | |
393 | |
394 int sourceCount = 0; | |
395 | |
396 for (ModelMap::iterator i = m_models.begin(); i != m_models.end(); ++i) { | |
397 if (i->second.source == model) { | |
398 ++sourceCount; | |
399 i->second.source = 0; | |
400 } | |
401 } | |
402 | |
403 if (sourceCount > 0) { | |
404 std::cerr << "Document::releaseModel: Deleting model " | |
405 << model << " even though it is source for " | |
406 << sourceCount << " other derived model(s) -- resetting " | |
407 << "their source fields appropriately" << std::endl; | |
408 } | |
409 | |
410 emit modelAboutToBeDeleted(model); | |
411 m_models.erase(model); | |
412 delete model; | |
413 } | |
414 } | |
415 | |
416 void | |
417 Document::deleteLayer(Layer *layer, bool force) | |
418 { | |
419 if (m_layerViewMap.find(layer) != m_layerViewMap.end() && | |
420 m_layerViewMap[layer].size() > 0) { | |
421 | |
422 std::cerr << "WARNING: Document::deleteLayer: Layer " | |
423 << layer << " [" << layer->objectName().toStdString() << "]" | |
424 << " is still used in " << m_layerViewMap[layer].size() | |
425 << " views!" << std::endl; | |
426 | |
427 if (force) { | |
428 | |
429 std::cerr << "(force flag set -- deleting from all views)" << std::endl; | |
430 | |
431 for (std::set<View *>::iterator j = m_layerViewMap[layer].begin(); | |
432 j != m_layerViewMap[layer].end(); ++j) { | |
433 // don't use removeLayerFromView, as it issues a command | |
434 layer->setLayerDormant(*j, true); | |
435 (*j)->removeLayer(layer); | |
436 } | |
437 | |
438 m_layerViewMap.erase(layer); | |
439 | |
440 } else { | |
441 return; | |
442 } | |
443 } | |
444 | |
445 if (m_layers.find(layer) == m_layers.end()) { | |
446 std::cerr << "Document::deleteLayer: Layer " | |
447 << layer << " does not exist, or has already been deleted " | |
448 << "(this may not be as serious as it sounds)" << std::endl; | |
449 return; | |
450 } | |
451 | |
452 m_layers.erase(layer); | |
453 | |
454 releaseModel(layer->getModel()); | |
455 emit layerRemoved(layer); | |
456 emit layerAboutToBeDeleted(layer); | |
457 delete layer; | |
458 } | |
459 | |
460 void | |
461 Document::setModel(Layer *layer, Model *model) | |
462 { | |
463 if (model && | |
464 model != m_mainModel && | |
465 m_models.find(model) == m_models.end()) { | |
466 std::cerr << "ERROR: Document::setModel: Layer " << layer | |
467 << " is using unregistered model " << model | |
468 << ": register the layer's model before setting it!" | |
469 << std::endl; | |
470 return; | |
471 } | |
472 | |
473 if (layer->getModel()) { | |
474 if (layer->getModel() == model) { | |
475 std::cerr << "WARNING: Document::setModel: Layer is already set to this model" << std::endl; | |
476 return; | |
477 } | |
478 releaseModel(layer->getModel()); | |
479 } | |
480 | |
481 if (model && model != m_mainModel) { | |
482 m_models[model].refcount ++; | |
483 } | |
484 | |
485 LayerFactory::getInstance()->setModel(layer, model); | |
486 } | |
487 | |
488 void | |
489 Document::setChannel(Layer *layer, int channel) | |
490 { | |
491 LayerFactory::getInstance()->setChannel(layer, channel); | |
492 } | |
493 | |
494 void | |
495 Document::addLayerToView(View *view, Layer *layer) | |
496 { | |
497 Model *model = layer->getModel(); | |
498 if (!model) { | |
499 std::cerr << "Document::addLayerToView: Layer with no model being added to view: normally you want to set the model first" << std::endl; | |
500 } else { | |
501 if (model != m_mainModel && | |
502 m_models.find(model) == m_models.end()) { | |
503 std::cerr << "ERROR: Document::addLayerToView: Layer " << layer | |
504 << " has unregistered model " << model | |
505 << " -- register the layer's model before adding the layer!" << std::endl; | |
506 return; | |
507 } | |
508 } | |
509 | |
510 CommandHistory::getInstance()->addCommand | |
511 (new Document::AddLayerCommand(this, view, layer)); | |
512 } | |
513 | |
514 void | |
515 Document::removeLayerFromView(View *view, Layer *layer) | |
516 { | |
517 CommandHistory::getInstance()->addCommand | |
518 (new Document::RemoveLayerCommand(this, view, layer)); | |
519 } | |
520 | |
521 void | |
522 Document::addToLayerViewMap(Layer *layer, View *view) | |
523 { | |
524 bool firstView = (m_layerViewMap.find(layer) == m_layerViewMap.end() || | |
525 m_layerViewMap[layer].empty()); | |
526 | |
527 if (m_layerViewMap[layer].find(view) != | |
528 m_layerViewMap[layer].end()) { | |
529 std::cerr << "WARNING: Document::addToLayerViewMap:" | |
530 << " Layer " << layer << " -> view " << view << " already in" | |
531 << " layer view map -- internal inconsistency" << std::endl; | |
532 } | |
533 | |
534 m_layerViewMap[layer].insert(view); | |
535 | |
536 if (firstView) emit layerInAView(layer, true); | |
537 } | |
538 | |
539 void | |
540 Document::removeFromLayerViewMap(Layer *layer, View *view) | |
541 { | |
542 if (m_layerViewMap[layer].find(view) == | |
543 m_layerViewMap[layer].end()) { | |
544 std::cerr << "WARNING: Document::removeFromLayerViewMap:" | |
545 << " Layer " << layer << " -> view " << view << " not in" | |
546 << " layer view map -- internal inconsistency" << std::endl; | |
547 } | |
548 | |
549 m_layerViewMap[layer].erase(view); | |
550 | |
551 if (m_layerViewMap[layer].empty()) { | |
552 m_layerViewMap.erase(layer); | |
553 emit layerInAView(layer, false); | |
554 } | |
555 } | |
556 | |
557 QString | |
558 Document::getUniqueLayerName(QString candidate) | |
559 { | |
560 for (int count = 1; ; ++count) { | |
561 | |
562 QString adjusted = | |
563 (count > 1 ? QString("%1 <%2>").arg(candidate).arg(count) : | |
564 candidate); | |
565 | |
566 bool duplicate = false; | |
567 | |
568 for (LayerSet::iterator i = m_layers.begin(); i != m_layers.end(); ++i) { | |
569 if ((*i)->objectName() == adjusted) { | |
570 duplicate = true; | |
571 break; | |
572 } | |
573 } | |
574 | |
575 if (!duplicate) return adjusted; | |
576 } | |
577 } | |
578 | |
579 Document::AddLayerCommand::AddLayerCommand(Document *d, | |
580 View *view, | |
581 Layer *layer) : | |
582 m_d(d), | |
583 m_view(view), | |
584 m_layer(layer), | |
585 m_name(d->tr("Add %1 Layer").arg(layer->objectName())), | |
586 m_added(false) | |
587 { | |
588 } | |
589 | |
590 Document::AddLayerCommand::~AddLayerCommand() | |
591 { | |
592 // std::cerr << "Document::AddLayerCommand::~AddLayerCommand" << std::endl; | |
593 if (!m_added) { | |
594 m_d->deleteLayer(m_layer); | |
595 } | |
596 } | |
597 | |
598 void | |
599 Document::AddLayerCommand::execute() | |
600 { | |
601 for (int i = 0; i < m_view->getLayerCount(); ++i) { | |
602 if (m_view->getLayer(i) == m_layer) { | |
603 // already there | |
604 m_layer->setLayerDormant(m_view, false); | |
605 m_added = true; | |
606 return; | |
607 } | |
608 } | |
609 | |
610 m_view->addLayer(m_layer); | |
611 m_layer->setLayerDormant(m_view, false); | |
612 | |
613 m_d->addToLayerViewMap(m_layer, m_view); | |
614 m_added = true; | |
615 } | |
616 | |
617 void | |
618 Document::AddLayerCommand::unexecute() | |
619 { | |
620 m_view->removeLayer(m_layer); | |
621 m_layer->setLayerDormant(m_view, true); | |
622 | |
623 m_d->removeFromLayerViewMap(m_layer, m_view); | |
624 m_added = false; | |
625 } | |
626 | |
627 Document::RemoveLayerCommand::RemoveLayerCommand(Document *d, | |
628 View *view, | |
629 Layer *layer) : | |
630 m_d(d), | |
631 m_view(view), | |
632 m_layer(layer), | |
633 m_name(d->tr("Delete %1 Layer").arg(layer->objectName())), | |
634 m_added(true) | |
635 { | |
636 } | |
637 | |
638 Document::RemoveLayerCommand::~RemoveLayerCommand() | |
639 { | |
640 // std::cerr << "Document::RemoveLayerCommand::~RemoveLayerCommand" << std::endl; | |
641 if (!m_added) { | |
642 m_d->deleteLayer(m_layer); | |
643 } | |
644 } | |
645 | |
646 void | |
647 Document::RemoveLayerCommand::execute() | |
648 { | |
649 bool have = false; | |
650 for (int i = 0; i < m_view->getLayerCount(); ++i) { | |
651 if (m_view->getLayer(i) == m_layer) { | |
652 have = true; | |
653 break; | |
654 } | |
655 } | |
656 | |
657 if (!have) { // not there! | |
658 m_layer->setLayerDormant(m_view, true); | |
659 m_added = false; | |
660 return; | |
661 } | |
662 | |
663 m_view->removeLayer(m_layer); | |
664 m_layer->setLayerDormant(m_view, true); | |
665 | |
666 m_d->removeFromLayerViewMap(m_layer, m_view); | |
667 m_added = false; | |
668 } | |
669 | |
670 void | |
671 Document::RemoveLayerCommand::unexecute() | |
672 { | |
673 m_view->addLayer(m_layer); | |
674 m_layer->setLayerDormant(m_view, false); | |
675 | |
676 m_d->addToLayerViewMap(m_layer, m_view); | |
677 m_added = true; | |
678 } | |
679 | |
680 void | |
681 Document::toXml(QTextStream &out, QString indent, QString extraAttributes) const | |
682 { | |
683 out << indent + QString("<data%1%2>\n") | |
684 .arg(extraAttributes == "" ? "" : " ").arg(extraAttributes); | |
685 | |
686 if (m_mainModel) { | |
687 m_mainModel->toXml(out, indent + " ", "mainModel=\"true\""); | |
688 } | |
689 | |
690 for (ModelMap::const_iterator i = m_models.begin(); | |
691 i != m_models.end(); ++i) { | |
692 | |
693 i->first->toXml(out, indent + " "); | |
694 | |
695 const ModelRecord &rec = i->second; | |
696 | |
697 if (rec.source && rec.transform != "") { | |
698 | |
699 out << indent; | |
700 out << QString(" <derivation source=\"%1\" model=\"%2\" channel=\"%3\" transform=\"%4\"") | |
701 .arg(XmlExportable::getObjectExportId(rec.source)) | |
702 .arg(XmlExportable::getObjectExportId(i->first)) | |
703 .arg(rec.channel) | |
704 .arg(XmlExportable::encodeEntities(rec.transform)); | |
705 | |
706 if (rec.configurationXml != "") { | |
707 out << ">\n " + indent + rec.configurationXml | |
708 + "\n" + indent + " </derivation>\n"; | |
709 } else { | |
710 out << "/>\n"; | |
711 } | |
712 } | |
713 | |
714 //!!! We should probably own the PlayParameterRepository | |
715 PlayParameters *playParameters = | |
716 PlayParameterRepository::getInstance()->getPlayParameters(i->first); | |
717 if (playParameters) { | |
718 playParameters->toXml | |
719 (out, indent + " ", | |
720 QString("model=\"%1\"") | |
721 .arg(XmlExportable::getObjectExportId(i->first))); | |
722 } | |
723 } | |
724 | |
725 for (LayerSet::const_iterator i = m_layers.begin(); | |
726 i != m_layers.end(); ++i) { | |
727 | |
728 (*i)->toXml(out, indent + " "); | |
729 } | |
730 | |
731 out << indent + "</data>\n"; | |
732 } | |
733 | |
734 QString | |
735 Document::toXmlString(QString indent, QString extraAttributes) const | |
736 { | |
737 QString s; | |
738 | |
739 { | |
740 QTextStream out(&s); | |
741 toXml(out, indent, extraAttributes); | |
742 } | |
743 | |
744 return s; | |
745 } | |
746 |