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