annotate document/Document.cpp @ 45:6b6bca31ad53

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