annotate layer/LayerFactory.cpp @ 1551:e79731086b0f

Fixes to NoteLayer, particularly to calculation of vertical scale when model unit is not Hz. To avoid inconsistency we now behave as if the unit is always Hz from the point of view of the external API and display, converting at the point where we obtain values from the events themselves. Also various fixes to editing.
author Chris Cannam
date Thu, 21 Nov 2019 14:02:57 +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