annotate layer/LayerFactory.cpp @ 454:e2a40fdadd8c

Various fixes: * Fix handling of HTTP redirects (avoiding crashes... I hope) * Fix failure to delete FFT models when a feature extraction model transformer was abandoned (also a cause of crashes in the past) * Fix deadlock when said transform was abandoned before its source model was ready because the session was being cleared (and so the source model would never be ready)
author Chris Cannam
date Fri, 28 Nov 2008 13:36:13 +0000
parents 96e4d7b9e165
children 1fe7951a61e8
rev   line source
Chris@58 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@0 2
Chris@0 3 /*
Chris@59 4 Sonic Visualiser
Chris@59 5 An audio file viewer and annotation editor.
Chris@59 6 Centre for Digital Music, Queen Mary, University of London.
Chris@59 7 This file copyright 2006 Chris Cannam.
Chris@0 8
Chris@59 9 This program is free software; you can redistribute it and/or
Chris@59 10 modify it under the terms of the GNU General Public License as
Chris@59 11 published by the Free Software Foundation; either version 2 of the
Chris@59 12 License, or (at your option) any later version. See the file
Chris@59 13 COPYING included with this distribution for more information.
Chris@0 14 */
Chris@0 15
Chris@0 16 #include "LayerFactory.h"
Chris@0 17
Chris@0 18 #include "WaveformLayer.h"
Chris@0 19 #include "SpectrogramLayer.h"
Chris@0 20 #include "TimeRulerLayer.h"
Chris@0 21 #include "TimeInstantLayer.h"
Chris@0 22 #include "TimeValueLayer.h"
Chris@30 23 #include "NoteLayer.h"
Chris@411 24 #include "RegionLayer.h"
Chris@35 25 #include "TextLayer.h"
Chris@303 26 #include "ImageLayer.h"
Chris@0 27 #include "Colour3DPlotLayer.h"
Chris@133 28 #include "SpectrumLayer.h"
Chris@193 29 #include "SliceLayer.h"
Chris@193 30 #include "SliceableLayer.h"
Chris@0 31
Chris@360 32 #include "base/Clipboard.h"
Chris@360 33
Chris@128 34 #include "data/model/RangeSummarisableTimeValueModel.h"
Chris@128 35 #include "data/model/DenseTimeValueModel.h"
Chris@128 36 #include "data/model/SparseOneDimensionalModel.h"
Chris@128 37 #include "data/model/SparseTimeValueModel.h"
Chris@128 38 #include "data/model/NoteModel.h"
Chris@411 39 #include "data/model/RegionModel.h"
Chris@128 40 #include "data/model/TextModel.h"
Chris@303 41 #include "data/model/ImageModel.h"
Chris@128 42 #include "data/model/DenseThreeDimensionalModel.h"
Chris@156 43 #include "data/model/WaveFileModel.h"
Chris@156 44 #include "data/model/WritableWaveFileModel.h"
Chris@0 45
Chris@326 46 #include <QDomDocument>
Chris@326 47 #include <QDomElement>
Chris@326 48 #include <QDomNamedNodeMap>
Chris@326 49 #include <QDomAttr>
Chris@326 50
Chris@326 51 #include <QSettings>
Chris@326 52
Chris@0 53 LayerFactory *
Chris@0 54 LayerFactory::m_instance = new LayerFactory;
Chris@0 55
Chris@0 56 LayerFactory *
Chris@125 57 LayerFactory::getInstance()
Chris@0 58 {
Chris@0 59 return m_instance;
Chris@0 60 }
Chris@0 61
Chris@0 62 LayerFactory::~LayerFactory()
Chris@0 63 {
Chris@0 64 }
Chris@0 65
Chris@0 66 QString
Chris@0 67 LayerFactory::getLayerPresentationName(LayerType type)
Chris@0 68 {
Chris@0 69 switch (type) {
Chris@0 70 case Waveform: return Layer::tr("Waveform");
Chris@0 71 case Spectrogram: return Layer::tr("Spectrogram");
Chris@0 72 case TimeRuler: return Layer::tr("Ruler");
Chris@0 73 case TimeInstants: return Layer::tr("Time Instants");
Chris@0 74 case TimeValues: return Layer::tr("Time Values");
Chris@30 75 case Notes: return Layer::tr("Notes");
Chris@411 76 case Regions: return Layer::tr("Regions");
Chris@35 77 case Text: return Layer::tr("Text");
Chris@303 78 case Image: return Layer::tr("Images");
Chris@0 79 case Colour3DPlot: return Layer::tr("Colour 3D Plot");
Chris@133 80 case Spectrum: return Layer::tr("Spectrum");
Chris@193 81 case Slice: return Layer::tr("Time Slice");
Chris@0 82
Chris@0 83 case MelodicRangeSpectrogram:
Chris@0 84 // The user can change all the parameters of this after the
Chris@0 85 // fact -- there's nothing permanently melodic-range about it
Chris@0 86 // that should be encoded in its name
Chris@0 87 return Layer::tr("Spectrogram");
Chris@11 88
Chris@37 89 case PeakFrequencySpectrogram:
Chris@37 90 // likewise
Chris@37 91 return Layer::tr("Spectrogram");
Chris@37 92
Chris@11 93 default: break;
Chris@0 94 }
Chris@0 95
Chris@0 96 return Layer::tr("Layer");
Chris@0 97 }
Chris@0 98
Chris@193 99 bool
Chris@193 100 LayerFactory::isLayerSliceable(const Layer *layer)
Chris@193 101 {
Chris@193 102 if (dynamic_cast<const SliceableLayer *>(layer)) {
Chris@193 103 if (dynamic_cast<const SpectrogramLayer *>(layer)) {
Chris@193 104
Chris@193 105 //!!! We can create slices of spectrograms, but there's a
Chris@193 106 // problem managing the models. The source model for the
Chris@193 107 // slice layer has to be one of the spectrogram's FFT
Chris@193 108 // models -- that's fine, except that we can't store &
Chris@193 109 // recall the slice layer with a reference to that model
Chris@193 110 // because the model is internal to the spectrogram layer
Chris@193 111 // and the document has no record of it. We would need
Chris@193 112 // some other way of managing models that are used in this
Chris@193 113 // way. For the moment we just don't allow slices of
Chris@193 114 // spectrograms -- and provide a spectrum layer for this
Chris@193 115 // instead.
Chris@193 116 //
Chris@193 117 // This business needs a bit more thought -- either come
Chris@193 118 // up with a sensible way to deal with that stuff, or
Chris@193 119 // simplify the existing slice layer logic so that it
Chris@193 120 // doesn't have to deal with models disappearing on it at
Chris@193 121 // all (and use the normal Document setModel mechanism to
Chris@193 122 // set its sliceable model instead of the fancy pants
Chris@193 123 // nonsense it's doing at the moment).
Chris@193 124
Chris@193 125 return false;
Chris@193 126 }
Chris@193 127 return true;
Chris@193 128 }
Chris@193 129 return false;
Chris@193 130 }
Chris@193 131
Chris@0 132 LayerFactory::LayerTypeSet
Chris@0 133 LayerFactory::getValidLayerTypes(Model *model)
Chris@0 134 {
Chris@0 135 LayerTypeSet types;
Chris@0 136
Chris@0 137 if (dynamic_cast<DenseThreeDimensionalModel *>(model)) {
Chris@0 138 types.insert(Colour3DPlot);
Chris@193 139 types.insert(Slice);
Chris@193 140 }
Chris@193 141
Chris@193 142 if (dynamic_cast<RangeSummarisableTimeValueModel *>(model)) {
Chris@193 143 types.insert(Waveform);
Chris@0 144 }
Chris@0 145
Chris@0 146 if (dynamic_cast<DenseTimeValueModel *>(model)) {
Chris@0 147 types.insert(Spectrogram);
Chris@0 148 types.insert(MelodicRangeSpectrogram);
Chris@37 149 types.insert(PeakFrequencySpectrogram);
Chris@0 150 }
Chris@0 151
Chris@0 152 if (dynamic_cast<SparseOneDimensionalModel *>(model)) {
Chris@0 153 types.insert(TimeInstants);
Chris@0 154 }
Chris@0 155
Chris@0 156 if (dynamic_cast<SparseTimeValueModel *>(model)) {
Chris@0 157 types.insert(TimeValues);
Chris@411 158 }
Chris@411 159
Chris@35 160 if (dynamic_cast<NoteModel *>(model)) {
Chris@35 161 types.insert(Notes);
Chris@0 162 }
Chris@0 163
Chris@411 164 if (dynamic_cast<RegionModel *>(model)) {
Chris@411 165 types.insert(Regions);
Chris@411 166 }
Chris@411 167
Chris@35 168 if (dynamic_cast<TextModel *>(model)) {
Chris@35 169 types.insert(Text);
Chris@30 170 }
Chris@30 171
Chris@303 172 if (dynamic_cast<ImageModel *>(model)) {
Chris@303 173 types.insert(Image);
Chris@303 174 }
Chris@303 175
Chris@133 176 if (dynamic_cast<DenseTimeValueModel *>(model)) {
Chris@133 177 types.insert(Spectrum);
Chris@133 178 }
Chris@133 179
Chris@0 180 // We don't count TimeRuler here as it doesn't actually display
Chris@0 181 // the data, although it can be backed by any model
Chris@0 182
Chris@0 183 return types;
Chris@0 184 }
Chris@0 185
Chris@17 186 LayerFactory::LayerTypeSet
Chris@17 187 LayerFactory::getValidEmptyLayerTypes()
Chris@17 188 {
Chris@17 189 LayerTypeSet types;
Chris@17 190 types.insert(TimeInstants);
Chris@17 191 types.insert(TimeValues);
Chris@30 192 types.insert(Notes);
Chris@411 193 types.insert(Regions);
Chris@35 194 types.insert(Text);
Chris@303 195 types.insert(Image);
Chris@17 196 //!!! and in principle Colour3DPlot -- now that's a challenge
Chris@17 197 return types;
Chris@17 198 }
Chris@17 199
Chris@0 200 LayerFactory::LayerType
Chris@6 201 LayerFactory::getLayerType(const Layer *layer)
Chris@0 202 {
Chris@6 203 if (dynamic_cast<const WaveformLayer *>(layer)) return Waveform;
Chris@6 204 if (dynamic_cast<const SpectrogramLayer *>(layer)) return Spectrogram;
Chris@6 205 if (dynamic_cast<const TimeRulerLayer *>(layer)) return TimeRuler;
Chris@6 206 if (dynamic_cast<const TimeInstantLayer *>(layer)) return TimeInstants;
Chris@6 207 if (dynamic_cast<const TimeValueLayer *>(layer)) return TimeValues;
Chris@30 208 if (dynamic_cast<const NoteLayer *>(layer)) return Notes;
Chris@411 209 if (dynamic_cast<const RegionLayer *>(layer)) return Regions;
Chris@35 210 if (dynamic_cast<const TextLayer *>(layer)) return Text;
Chris@303 211 if (dynamic_cast<const ImageLayer *>(layer)) return Image;
Chris@6 212 if (dynamic_cast<const Colour3DPlotLayer *>(layer)) return Colour3DPlot;
Chris@133 213 if (dynamic_cast<const SpectrumLayer *>(layer)) return Spectrum;
Chris@193 214 if (dynamic_cast<const SliceLayer *>(layer)) return Slice;
Chris@6 215 return UnknownLayer;
Chris@6 216 }
Chris@6 217
Chris@6 218 QString
Chris@17 219 LayerFactory::getLayerIconName(LayerType type)
Chris@17 220 {
Chris@17 221 switch (type) {
Chris@17 222 case Waveform: return "waveform";
Chris@17 223 case Spectrogram: return "spectrogram";
Chris@17 224 case TimeRuler: return "timeruler";
Chris@17 225 case TimeInstants: return "instants";
Chris@17 226 case TimeValues: return "values";
Chris@30 227 case Notes: return "notes";
Chris@411 228 case Regions: return "regions";
Chris@35 229 case Text: return "text";
Chris@303 230 case Image: return "image";
Chris@17 231 case Colour3DPlot: return "colour3d";
Chris@133 232 case Spectrum: return "spectrum";
Chris@193 233 case Slice: return "spectrum";
Chris@326 234 case MelodicRangeSpectrogram: return "spectrogram";
Chris@326 235 case PeakFrequencySpectrogram: return "spectrogram";
Chris@17 236 default: return "unknown";
Chris@17 237 }
Chris@17 238 }
Chris@17 239
Chris@17 240 QString
Chris@6 241 LayerFactory::getLayerTypeName(LayerType type)
Chris@6 242 {
Chris@6 243 switch (type) {
Chris@6 244 case Waveform: return "waveform";
Chris@6 245 case Spectrogram: return "spectrogram";
Chris@6 246 case TimeRuler: return "timeruler";
Chris@6 247 case TimeInstants: return "timeinstants";
Chris@6 248 case TimeValues: return "timevalues";
Chris@30 249 case Notes: return "notes";
Chris@411 250 case Regions: return "regions";
Chris@35 251 case Text: return "text";
Chris@303 252 case Image: return "image";
Chris@6 253 case Colour3DPlot: return "colour3dplot";
Chris@133 254 case Spectrum: return "spectrum";
Chris@193 255 case Slice: return "slice";
Chris@326 256 case MelodicRangeSpectrogram: return "melodicrange";
Chris@326 257 case PeakFrequencySpectrogram: return "peakfrequency";
Chris@6 258 default: return "unknown";
Chris@6 259 }
Chris@6 260 }
Chris@6 261
Chris@6 262 LayerFactory::LayerType
Chris@6 263 LayerFactory::getLayerTypeForName(QString name)
Chris@6 264 {
Chris@6 265 if (name == "waveform") return Waveform;
Chris@6 266 if (name == "spectrogram") return Spectrogram;
Chris@6 267 if (name == "timeruler") return TimeRuler;
Chris@6 268 if (name == "timeinstants") return TimeInstants;
Chris@6 269 if (name == "timevalues") return TimeValues;
Chris@30 270 if (name == "notes") return Notes;
Chris@411 271 if (name == "regions") return Regions;
Chris@35 272 if (name == "text") return Text;
Chris@303 273 if (name == "image") return Image;
Chris@6 274 if (name == "colour3dplot") return Colour3DPlot;
Chris@133 275 if (name == "spectrum") return Spectrum;
Chris@193 276 if (name == "slice") return Slice;
Chris@0 277 return UnknownLayer;
Chris@0 278 }
Chris@0 279
Chris@0 280 void
Chris@0 281 LayerFactory::setModel(Layer *layer, Model *model)
Chris@0 282 {
Chris@156 283 // if (trySetModel<WaveformLayer, RangeSummarisableTimeValueModel>(layer, model))
Chris@156 284 // return;
Chris@156 285
Chris@156 286 if (trySetModel<WaveformLayer, WaveFileModel>(layer, model))
Chris@156 287 return;
Chris@156 288
Chris@156 289 if (trySetModel<WaveformLayer, WritableWaveFileModel>(layer, model))
Chris@0 290 return;
Chris@0 291
Chris@0 292 if (trySetModel<SpectrogramLayer, DenseTimeValueModel>(layer, model))
Chris@0 293 return;
Chris@0 294
Chris@0 295 if (trySetModel<TimeRulerLayer, Model>(layer, model))
Chris@0 296 return;
Chris@0 297
Chris@0 298 if (trySetModel<TimeInstantLayer, SparseOneDimensionalModel>(layer, model))
Chris@0 299 return;
Chris@0 300
Chris@0 301 if (trySetModel<TimeValueLayer, SparseTimeValueModel>(layer, model))
Chris@0 302 return;
Chris@0 303
Chris@30 304 if (trySetModel<NoteLayer, NoteModel>(layer, model))
Chris@30 305 return;
Chris@30 306
Chris@411 307 if (trySetModel<RegionLayer, RegionModel>(layer, model))
Chris@411 308 return;
Chris@411 309
Chris@35 310 if (trySetModel<TextLayer, TextModel>(layer, model))
Chris@35 311 return;
Chris@35 312
Chris@303 313 if (trySetModel<ImageLayer, ImageModel>(layer, model))
Chris@303 314 return;
Chris@303 315
Chris@0 316 if (trySetModel<Colour3DPlotLayer, DenseThreeDimensionalModel>(layer, model))
Chris@0 317 return;
Chris@0 318
Chris@0 319 if (trySetModel<SpectrogramLayer, DenseTimeValueModel>(layer, model))
Chris@0 320 return;
Chris@133 321
Chris@133 322 if (trySetModel<SpectrumLayer, DenseTimeValueModel>(layer, model))
Chris@133 323 return;
Chris@193 324
Chris@193 325 // if (trySetModel<SliceLayer, DenseThreeDimensionalModel>(layer, model))
Chris@193 326 // return;
Chris@0 327 }
Chris@0 328
Chris@17 329 Model *
Chris@17 330 LayerFactory::createEmptyModel(LayerType layerType, Model *baseModel)
Chris@17 331 {
Chris@17 332 if (layerType == TimeInstants) {
Chris@17 333 return new SparseOneDimensionalModel(baseModel->getSampleRate(), 1);
Chris@17 334 } else if (layerType == TimeValues) {
Chris@245 335 return new SparseTimeValueModel(baseModel->getSampleRate(), 1, true);
Chris@30 336 } else if (layerType == Notes) {
Chris@245 337 return new NoteModel(baseModel->getSampleRate(), 1, true);
Chris@411 338 } else if (layerType == Regions) {
Chris@411 339 return new RegionModel(baseModel->getSampleRate(), 1, true);
Chris@35 340 } else if (layerType == Text) {
Chris@35 341 return new TextModel(baseModel->getSampleRate(), 1, true);
Chris@303 342 } else if (layerType == Image) {
Chris@303 343 return new ImageModel(baseModel->getSampleRate(), 1, true);
Chris@17 344 } else {
Chris@17 345 return 0;
Chris@17 346 }
Chris@17 347 }
Chris@17 348
Chris@53 349 int
Chris@53 350 LayerFactory::getChannel(Layer *layer)
Chris@53 351 {
Chris@53 352 if (dynamic_cast<WaveformLayer *>(layer)) {
Chris@53 353 return dynamic_cast<WaveformLayer *>(layer)->getChannel();
Chris@53 354 }
Chris@53 355 if (dynamic_cast<SpectrogramLayer *>(layer)) {
Chris@53 356 return dynamic_cast<SpectrogramLayer *>(layer)->getChannel();
Chris@53 357 }
Chris@53 358 return -1;
Chris@53 359 }
Chris@53 360
Chris@53 361 void
Chris@53 362 LayerFactory::setChannel(Layer *layer, int channel)
Chris@53 363 {
Chris@53 364 if (dynamic_cast<WaveformLayer *>(layer)) {
Chris@53 365 dynamic_cast<WaveformLayer *>(layer)->setChannel(channel);
Chris@53 366 return;
Chris@53 367 }
Chris@53 368 if (dynamic_cast<SpectrogramLayer *>(layer)) {
Chris@53 369 dynamic_cast<SpectrogramLayer *>(layer)->setChannel(channel);
Chris@53 370 return;
Chris@53 371 }
Chris@349 372 if (dynamic_cast<SpectrumLayer *>(layer)) {
Chris@349 373 dynamic_cast<SpectrumLayer *>(layer)->setChannel(channel);
Chris@349 374 return;
Chris@349 375 }
Chris@53 376 }
Chris@53 377
Chris@0 378 Layer *
Chris@53 379 LayerFactory::createLayer(LayerType type)
Chris@0 380 {
Chris@0 381 Layer *layer = 0;
Chris@0 382
Chris@0 383 switch (type) {
Chris@0 384
Chris@0 385 case Waveform:
Chris@44 386 layer = new WaveformLayer;
Chris@0 387 break;
Chris@0 388
Chris@0 389 case Spectrogram:
Chris@44 390 layer = new SpectrogramLayer;
Chris@0 391 break;
Chris@0 392
Chris@0 393 case TimeRuler:
Chris@44 394 layer = new TimeRulerLayer;
Chris@0 395 break;
Chris@0 396
Chris@0 397 case TimeInstants:
Chris@44 398 layer = new TimeInstantLayer;
Chris@0 399 break;
Chris@0 400
Chris@0 401 case TimeValues:
Chris@44 402 layer = new TimeValueLayer;
Chris@0 403 break;
Chris@0 404
Chris@30 405 case Notes:
Chris@44 406 layer = new NoteLayer;
Chris@30 407 break;
Chris@30 408
Chris@411 409 case Regions:
Chris@411 410 layer = new RegionLayer;
Chris@411 411 break;
Chris@411 412
Chris@35 413 case Text:
Chris@44 414 layer = new TextLayer;
Chris@35 415 break;
Chris@35 416
Chris@303 417 case Image:
Chris@303 418 layer = new ImageLayer;
Chris@303 419 break;
Chris@303 420
Chris@0 421 case Colour3DPlot:
Chris@44 422 layer = new Colour3DPlotLayer;
Chris@0 423 break;
Chris@0 424
Chris@133 425 case Spectrum:
Chris@133 426 layer = new SpectrumLayer;
Chris@133 427 break;
Chris@133 428
Chris@193 429 case Slice:
Chris@193 430 layer = new SliceLayer;
Chris@193 431 break;
Chris@193 432
Chris@0 433 case MelodicRangeSpectrogram:
Chris@44 434 layer = new SpectrogramLayer(SpectrogramLayer::MelodicRange);
Chris@0 435 break;
Chris@11 436
Chris@37 437 case PeakFrequencySpectrogram:
Chris@44 438 layer = new SpectrogramLayer(SpectrogramLayer::MelodicPeaks);
Chris@37 439 break;
Chris@37 440
Chris@11 441 default: break;
Chris@0 442 }
Chris@0 443
Chris@0 444 if (!layer) {
Chris@0 445 std::cerr << "LayerFactory::createLayer: Unknown layer type "
Chris@0 446 << type << std::endl;
Chris@0 447 } else {
Chris@336 448 // std::cerr << "LayerFactory::createLayer: Setting object name "
Chris@336 449 // << getLayerPresentationName(type).toStdString() << " on " << layer << std::endl;
Chris@0 450 layer->setObjectName(getLayerPresentationName(type));
Chris@326 451 setLayerDefaultProperties(type, layer);
Chris@0 452 }
Chris@0 453
Chris@0 454 return layer;
Chris@0 455 }
Chris@0 456
Chris@326 457 void
Chris@326 458 LayerFactory::setLayerDefaultProperties(LayerType type, Layer *layer)
Chris@326 459 {
Chris@336 460 // std::cerr << "LayerFactory::setLayerDefaultProperties: type " << type << " (name \"" << getLayerTypeName(type).toStdString() << "\")" << std::endl;
Chris@327 461
Chris@326 462 QSettings settings;
Chris@326 463 settings.beginGroup("LayerDefaults");
Chris@326 464 QString defaults = settings.value(getLayerTypeName(type), "").toString();
Chris@326 465 if (defaults == "") return;
Chris@326 466
Chris@336 467 // std::cerr << "defaults=\"" << defaults.toStdString() << "\"" << std::endl;
Chris@327 468
Chris@326 469 QString xml = layer->toXmlString();
Chris@326 470 QDomDocument docOld, docNew;
Chris@326 471
Chris@326 472 if (docOld.setContent(xml, false) &&
Chris@326 473 docNew.setContent(defaults, false)) {
Chris@326 474
Chris@326 475 QXmlAttributes attrs;
Chris@326 476
Chris@326 477 QDomElement layerElt = docNew.firstChildElement("layer");
Chris@326 478 QDomNamedNodeMap attrNodes = layerElt.attributes();
Chris@326 479
Chris@326 480 for (unsigned int i = 0; i < attrNodes.length(); ++i) {
Chris@326 481 QDomAttr attr = attrNodes.item(i).toAttr();
Chris@326 482 if (attr.isNull()) continue;
Chris@336 483 // std::cerr << "append \"" << attr.name().toStdString()
Chris@336 484 // << "\" -> \"" << attr.value().toStdString() << "\""
Chris@336 485 // << std::endl;
Chris@326 486 attrs.append(attr.name(), "", "", attr.value());
Chris@326 487 }
Chris@326 488
Chris@326 489 layerElt = docOld.firstChildElement("layer");
Chris@326 490 attrNodes = layerElt.attributes();
Chris@326 491 for (unsigned int i = 0; i < attrNodes.length(); ++i) {
Chris@326 492 QDomAttr attr = attrNodes.item(i).toAttr();
Chris@326 493 if (attr.isNull()) continue;
Chris@326 494 if (attrs.value(attr.name()) == "") {
Chris@336 495 // std::cerr << "append \"" << attr.name().toStdString()
Chris@336 496 // << "\" -> \"" << attr.value().toStdString() << "\""
Chris@336 497 // << std::endl;
Chris@326 498 attrs.append(attr.name(), "", "", attr.value());
Chris@326 499 }
Chris@326 500 }
Chris@326 501
Chris@326 502 layer->setProperties(attrs);
Chris@326 503 }
Chris@326 504
Chris@326 505 settings.endGroup();
Chris@326 506 }
Chris@326 507
Chris@360 508 LayerFactory::LayerType
Chris@360 509 LayerFactory::getLayerTypeForClipboardContents(const Clipboard &clip)
Chris@360 510 {
Chris@360 511 const Clipboard::PointList &contents = clip.getPoints();
Chris@360 512
Chris@360 513 bool haveFrame = false;
Chris@360 514 bool haveValue = false;
Chris@360 515 bool haveDuration = false;
Chris@411 516 bool haveLevel = false;
Chris@360 517
Chris@360 518 for (Clipboard::PointList::const_iterator i = contents.begin();
Chris@360 519 i != contents.end(); ++i) {
Chris@360 520 if (i->haveFrame()) haveFrame = true;
Chris@360 521 if (i->haveValue()) haveValue = true;
Chris@360 522 if (i->haveDuration()) haveDuration = true;
Chris@411 523 if (i->haveLevel()) haveLevel = true;
Chris@360 524 }
Chris@360 525
Chris@411 526 if (haveFrame && haveValue && haveDuration && haveLevel) return Notes;
Chris@411 527 if (haveFrame && haveValue && haveDuration) return Regions;
Chris@360 528 if (haveFrame && haveValue) return TimeValues;
Chris@360 529 return TimeInstants;
Chris@360 530 }
Chris@360 531