annotate layer/LayerFactory.cpp @ 1554:a0b2f3b4dd2f spectrogram-export

Start work on spectrogram export code
author Chris Cannam
date Mon, 06 Jan 2020 14:46:25 +0000
parents 2e94c268f7a0
children 1acd7be4df9a
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"
matthiasm@621 24 #include "FlexiNoteLayer.h"
Chris@411 25 #include "RegionLayer.h"
Chris@1518 26 #include "BoxLayer.h"
Chris@35 27 #include "TextLayer.h"
Chris@303 28 #include "ImageLayer.h"
Chris@0 29 #include "Colour3DPlotLayer.h"
Chris@133 30 #include "SpectrumLayer.h"
Chris@193 31 #include "SliceLayer.h"
Chris@193 32 #include "SliceableLayer.h"
Chris@0 33
Chris@360 34 #include "base/Clipboard.h"
Chris@360 35
Chris@128 36 #include "data/model/RangeSummarisableTimeValueModel.h"
Chris@128 37 #include "data/model/DenseTimeValueModel.h"
Chris@128 38 #include "data/model/SparseOneDimensionalModel.h"
Chris@128 39 #include "data/model/SparseTimeValueModel.h"
Chris@128 40 #include "data/model/NoteModel.h"
Chris@411 41 #include "data/model/RegionModel.h"
Chris@1518 42 #include "data/model/BoxModel.h"
Chris@128 43 #include "data/model/TextModel.h"
Chris@303 44 #include "data/model/ImageModel.h"
Chris@128 45 #include "data/model/DenseThreeDimensionalModel.h"
Chris@156 46 #include "data/model/WaveFileModel.h"
Chris@156 47 #include "data/model/WritableWaveFileModel.h"
Chris@0 48
Chris@326 49 #include <QDomDocument>
Chris@326 50 #include <QDomElement>
Chris@326 51 #include <QDomNamedNodeMap>
Chris@326 52 #include <QDomAttr>
Chris@326 53
Chris@326 54 #include <QSettings>
Chris@326 55
Chris@0 56 LayerFactory *
Chris@0 57 LayerFactory::m_instance = new LayerFactory;
Chris@0 58
Chris@0 59 LayerFactory *
Chris@125 60 LayerFactory::getInstance()
Chris@0 61 {
Chris@0 62 return m_instance;
Chris@0 63 }
Chris@0 64
Chris@0 65 LayerFactory::~LayerFactory()
Chris@0 66 {
Chris@0 67 }
Chris@0 68
Chris@0 69 QString
Chris@0 70 LayerFactory::getLayerPresentationName(LayerType type)
Chris@0 71 {
Chris@0 72 switch (type) {
Chris@0 73 case Waveform: return Layer::tr("Waveform");
Chris@0 74 case Spectrogram: return Layer::tr("Spectrogram");
Chris@0 75 case TimeRuler: return Layer::tr("Ruler");
Chris@0 76 case TimeInstants: return Layer::tr("Time Instants");
Chris@0 77 case TimeValues: return Layer::tr("Time Values");
Chris@30 78 case Notes: return Layer::tr("Notes");
gyorgyf@625 79 case FlexiNotes: return Layer::tr("Flexible Notes");
Chris@411 80 case Regions: return Layer::tr("Regions");
Chris@1518 81 case Boxes: return Layer::tr("Boxes");
Chris@35 82 case Text: return Layer::tr("Text");
Chris@303 83 case Image: return Layer::tr("Images");
Chris@0 84 case Colour3DPlot: return Layer::tr("Colour 3D Plot");
Chris@133 85 case Spectrum: return Layer::tr("Spectrum");
Chris@193 86 case Slice: return Layer::tr("Time Slice");
Chris@0 87
Chris@0 88 case MelodicRangeSpectrogram:
Chris@1266 89 // The user can change all the parameters of this after the
Chris@1266 90 // fact -- there's nothing permanently melodic-range about it
Chris@1266 91 // that should be encoded in its name
Chris@1266 92 return Layer::tr("Spectrogram");
Chris@11 93
Chris@37 94 case PeakFrequencySpectrogram:
Chris@1266 95 // likewise
Chris@1266 96 return Layer::tr("Spectrogram");
Chris@37 97
Chris@805 98 case UnknownLayer:
Chris@805 99 default:
Chris@805 100 cerr << "WARNING: LayerFactory::getLayerPresentationName passed unknown layer" << endl;
Chris@805 101 return Layer::tr("Unknown Layer");
Chris@0 102 }
Chris@0 103 }
Chris@0 104
Chris@193 105 bool
Chris@193 106 LayerFactory::isLayerSliceable(const Layer *layer)
Chris@193 107 {
Chris@193 108 if (dynamic_cast<const SliceableLayer *>(layer)) {
Chris@193 109 if (dynamic_cast<const SpectrogramLayer *>(layer)) {
Chris@193 110
Chris@193 111 //!!! We can create slices of spectrograms, but there's a
Chris@193 112 // problem managing the models. The source model for the
Chris@193 113 // slice layer has to be one of the spectrogram's FFT
Chris@193 114 // models -- that's fine, except that we can't store &
Chris@193 115 // recall the slice layer with a reference to that model
Chris@193 116 // because the model is internal to the spectrogram layer
Chris@193 117 // and the document has no record of it. We would need
Chris@193 118 // some other way of managing models that are used in this
Chris@193 119 // way. For the moment we just don't allow slices of
Chris@193 120 // spectrograms -- and provide a spectrum layer for this
Chris@193 121 // instead.
Chris@193 122 //
Chris@193 123 // This business needs a bit more thought -- either come
Chris@193 124 // up with a sensible way to deal with that stuff, or
Chris@193 125 // simplify the existing slice layer logic so that it
Chris@193 126 // doesn't have to deal with models disappearing on it at
Chris@193 127 // all (and use the normal Document setModel mechanism to
Chris@193 128 // set its sliceable model instead of the fancy pants
Chris@193 129 // nonsense it's doing at the moment).
Chris@193 130
Chris@193 131 return false;
Chris@193 132 }
Chris@193 133 return true;
Chris@193 134 }
Chris@193 135 return false;
Chris@193 136 }
Chris@193 137
Chris@0 138 LayerFactory::LayerTypeSet
Chris@1471 139 LayerFactory::getValidLayerTypes(ModelId modelId)
Chris@0 140 {
Chris@0 141 LayerTypeSet types;
Chris@0 142
Chris@1471 143 if (ModelById::getAs<DenseThreeDimensionalModel>(modelId)) {
Chris@1266 144 types.insert(Colour3DPlot);
Chris@193 145 types.insert(Slice);
Chris@193 146 }
Chris@193 147
Chris@1471 148 if (ModelById::getAs<RangeSummarisableTimeValueModel>(modelId)) {
Chris@1266 149 types.insert(Waveform);
Chris@0 150 }
Chris@0 151
Chris@1471 152 if (ModelById::getAs<DenseTimeValueModel>(modelId)) {
Chris@1266 153 types.insert(Spectrogram);
Chris@1266 154 types.insert(MelodicRangeSpectrogram);
Chris@1266 155 types.insert(PeakFrequencySpectrogram);
Chris@0 156 }
Chris@0 157
Chris@1471 158 if (ModelById::getAs<SparseOneDimensionalModel>(modelId)) {
Chris@1266 159 types.insert(TimeInstants);
Chris@0 160 }
Chris@0 161
Chris@1471 162 if (ModelById::getAs<SparseTimeValueModel>(modelId)) {
Chris@1266 163 types.insert(TimeValues);
Chris@411 164 }
Chris@411 165
Chris@1471 166 if (ModelById::getAs<NoteModel>(modelId)) {
Chris@1471 167 auto nm = ModelById::getAs<NoteModel>(modelId);
Chris@1471 168 if (nm && nm->getSubtype() == NoteModel::FLEXI_NOTE) {
Chris@1426 169 types.insert(FlexiNotes);
Chris@1426 170 } else {
Chris@1426 171 types.insert(Notes);
Chris@1426 172 }
matthiasm@621 173 }
matthiasm@621 174
Chris@1471 175 if (ModelById::getAs<RegionModel>(modelId)) {
Chris@1266 176 types.insert(Regions);
Chris@411 177 }
Chris@411 178
Chris@1518 179 if (ModelById::getAs<BoxModel>(modelId)) {
Chris@1518 180 types.insert(Boxes);
Chris@1512 181 }
Chris@1512 182
Chris@1471 183 if (ModelById::getAs<TextModel>(modelId)) {
Chris@1266 184 types.insert(Text);
Chris@30 185 }
Chris@30 186
Chris@1471 187 if (ModelById::getAs<ImageModel>(modelId)) {
Chris@1266 188 types.insert(Image);
Chris@303 189 }
Chris@303 190
Chris@1471 191 if (ModelById::getAs<DenseTimeValueModel>(modelId)) {
Chris@133 192 types.insert(Spectrum);
Chris@133 193 }
Chris@133 194
Chris@0 195 // We don't count TimeRuler here as it doesn't actually display
Chris@0 196 // the data, although it can be backed by any model
Chris@0 197
Chris@0 198 return types;
Chris@0 199 }
Chris@0 200
Chris@17 201 LayerFactory::LayerTypeSet
Chris@17 202 LayerFactory::getValidEmptyLayerTypes()
Chris@17 203 {
Chris@17 204 LayerTypeSet types;
Chris@17 205 types.insert(TimeInstants);
Chris@17 206 types.insert(TimeValues);
Chris@962 207 // Because this is strictly a UI function -- list the layer types
Chris@962 208 // to show in a menu -- it should not contain FlexiNotes; the
Chris@962 209 // layer isn't meaningfully editable in SV
Chris@962 210 // types.insert(FlexiNotes);
Chris@30 211 types.insert(Notes);
Chris@411 212 types.insert(Regions);
Chris@1518 213 types.insert(Boxes);
Chris@35 214 types.insert(Text);
Chris@303 215 types.insert(Image);
Chris@17 216 //!!! and in principle Colour3DPlot -- now that's a challenge
Chris@17 217 return types;
Chris@17 218 }
Chris@17 219
Chris@0 220 LayerFactory::LayerType
Chris@6 221 LayerFactory::getLayerType(const Layer *layer)
Chris@0 222 {
Chris@6 223 if (dynamic_cast<const WaveformLayer *>(layer)) return Waveform;
Chris@6 224 if (dynamic_cast<const SpectrogramLayer *>(layer)) return Spectrogram;
Chris@6 225 if (dynamic_cast<const TimeRulerLayer *>(layer)) return TimeRuler;
Chris@6 226 if (dynamic_cast<const TimeInstantLayer *>(layer)) return TimeInstants;
Chris@6 227 if (dynamic_cast<const TimeValueLayer *>(layer)) return TimeValues;
Chris@782 228 if (dynamic_cast<const FlexiNoteLayer *>(layer)) return FlexiNotes;
Chris@30 229 if (dynamic_cast<const NoteLayer *>(layer)) return Notes;
Chris@411 230 if (dynamic_cast<const RegionLayer *>(layer)) return Regions;
Chris@1518 231 if (dynamic_cast<const BoxLayer *>(layer)) return Boxes;
Chris@35 232 if (dynamic_cast<const TextLayer *>(layer)) return Text;
Chris@303 233 if (dynamic_cast<const ImageLayer *>(layer)) return Image;
Chris@6 234 if (dynamic_cast<const Colour3DPlotLayer *>(layer)) return Colour3DPlot;
Chris@133 235 if (dynamic_cast<const SpectrumLayer *>(layer)) return Spectrum;
Chris@193 236 if (dynamic_cast<const SliceLayer *>(layer)) return Slice;
Chris@6 237 return UnknownLayer;
Chris@6 238 }
Chris@6 239
Chris@6 240 QString
Chris@17 241 LayerFactory::getLayerIconName(LayerType type)
Chris@17 242 {
Chris@17 243 switch (type) {
Chris@17 244 case Waveform: return "waveform";
Chris@17 245 case Spectrogram: return "spectrogram";
Chris@17 246 case TimeRuler: return "timeruler";
Chris@17 247 case TimeInstants: return "instants";
Chris@17 248 case TimeValues: return "values";
Chris@30 249 case Notes: return "notes";
Chris@782 250 case FlexiNotes: return "flexinotes";
Chris@411 251 case Regions: return "regions";
Chris@1518 252 case Boxes: return "boxes";
Chris@35 253 case Text: return "text";
Chris@303 254 case Image: return "image";
Chris@17 255 case Colour3DPlot: return "colour3d";
Chris@133 256 case Spectrum: return "spectrum";
Chris@193 257 case Slice: return "spectrum";
Chris@326 258 case MelodicRangeSpectrogram: return "spectrogram";
Chris@326 259 case PeakFrequencySpectrogram: return "spectrogram";
Chris@805 260 case UnknownLayer:
Chris@805 261 default:
Chris@805 262 cerr << "WARNING: LayerFactory::getLayerIconName passed unknown layer" << endl;
Chris@805 263 return "unknown";
Chris@17 264 }
Chris@17 265 }
Chris@17 266
Chris@17 267 QString
Chris@6 268 LayerFactory::getLayerTypeName(LayerType type)
Chris@6 269 {
Chris@6 270 switch (type) {
Chris@6 271 case Waveform: return "waveform";
Chris@6 272 case Spectrogram: return "spectrogram";
Chris@6 273 case TimeRuler: return "timeruler";
Chris@6 274 case TimeInstants: return "timeinstants";
Chris@6 275 case TimeValues: return "timevalues";
Chris@30 276 case Notes: return "notes";
matthiasm@623 277 case FlexiNotes: return "flexinotes";
Chris@411 278 case Regions: return "regions";
Chris@1518 279 case Boxes: return "boxes";
Chris@35 280 case Text: return "text";
Chris@303 281 case Image: return "image";
Chris@6 282 case Colour3DPlot: return "colour3dplot";
Chris@133 283 case Spectrum: return "spectrum";
Chris@193 284 case Slice: return "slice";
Chris@326 285 case MelodicRangeSpectrogram: return "melodicrange";
Chris@326 286 case PeakFrequencySpectrogram: return "peakfrequency";
Chris@805 287 case UnknownLayer:
Chris@805 288 default:
Chris@805 289 cerr << "WARNING: LayerFactory::getLayerTypeName passed unknown layer" << endl;
Chris@805 290 return "unknown";
Chris@6 291 }
Chris@6 292 }
Chris@6 293
Chris@6 294 LayerFactory::LayerType
Chris@6 295 LayerFactory::getLayerTypeForName(QString name)
Chris@6 296 {
Chris@6 297 if (name == "waveform") return Waveform;
Chris@6 298 if (name == "spectrogram") return Spectrogram;
Chris@6 299 if (name == "timeruler") return TimeRuler;
Chris@6 300 if (name == "timeinstants") return TimeInstants;
Chris@6 301 if (name == "timevalues") return TimeValues;
Chris@1005 302 if (name == "notes") return Notes;
matthiasm@623 303 if (name == "flexinotes") return FlexiNotes;
Chris@411 304 if (name == "regions") return Regions;
Chris@1518 305 if (name == "boxes" || name == "timefrequencybox") return Boxes;
Chris@35 306 if (name == "text") return Text;
Chris@303 307 if (name == "image") return Image;
Chris@6 308 if (name == "colour3dplot") return Colour3DPlot;
Chris@133 309 if (name == "spectrum") return Spectrum;
Chris@193 310 if (name == "slice") return Slice;
Chris@0 311 return UnknownLayer;
Chris@0 312 }
Chris@0 313
Chris@0 314 void
Chris@1471 315 LayerFactory::setModel(Layer *layer, ModelId model)
Chris@0 316 {
Chris@156 317 if (trySetModel<WaveformLayer, WaveFileModel>(layer, model))
Chris@1266 318 return;
Chris@156 319
Chris@156 320 if (trySetModel<WaveformLayer, WritableWaveFileModel>(layer, model))
Chris@1266 321 return;
Chris@0 322
Chris@0 323 if (trySetModel<SpectrogramLayer, DenseTimeValueModel>(layer, model))
Chris@1266 324 return;
Chris@0 325
Chris@0 326 if (trySetModel<TimeRulerLayer, Model>(layer, model))
Chris@1266 327 return;
Chris@0 328
Chris@0 329 if (trySetModel<TimeInstantLayer, SparseOneDimensionalModel>(layer, model))
Chris@1266 330 return;
Chris@0 331
Chris@0 332 if (trySetModel<TimeValueLayer, SparseTimeValueModel>(layer, model))
Chris@1266 333 return;
Chris@0 334
gyorgyf@626 335 if (trySetModel<NoteLayer, NoteModel>(layer, model))
Chris@1266 336 return;
Chris@30 337
Chris@1426 338 if (trySetModel<FlexiNoteLayer, NoteModel>(layer, model))
Chris@1266 339 return;
Chris@1266 340
Chris@411 341 if (trySetModel<RegionLayer, RegionModel>(layer, model))
Chris@1266 342 return;
Chris@411 343
Chris@1518 344 if (trySetModel<BoxLayer, BoxModel>(layer, model))
Chris@1512 345 return;
Chris@1512 346
Chris@35 347 if (trySetModel<TextLayer, TextModel>(layer, model))
Chris@1266 348 return;
Chris@35 349
Chris@303 350 if (trySetModel<ImageLayer, ImageModel>(layer, model))
Chris@1266 351 return;
Chris@303 352
Chris@0 353 if (trySetModel<Colour3DPlotLayer, DenseThreeDimensionalModel>(layer, model))
Chris@1266 354 return;
Chris@0 355
Chris@133 356 if (trySetModel<SpectrumLayer, DenseTimeValueModel>(layer, model))
Chris@133 357 return;
Chris@0 358 }
Chris@0 359
Chris@1471 360 std::shared_ptr<Model>
Chris@1471 361 LayerFactory::createEmptyModel(LayerType layerType, ModelId baseModelId)
Chris@17 362 {
Chris@1471 363 auto baseModel = ModelById::get(baseModelId);
Chris@1471 364 if (!baseModel) return {};
Chris@1471 365
Chris@1471 366 sv_samplerate_t rate = baseModel->getSampleRate();
Chris@1471 367
Chris@17 368 if (layerType == TimeInstants) {
Chris@1471 369 return std::make_shared<SparseOneDimensionalModel>(rate, 1);
Chris@17 370 } else if (layerType == TimeValues) {
Chris@1471 371 return std::make_shared<SparseTimeValueModel>(rate, 1, true);
Chris@782 372 } else if (layerType == FlexiNotes) {
Chris@1471 373 return std::make_shared<NoteModel>(rate, 1, true);
Chris@30 374 } else if (layerType == Notes) {
Chris@1471 375 return std::make_shared<NoteModel>(rate, 1, true);
Chris@411 376 } else if (layerType == Regions) {
Chris@1471 377 return std::make_shared<RegionModel>(rate, 1, true);
Chris@1518 378 } else if (layerType == Boxes) {
Chris@1518 379 return std::make_shared<BoxModel>(rate, 1, true);
Chris@35 380 } else if (layerType == Text) {
Chris@1471 381 return std::make_shared<TextModel>(rate, 1, true);
Chris@303 382 } else if (layerType == Image) {
Chris@1471 383 return std::make_shared<ImageModel>(rate, 1, true);
Chris@17 384 } else {
Chris@1471 385 return {};
Chris@17 386 }
Chris@17 387 }
Chris@17 388
Chris@53 389 int
Chris@53 390 LayerFactory::getChannel(Layer *layer)
Chris@53 391 {
Chris@53 392 if (dynamic_cast<WaveformLayer *>(layer)) {
Chris@1266 393 return dynamic_cast<WaveformLayer *>(layer)->getChannel();
Chris@53 394 }
Chris@53 395 if (dynamic_cast<SpectrogramLayer *>(layer)) {
Chris@1266 396 return dynamic_cast<SpectrogramLayer *>(layer)->getChannel();
Chris@53 397 }
Chris@53 398 return -1;
Chris@53 399 }
Chris@53 400
Chris@53 401 void
Chris@53 402 LayerFactory::setChannel(Layer *layer, int channel)
Chris@53 403 {
Chris@53 404 if (dynamic_cast<WaveformLayer *>(layer)) {
Chris@1266 405 dynamic_cast<WaveformLayer *>(layer)->setChannel(channel);
Chris@1266 406 return;
Chris@53 407 }
Chris@53 408 if (dynamic_cast<SpectrogramLayer *>(layer)) {
Chris@1266 409 dynamic_cast<SpectrogramLayer *>(layer)->setChannel(channel);
Chris@1266 410 return;
Chris@53 411 }
Chris@349 412 if (dynamic_cast<SpectrumLayer *>(layer)) {
Chris@1266 413 dynamic_cast<SpectrumLayer *>(layer)->setChannel(channel);
Chris@1266 414 return;
Chris@349 415 }
Chris@53 416 }
Chris@53 417
Chris@0 418 Layer *
Chris@53 419 LayerFactory::createLayer(LayerType type)
Chris@0 420 {
Chris@1408 421 Layer *layer = nullptr;
Chris@0 422
Chris@0 423 switch (type) {
Chris@0 424
Chris@0 425 case Waveform:
Chris@1266 426 layer = new WaveformLayer;
Chris@1266 427 break;
Chris@0 428
Chris@0 429 case Spectrogram:
Chris@1266 430 layer = new SpectrogramLayer;
Chris@1266 431 break;
Chris@0 432
Chris@0 433 case TimeRuler:
Chris@1266 434 layer = new TimeRulerLayer;
Chris@1266 435 break;
Chris@0 436
Chris@0 437 case TimeInstants:
Chris@1266 438 layer = new TimeInstantLayer;
Chris@1266 439 break;
Chris@0 440
Chris@0 441 case TimeValues:
Chris@1266 442 layer = new TimeValueLayer;
Chris@1266 443 break;
Chris@0 444
matthiasm@623 445 case FlexiNotes:
Chris@1266 446 layer = new FlexiNoteLayer;
Chris@1266 447 break;
matthiasm@623 448
Chris@30 449 case Notes:
Chris@1266 450 layer = new NoteLayer;
Chris@1266 451 break;
Chris@30 452
Chris@411 453 case Regions:
Chris@1266 454 layer = new RegionLayer;
Chris@1266 455 break;
Chris@411 456
Chris@1518 457 case Boxes:
Chris@1518 458 layer = new BoxLayer;
Chris@1512 459 break;
Chris@1512 460
Chris@35 461 case Text:
Chris@1266 462 layer = new TextLayer;
Chris@1266 463 break;
Chris@35 464
Chris@303 465 case Image:
Chris@1266 466 layer = new ImageLayer;
Chris@1266 467 break;
Chris@303 468
Chris@0 469 case Colour3DPlot:
Chris@1266 470 layer = new Colour3DPlotLayer;
Chris@1266 471 break;
Chris@0 472
Chris@133 473 case Spectrum:
Chris@133 474 layer = new SpectrumLayer;
Chris@133 475 break;
Chris@133 476
Chris@193 477 case Slice:
Chris@193 478 layer = new SliceLayer;
Chris@193 479 break;
Chris@193 480
Chris@0 481 case MelodicRangeSpectrogram:
Chris@1266 482 layer = new SpectrogramLayer(SpectrogramLayer::MelodicRange);
Chris@1266 483 break;
Chris@11 484
Chris@37 485 case PeakFrequencySpectrogram:
Chris@1266 486 layer = new SpectrogramLayer(SpectrogramLayer::MelodicPeaks);
Chris@1266 487 break;
Chris@37 488
Chris@805 489 case UnknownLayer:
Chris@805 490 default:
Chris@805 491 cerr << "WARNING: LayerFactory::createLayer passed unknown layer" << endl;
Chris@805 492 break;
Chris@0 493 }
Chris@0 494
Chris@0 495 if (!layer) {
Chris@1266 496 cerr << "LayerFactory::createLayer: Unknown layer type "
Chris@1266 497 << type << endl;
Chris@0 498 } else {
Chris@1266 499 // SVDEBUG << "LayerFactory::createLayer: Setting object name "
Chris@1266 500 // << getLayerPresentationName(type) << " on " << layer << endl;
Chris@1266 501 layer->setObjectName(getLayerPresentationName(type));
Chris@326 502 setLayerDefaultProperties(type, layer);
Chris@0 503 }
Chris@0 504
Chris@0 505 return layer;
Chris@0 506 }
Chris@0 507
Chris@326 508 void
Chris@326 509 LayerFactory::setLayerDefaultProperties(LayerType type, Layer *layer)
Chris@326 510 {
Chris@587 511 // SVDEBUG << "LayerFactory::setLayerDefaultProperties: type " << type << " (name \"" << getLayerTypeName(type) << "\")" << endl;
Chris@327 512
Chris@326 513 QSettings settings;
Chris@326 514 settings.beginGroup("LayerDefaults");
Chris@326 515 QString defaults = settings.value(getLayerTypeName(type), "").toString();
Chris@326 516 if (defaults == "") return;
Chris@1455 517 setLayerProperties(layer, defaults);
Chris@1455 518 settings.endGroup();
Chris@1455 519 }
Chris@326 520
Chris@1455 521 void
Chris@1455 522 LayerFactory::setLayerProperties(Layer *layer, QString newXml)
Chris@1455 523 {
Chris@1455 524 QDomDocument docOld, docNew;
Chris@1455 525 QString oldXml = layer->toXmlString();
Chris@327 526
Chris@1455 527 if (!docOld.setContent(oldXml, false)) {
Chris@1455 528 SVCERR << "LayerFactory::setLayerProperties: Failed to parse XML for existing layer properties! XML string is: " << oldXml << endl;
Chris@1455 529 return;
Chris@1455 530 }
Chris@1455 531
Chris@1455 532 if (!docNew.setContent(newXml, false)) {
Chris@1455 533 SVCERR << "LayerFactory::setLayerProperties: Failed to parse XML: " << newXml << endl;
Chris@1455 534 return;
Chris@1455 535 }
Chris@326 536
Chris@1455 537 QXmlAttributes attrs;
Chris@326 538
Chris@1455 539 QDomElement layerElt = docNew.firstChildElement("layer");
Chris@1455 540 QDomNamedNodeMap attrNodes = layerElt.attributes();
Chris@326 541
Chris@1455 542 for (int i = 0; i < attrNodes.length(); ++i) {
Chris@1455 543 QDomAttr attr = attrNodes.item(i).toAttr();
Chris@1455 544 if (attr.isNull()) continue;
Chris@683 545 // cerr << "append \"" << attr.name()
Chris@584 546 // << "\" -> \"" << attr.value() << "\""
Chris@682 547 // << endl;
Chris@1455 548 attrs.append(attr.name(), "", "", attr.value());
Chris@1455 549 }
Chris@1455 550
Chris@1455 551 layerElt = docOld.firstChildElement("layer");
Chris@1455 552 attrNodes = layerElt.attributes();
Chris@1455 553 for (int i = 0; i < attrNodes.length(); ++i) {
Chris@1455 554 QDomAttr attr = attrNodes.item(i).toAttr();
Chris@1455 555 if (attr.isNull()) continue;
Chris@1455 556 if (attrs.value(attr.name()) == "") {
Chris@683 557 // cerr << "append \"" << attr.name()
Chris@584 558 // << "\" -> \"" << attr.value() << "\""
Chris@682 559 // << endl;
Chris@1455 560 attrs.append(attr.name(), "", "", attr.value());
Chris@326 561 }
Chris@326 562 }
Chris@1455 563
Chris@1455 564 layer->setProperties(attrs);
Chris@326 565 }
Chris@326 566
Chris@360 567 LayerFactory::LayerType
Chris@360 568 LayerFactory::getLayerTypeForClipboardContents(const Clipboard &clip)
Chris@360 569 {
Chris@1423 570 const EventVector &contents = clip.getPoints();
Chris@360 571
Chris@360 572 bool haveValue = false;
Chris@360 573 bool haveDuration = false;
Chris@411 574 bool haveLevel = false;
Chris@360 575
Chris@1423 576 for (EventVector::const_iterator i = contents.begin();
Chris@360 577 i != contents.end(); ++i) {
Chris@1423 578 if (i->hasValue()) haveValue = true;
Chris@1423 579 if (i->hasDuration()) haveDuration = true;
Chris@1423 580 if (i->hasLevel()) haveLevel = true;
Chris@360 581 }
Chris@360 582
Chris@1423 583 if (haveValue && haveDuration && haveLevel) return Notes;
Chris@1423 584 if (haveValue && haveDuration) return Regions;
Chris@1423 585 if (haveValue) return TimeValues;
Chris@360 586 return TimeInstants;
Chris@360 587 }
Chris@360 588