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