annotate document/Document.cpp @ 35:06787742542a

* Add a bit of resistance to pane dragging so as to make it harder to inadvertently drag in the other axis from the one you intended
author Chris Cannam
date Fri, 22 Sep 2006 16:46:10 +0000
parents 56e1d4242bb4
children 6b6bca31ad53
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@0 236 if (model == oldMainModel) {
Chris@0 237 LayerFactory::getInstance()->setModel(layer, m_mainModel);
Chris@0 238 continue;
Chris@0 239 }
Chris@0 240
Chris@0 241 if (m_models.find(model) == m_models.end()) {
Chris@0 242 std::cerr << "WARNING: Document::setMainModel: Unknown model "
Chris@0 243 << model << " in layer " << layer << std::endl;
Chris@0 244 // get rid of this hideous degenerate
Chris@0 245 obsoleteLayers.push_back(layer);
Chris@0 246 continue;
Chris@0 247 }
Chris@0 248
Chris@0 249 if (m_models[model].source == oldMainModel) {
Chris@0 250
Chris@0 251 // This model was derived from the previous main
Chris@0 252 // model: regenerate it.
Chris@0 253
Chris@0 254 TransformName transform = m_models[model].transform;
Chris@27 255 PluginTransform::ExecutionContext context = m_models[model].context;
Chris@0 256
Chris@0 257 Model *replacementModel =
Chris@0 258 createModelForTransform(transform,
Chris@0 259 m_mainModel,
Chris@27 260 context,
Chris@0 261 m_models[model].configurationXml);
Chris@0 262
Chris@0 263 if (!replacementModel) {
Chris@0 264 std::cerr << "WARNING: Document::setMainModel: Failed to regenerate model for transform \""
Chris@0 265 << transform.toStdString() << "\"" << " in layer " << layer << std::endl;
Chris@0 266 if (failedTransforms.find(transform) == failedTransforms.end()) {
Chris@0 267 emit modelRegenerationFailed(layer->objectName(),
Chris@0 268 transform);
Chris@0 269 failedTransforms.insert(transform);
Chris@0 270 }
Chris@0 271 obsoleteLayers.push_back(layer);
Chris@0 272 } else {
Chris@0 273 setModel(layer, replacementModel);
Chris@0 274 }
Chris@0 275 }
Chris@0 276 }
Chris@0 277
Chris@0 278 for (size_t k = 0; k < obsoleteLayers.size(); ++k) {
Chris@0 279 deleteLayer(obsoleteLayers[k], true);
Chris@0 280 }
Chris@0 281
Chris@0 282 emit mainModelChanged(m_mainModel);
Chris@0 283
Chris@0 284 // we already emitted modelAboutToBeDeleted for this
Chris@0 285 delete oldMainModel;
Chris@0 286 }
Chris@0 287
Chris@0 288 void
Chris@0 289 Document::addDerivedModel(TransformName transform,
Chris@0 290 Model *inputModel,
Chris@27 291 const PluginTransform::ExecutionContext &context,
Chris@0 292 Model *outputModelToAdd,
Chris@0 293 QString configurationXml)
Chris@0 294 {
Chris@0 295 if (m_models.find(outputModelToAdd) != m_models.end()) {
Chris@0 296 std::cerr << "WARNING: Document::addDerivedModel: Model already added"
Chris@0 297 << std::endl;
Chris@0 298 return;
Chris@0 299 }
Chris@0 300
Chris@0 301 ModelRecord rec;
Chris@0 302 rec.source = inputModel;
Chris@0 303 rec.transform = transform;
Chris@27 304 rec.context = context;
Chris@0 305 rec.configurationXml = configurationXml;
Chris@0 306 rec.refcount = 0;
Chris@0 307
Chris@0 308 m_models[outputModelToAdd] = rec;
Chris@0 309
Chris@0 310 emit modelAdded(outputModelToAdd);
Chris@0 311 }
Chris@0 312
Chris@0 313
Chris@0 314 void
Chris@0 315 Document::addImportedModel(Model *model)
Chris@0 316 {
Chris@0 317 if (m_models.find(model) != m_models.end()) {
Chris@0 318 std::cerr << "WARNING: Document::addImportedModel: Model already added"
Chris@0 319 << std::endl;
Chris@0 320 return;
Chris@0 321 }
Chris@0 322
Chris@0 323 ModelRecord rec;
Chris@0 324 rec.source = 0;
Chris@0 325 rec.transform = "";
Chris@0 326 rec.refcount = 0;
Chris@0 327
Chris@0 328 m_models[model] = rec;
Chris@0 329
Chris@0 330 emit modelAdded(model);
Chris@0 331 }
Chris@0 332
Chris@0 333 Model *
Chris@0 334 Document::createModelForTransform(TransformName transform,
Chris@0 335 Model *inputModel,
Chris@27 336 const PluginTransform::ExecutionContext &context,
Chris@0 337 QString configurationXml)
Chris@0 338 {
Chris@0 339 Model *model = 0;
Chris@0 340
Chris@0 341 for (ModelMap::iterator i = m_models.begin(); i != m_models.end(); ++i) {
Chris@0 342 if (i->second.transform == transform &&
Chris@0 343 i->second.source == inputModel &&
Chris@27 344 i->second.context == context &&
Chris@0 345 i->second.configurationXml == configurationXml) {
Chris@0 346 return i->first;
Chris@0 347 }
Chris@0 348 }
Chris@0 349
Chris@0 350 model = TransformFactory::getInstance()->transform
Chris@27 351 (transform, inputModel, context, configurationXml);
Chris@0 352
Chris@0 353 if (!model) {
Chris@0 354 std::cerr << "WARNING: Document::createModelForTransform: no output model for transform " << transform.toStdString() << std::endl;
Chris@0 355 } else {
Chris@27 356 addDerivedModel(transform, inputModel, context, model, configurationXml);
Chris@0 357 }
Chris@0 358
Chris@0 359 return model;
Chris@0 360 }
Chris@0 361
Chris@0 362 void
Chris@0 363 Document::releaseModel(Model *model) // Will _not_ release main model!
Chris@0 364 {
Chris@0 365 if (model == 0) {
Chris@0 366 return;
Chris@0 367 }
Chris@0 368
Chris@0 369 if (model == m_mainModel) {
Chris@0 370 return;
Chris@0 371 }
Chris@0 372
Chris@0 373 bool toDelete = false;
Chris@0 374
Chris@0 375 if (m_models.find(model) != m_models.end()) {
Chris@0 376
Chris@0 377 if (m_models[model].refcount == 0) {
Chris@0 378 std::cerr << "WARNING: Document::releaseModel: model " << model
Chris@0 379 << " reference count is zero already!" << std::endl;
Chris@0 380 } else {
Chris@0 381 if (--m_models[model].refcount == 0) {
Chris@0 382 toDelete = true;
Chris@0 383 }
Chris@0 384 }
Chris@0 385 } else {
Chris@0 386 std::cerr << "WARNING: Document::releaseModel: Unfound model "
Chris@0 387 << model << std::endl;
Chris@0 388 toDelete = true;
Chris@0 389 }
Chris@0 390
Chris@0 391 if (toDelete) {
Chris@0 392
Chris@0 393 int sourceCount = 0;
Chris@0 394
Chris@0 395 for (ModelMap::iterator i = m_models.begin(); i != m_models.end(); ++i) {
Chris@0 396 if (i->second.source == model) {
Chris@0 397 ++sourceCount;
Chris@0 398 i->second.source = 0;
Chris@0 399 }
Chris@0 400 }
Chris@0 401
Chris@0 402 if (sourceCount > 0) {
Chris@0 403 std::cerr << "Document::releaseModel: Deleting model "
Chris@0 404 << model << " even though it is source for "
Chris@0 405 << sourceCount << " other derived model(s) -- resetting "
Chris@0 406 << "their source fields appropriately" << std::endl;
Chris@0 407 }
Chris@0 408
Chris@0 409 emit modelAboutToBeDeleted(model);
Chris@0 410 m_models.erase(model);
Chris@0 411 delete model;
Chris@0 412 }
Chris@0 413 }
Chris@0 414
Chris@0 415 void
Chris@0 416 Document::deleteLayer(Layer *layer, bool force)
Chris@0 417 {
Chris@0 418 if (m_layerViewMap.find(layer) != m_layerViewMap.end() &&
Chris@0 419 m_layerViewMap[layer].size() > 0) {
Chris@0 420
Chris@0 421 std::cerr << "WARNING: Document::deleteLayer: Layer "
Chris@0 422 << layer << " [" << layer->objectName().toStdString() << "]"
Chris@0 423 << " is still used in " << m_layerViewMap[layer].size()
Chris@0 424 << " views!" << std::endl;
Chris@0 425
Chris@0 426 if (force) {
Chris@0 427
Chris@0 428 std::cerr << "(force flag set -- deleting from all views)" << std::endl;
Chris@0 429
Chris@0 430 for (std::set<View *>::iterator j = m_layerViewMap[layer].begin();
Chris@0 431 j != m_layerViewMap[layer].end(); ++j) {
Chris@0 432 // don't use removeLayerFromView, as it issues a command
Chris@0 433 layer->setLayerDormant(*j, true);
Chris@0 434 (*j)->removeLayer(layer);
Chris@0 435 }
Chris@0 436
Chris@0 437 m_layerViewMap.erase(layer);
Chris@0 438
Chris@0 439 } else {
Chris@0 440 return;
Chris@0 441 }
Chris@0 442 }
Chris@0 443
Chris@0 444 if (m_layers.find(layer) == m_layers.end()) {
Chris@0 445 std::cerr << "Document::deleteLayer: Layer "
Chris@0 446 << layer << " does not exist, or has already been deleted "
Chris@0 447 << "(this may not be as serious as it sounds)" << std::endl;
Chris@0 448 return;
Chris@0 449 }
Chris@0 450
Chris@0 451 m_layers.erase(layer);
Chris@0 452
Chris@0 453 releaseModel(layer->getModel());
Chris@0 454 emit layerRemoved(layer);
Chris@0 455 emit layerAboutToBeDeleted(layer);
Chris@0 456 delete layer;
Chris@0 457 }
Chris@0 458
Chris@0 459 void
Chris@0 460 Document::setModel(Layer *layer, Model *model)
Chris@0 461 {
Chris@0 462 if (model &&
Chris@0 463 model != m_mainModel &&
Chris@0 464 m_models.find(model) == m_models.end()) {
Chris@0 465 std::cerr << "ERROR: Document::setModel: Layer " << layer
Chris@0 466 << " is using unregistered model " << model
Chris@0 467 << ": register the layer's model before setting it!"
Chris@0 468 << std::endl;
Chris@0 469 return;
Chris@0 470 }
Chris@0 471
Chris@0 472 if (layer->getModel()) {
Chris@0 473 if (layer->getModel() == model) {
Chris@0 474 std::cerr << "WARNING: Document::setModel: Layer is already set to this model" << std::endl;
Chris@0 475 return;
Chris@0 476 }
Chris@0 477 releaseModel(layer->getModel());
Chris@0 478 }
Chris@0 479
Chris@0 480 if (model && model != m_mainModel) {
Chris@0 481 m_models[model].refcount ++;
Chris@0 482 }
Chris@0 483
Chris@0 484 LayerFactory::getInstance()->setModel(layer, model);
Chris@0 485 }
Chris@0 486
Chris@0 487 void
Chris@0 488 Document::setChannel(Layer *layer, int channel)
Chris@0 489 {
Chris@0 490 LayerFactory::getInstance()->setChannel(layer, channel);
Chris@0 491 }
Chris@0 492
Chris@0 493 void
Chris@0 494 Document::addLayerToView(View *view, Layer *layer)
Chris@0 495 {
Chris@0 496 Model *model = layer->getModel();
Chris@0 497 if (!model) {
Chris@0 498 std::cerr << "Document::addLayerToView: Layer with no model being added to view: normally you want to set the model first" << std::endl;
Chris@0 499 } else {
Chris@0 500 if (model != m_mainModel &&
Chris@0 501 m_models.find(model) == m_models.end()) {
Chris@0 502 std::cerr << "ERROR: Document::addLayerToView: Layer " << layer
Chris@0 503 << " has unregistered model " << model
Chris@0 504 << " -- register the layer's model before adding the layer!" << std::endl;
Chris@0 505 return;
Chris@0 506 }
Chris@0 507 }
Chris@0 508
Chris@0 509 CommandHistory::getInstance()->addCommand
Chris@0 510 (new Document::AddLayerCommand(this, view, layer));
Chris@0 511 }
Chris@0 512
Chris@0 513 void
Chris@0 514 Document::removeLayerFromView(View *view, Layer *layer)
Chris@0 515 {
Chris@0 516 CommandHistory::getInstance()->addCommand
Chris@0 517 (new Document::RemoveLayerCommand(this, view, layer));
Chris@0 518 }
Chris@0 519
Chris@0 520 void
Chris@0 521 Document::addToLayerViewMap(Layer *layer, View *view)
Chris@0 522 {
Chris@0 523 bool firstView = (m_layerViewMap.find(layer) == m_layerViewMap.end() ||
Chris@0 524 m_layerViewMap[layer].empty());
Chris@0 525
Chris@0 526 if (m_layerViewMap[layer].find(view) !=
Chris@0 527 m_layerViewMap[layer].end()) {
Chris@0 528 std::cerr << "WARNING: Document::addToLayerViewMap:"
Chris@0 529 << " Layer " << layer << " -> view " << view << " already in"
Chris@0 530 << " layer view map -- internal inconsistency" << std::endl;
Chris@0 531 }
Chris@0 532
Chris@0 533 m_layerViewMap[layer].insert(view);
Chris@0 534
Chris@0 535 if (firstView) emit layerInAView(layer, true);
Chris@0 536 }
Chris@0 537
Chris@0 538 void
Chris@0 539 Document::removeFromLayerViewMap(Layer *layer, View *view)
Chris@0 540 {
Chris@0 541 if (m_layerViewMap[layer].find(view) ==
Chris@0 542 m_layerViewMap[layer].end()) {
Chris@0 543 std::cerr << "WARNING: Document::removeFromLayerViewMap:"
Chris@0 544 << " Layer " << layer << " -> view " << view << " not in"
Chris@0 545 << " layer view map -- internal inconsistency" << std::endl;
Chris@0 546 }
Chris@0 547
Chris@0 548 m_layerViewMap[layer].erase(view);
Chris@0 549
Chris@0 550 if (m_layerViewMap[layer].empty()) {
Chris@0 551 m_layerViewMap.erase(layer);
Chris@0 552 emit layerInAView(layer, false);
Chris@0 553 }
Chris@0 554 }
Chris@0 555
Chris@0 556 QString
Chris@0 557 Document::getUniqueLayerName(QString candidate)
Chris@0 558 {
Chris@0 559 for (int count = 1; ; ++count) {
Chris@0 560
Chris@0 561 QString adjusted =
Chris@0 562 (count > 1 ? QString("%1 <%2>").arg(candidate).arg(count) :
Chris@0 563 candidate);
Chris@0 564
Chris@0 565 bool duplicate = false;
Chris@0 566
Chris@0 567 for (LayerSet::iterator i = m_layers.begin(); i != m_layers.end(); ++i) {
Chris@0 568 if ((*i)->objectName() == adjusted) {
Chris@0 569 duplicate = true;
Chris@0 570 break;
Chris@0 571 }
Chris@0 572 }
Chris@0 573
Chris@0 574 if (!duplicate) return adjusted;
Chris@0 575 }
Chris@0 576 }
Chris@0 577
Chris@0 578 Document::AddLayerCommand::AddLayerCommand(Document *d,
Chris@0 579 View *view,
Chris@0 580 Layer *layer) :
Chris@0 581 m_d(d),
Chris@0 582 m_view(view),
Chris@0 583 m_layer(layer),
Chris@0 584 m_name(d->tr("Add %1 Layer").arg(layer->objectName())),
Chris@0 585 m_added(false)
Chris@0 586 {
Chris@0 587 }
Chris@0 588
Chris@0 589 Document::AddLayerCommand::~AddLayerCommand()
Chris@0 590 {
Chris@0 591 // std::cerr << "Document::AddLayerCommand::~AddLayerCommand" << std::endl;
Chris@0 592 if (!m_added) {
Chris@0 593 m_d->deleteLayer(m_layer);
Chris@0 594 }
Chris@0 595 }
Chris@0 596
Chris@0 597 void
Chris@0 598 Document::AddLayerCommand::execute()
Chris@0 599 {
Chris@0 600 for (int i = 0; i < m_view->getLayerCount(); ++i) {
Chris@0 601 if (m_view->getLayer(i) == m_layer) {
Chris@0 602 // already there
Chris@0 603 m_layer->setLayerDormant(m_view, false);
Chris@0 604 m_added = true;
Chris@0 605 return;
Chris@0 606 }
Chris@0 607 }
Chris@0 608
Chris@0 609 m_view->addLayer(m_layer);
Chris@0 610 m_layer->setLayerDormant(m_view, false);
Chris@0 611
Chris@0 612 m_d->addToLayerViewMap(m_layer, m_view);
Chris@0 613 m_added = true;
Chris@0 614 }
Chris@0 615
Chris@0 616 void
Chris@0 617 Document::AddLayerCommand::unexecute()
Chris@0 618 {
Chris@0 619 m_view->removeLayer(m_layer);
Chris@0 620 m_layer->setLayerDormant(m_view, true);
Chris@0 621
Chris@0 622 m_d->removeFromLayerViewMap(m_layer, m_view);
Chris@0 623 m_added = false;
Chris@0 624 }
Chris@0 625
Chris@0 626 Document::RemoveLayerCommand::RemoveLayerCommand(Document *d,
Chris@0 627 View *view,
Chris@0 628 Layer *layer) :
Chris@0 629 m_d(d),
Chris@0 630 m_view(view),
Chris@0 631 m_layer(layer),
Chris@0 632 m_name(d->tr("Delete %1 Layer").arg(layer->objectName())),
Chris@0 633 m_added(true)
Chris@0 634 {
Chris@0 635 }
Chris@0 636
Chris@0 637 Document::RemoveLayerCommand::~RemoveLayerCommand()
Chris@0 638 {
Chris@0 639 // std::cerr << "Document::RemoveLayerCommand::~RemoveLayerCommand" << std::endl;
Chris@0 640 if (!m_added) {
Chris@0 641 m_d->deleteLayer(m_layer);
Chris@0 642 }
Chris@0 643 }
Chris@0 644
Chris@0 645 void
Chris@0 646 Document::RemoveLayerCommand::execute()
Chris@0 647 {
Chris@0 648 bool have = false;
Chris@0 649 for (int i = 0; i < m_view->getLayerCount(); ++i) {
Chris@0 650 if (m_view->getLayer(i) == m_layer) {
Chris@0 651 have = true;
Chris@0 652 break;
Chris@0 653 }
Chris@0 654 }
Chris@0 655
Chris@0 656 if (!have) { // not there!
Chris@0 657 m_layer->setLayerDormant(m_view, true);
Chris@0 658 m_added = false;
Chris@0 659 return;
Chris@0 660 }
Chris@0 661
Chris@0 662 m_view->removeLayer(m_layer);
Chris@0 663 m_layer->setLayerDormant(m_view, true);
Chris@0 664
Chris@0 665 m_d->removeFromLayerViewMap(m_layer, m_view);
Chris@0 666 m_added = false;
Chris@0 667 }
Chris@0 668
Chris@0 669 void
Chris@0 670 Document::RemoveLayerCommand::unexecute()
Chris@0 671 {
Chris@0 672 m_view->addLayer(m_layer);
Chris@0 673 m_layer->setLayerDormant(m_view, false);
Chris@0 674
Chris@0 675 m_d->addToLayerViewMap(m_layer, m_view);
Chris@0 676 m_added = true;
Chris@0 677 }
Chris@0 678
Chris@0 679 void
Chris@0 680 Document::toXml(QTextStream &out, QString indent, QString extraAttributes) const
Chris@0 681 {
Chris@0 682 out << indent + QString("<data%1%2>\n")
Chris@0 683 .arg(extraAttributes == "" ? "" : " ").arg(extraAttributes);
Chris@0 684
Chris@0 685 if (m_mainModel) {
Chris@0 686 m_mainModel->toXml(out, indent + " ", "mainModel=\"true\"");
Chris@0 687 }
Chris@0 688
Chris@0 689 for (ModelMap::const_iterator i = m_models.begin();
Chris@0 690 i != m_models.end(); ++i) {
Chris@0 691
Chris@0 692 i->first->toXml(out, indent + " ");
Chris@0 693
Chris@0 694 const ModelRecord &rec = i->second;
Chris@0 695
Chris@0 696 if (rec.source && rec.transform != "") {
Chris@0 697
Chris@27 698 //!!! stream the rest of the execution context in both directions (i.e. not just channel)
Chris@27 699
Chris@0 700 out << indent;
Chris@30 701 out << QString(" <derivation source=\"%1\" model=\"%2\" channel=\"%3\" domain=\"%4\" stepSize=\"%5\" blockSize=\"%6\" windowType=\"%7\" transform=\"%8\"")
Chris@0 702 .arg(XmlExportable::getObjectExportId(rec.source))
Chris@0 703 .arg(XmlExportable::getObjectExportId(i->first))
Chris@27 704 .arg(rec.context.channel)
Chris@30 705 .arg(rec.context.domain)
Chris@30 706 .arg(rec.context.stepSize)
Chris@30 707 .arg(rec.context.blockSize)
Chris@30 708 .arg(int(rec.context.windowType))
Chris@0 709 .arg(XmlExportable::encodeEntities(rec.transform));
Chris@0 710
Chris@0 711 if (rec.configurationXml != "") {
Chris@0 712 out << ">\n " + indent + rec.configurationXml
Chris@0 713 + "\n" + indent + " </derivation>\n";
Chris@0 714 } else {
Chris@0 715 out << "/>\n";
Chris@0 716 }
Chris@0 717 }
Chris@0 718
Chris@0 719 //!!! We should probably own the PlayParameterRepository
Chris@0 720 PlayParameters *playParameters =
Chris@0 721 PlayParameterRepository::getInstance()->getPlayParameters(i->first);
Chris@0 722 if (playParameters) {
Chris@0 723 playParameters->toXml
Chris@0 724 (out, indent + " ",
Chris@0 725 QString("model=\"%1\"")
Chris@0 726 .arg(XmlExportable::getObjectExportId(i->first)));
Chris@0 727 }
Chris@0 728 }
Chris@0 729
Chris@0 730 for (LayerSet::const_iterator i = m_layers.begin();
Chris@0 731 i != m_layers.end(); ++i) {
Chris@0 732
Chris@0 733 (*i)->toXml(out, indent + " ");
Chris@0 734 }
Chris@0 735
Chris@0 736 out << indent + "</data>\n";
Chris@0 737 }
Chris@0 738
Chris@0 739 QString
Chris@0 740 Document::toXmlString(QString indent, QString extraAttributes) const
Chris@0 741 {
Chris@0 742 QString s;
Chris@0 743
Chris@0 744 {
Chris@0 745 QTextStream out(&s);
Chris@0 746 toXml(out, indent, extraAttributes);
Chris@0 747 }
Chris@0 748
Chris@0 749 return s;
Chris@0 750 }
Chris@0 751