annotate document/Document.cpp @ 182:21a76c9ed5c3

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