annotate document/Document.cpp @ 78:9918c8a3f904

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