annotate layer/SliceLayer.cpp @ 195:4a3bdde1ef13

* beginnings of spectrum scales
author Chris Cannam
date Mon, 29 Jan 2007 18:11:20 +0000
parents d13e209bfa94
children 6b023411087b
rev   line source
Chris@133 1
Chris@133 2 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@133 3
Chris@133 4 /*
Chris@133 5 Sonic Visualiser
Chris@133 6 An audio file viewer and annotation editor.
Chris@133 7 Centre for Digital Music, Queen Mary, University of London.
Chris@195 8 This file copyright 2006-2007 QMUL.
Chris@133 9
Chris@133 10 This program is free software; you can redistribute it and/or
Chris@133 11 modify it under the terms of the GNU General Public License as
Chris@133 12 published by the Free Software Foundation; either version 2 of the
Chris@133 13 License, or (at your option) any later version. See the file
Chris@133 14 COPYING included with this distribution for more information.
Chris@133 15 */
Chris@133 16
Chris@193 17 #include "SliceLayer.h"
Chris@133 18
Chris@133 19 #include "view/View.h"
Chris@153 20 #include "base/AudioLevel.h"
Chris@167 21 #include "base/RangeMapper.h"
Chris@195 22 #include "base/RealTime.h"
Chris@195 23
Chris@195 24 #include "PaintAssistant.h"
Chris@133 25
Chris@133 26 #include <QPainter>
Chris@133 27 #include <QPainterPath>
Chris@133 28
Chris@193 29 SliceLayer::SliceLayer() :
Chris@193 30 m_sliceableModel(0),
Chris@153 31 m_colour(Qt::darkBlue),
Chris@153 32 m_energyScale(dBScale),
Chris@193 33 m_samplingMode(SamplePeak),
Chris@195 34 m_plotStyle(PlotSteps),
Chris@193 35 m_binScale(LinearBins),
Chris@153 36 m_normalize(false),
Chris@194 37 m_bias(false),
Chris@193 38 m_gain(1.0)
Chris@133 39 {
Chris@133 40 }
Chris@133 41
Chris@193 42 SliceLayer::~SliceLayer()
Chris@133 43 {
Chris@193 44
Chris@133 45 }
Chris@133 46
Chris@133 47 void
Chris@193 48 SliceLayer::setSliceableModel(const Model *model)
Chris@133 49 {
Chris@193 50 const DenseThreeDimensionalModel *sliceable =
Chris@193 51 dynamic_cast<const DenseThreeDimensionalModel *>(model);
Chris@193 52
Chris@193 53 if (model && !sliceable) {
Chris@193 54 std::cerr << "WARNING: SliceLayer::setSliceableModel(" << model
Chris@193 55 << "): model is not a DenseThreeDimensionalModel" << std::endl;
Chris@193 56 }
Chris@193 57
Chris@193 58 if (m_sliceableModel == sliceable) return;
Chris@193 59
Chris@193 60 m_sliceableModel = sliceable;
Chris@193 61
Chris@193 62 connect(m_sliceableModel, SIGNAL(modelChanged()),
Chris@193 63 this, SIGNAL(modelChanged()));
Chris@193 64
Chris@193 65 connect(m_sliceableModel, SIGNAL(modelChanged(size_t, size_t)),
Chris@193 66 this, SIGNAL(modelChanged(size_t, size_t)));
Chris@193 67
Chris@193 68 connect(m_sliceableModel, SIGNAL(completionChanged()),
Chris@193 69 this, SIGNAL(modelCompletionChanged()));
Chris@193 70
Chris@193 71 emit modelReplaced();
Chris@153 72 }
Chris@153 73
Chris@153 74 void
Chris@193 75 SliceLayer::sliceableModelReplaced(const Model *orig, const Model *replacement)
Chris@153 76 {
Chris@193 77 std::cerr << "SliceLayer::sliceableModelReplaced(" << orig << ", " << replacement << ")" << std::endl;
Chris@153 78
Chris@193 79 if (orig == m_sliceableModel) {
Chris@193 80 setSliceableModel
Chris@193 81 (dynamic_cast<const DenseThreeDimensionalModel *>(replacement));
Chris@153 82 }
Chris@153 83 }
Chris@153 84
Chris@153 85 void
Chris@193 86 SliceLayer::modelAboutToBeDeleted(Model *m)
Chris@153 87 {
Chris@193 88 std::cerr << "SliceLayer::modelAboutToBeDeleted(" << m << ")" << std::endl;
Chris@153 89
Chris@193 90 if (m == m_sliceableModel) {
Chris@193 91 setSliceableModel(0);
Chris@153 92 }
Chris@133 93 }
Chris@133 94
Chris@133 95 void
Chris@193 96 SliceLayer::paint(View *v, QPainter &paint, QRect rect) const
Chris@133 97 {
Chris@193 98 if (!m_sliceableModel) return;
Chris@133 99
Chris@195 100 paint.save();
Chris@195 101 paint.setRenderHint(QPainter::Antialiasing, false);
Chris@195 102
Chris@195 103 if (v->getViewManager() && v->getViewManager()->shouldShowScaleGuides()) {
Chris@195 104 if (!m_scalePoints.empty()) {
Chris@195 105 paint.setPen(QColor(240, 240, 240)); //!!! and dark background?
Chris@195 106 for (size_t i = 0; i < m_scalePoints.size(); ++i) {
Chris@195 107 paint.drawLine(0, m_scalePoints[i], rect.width(), m_scalePoints[i]);
Chris@195 108 }
Chris@195 109 }
Chris@195 110 }
Chris@195 111
Chris@195 112 paint.setPen(m_colour);
Chris@195 113
Chris@195 114 // int w = (v->width() * 2) / 3;
Chris@195 115 int xorigin = getVerticalScaleWidth(v, paint) + 1; //!!! (v->width() / 2) - (w / 2);
Chris@195 116 int w = v->width() - xorigin - 1;
Chris@133 117
Chris@195 118 int yorigin = v->height() - 20 - paint.fontMetrics().height() - 7;
Chris@195 119 int h = yorigin - paint.fontMetrics().height() - 8;
Chris@195 120 if (h < 0) return;
Chris@133 121
Chris@195 122 // int h = (v->height() * 3) / 4;
Chris@195 123 // int yorigin = (v->height() / 2) + (h / 2);
Chris@133 124
Chris@133 125 QPainterPath path;
Chris@133 126 float thresh = -80.f;
Chris@133 127
Chris@193 128 int mh = m_sliceableModel->getHeight();
Chris@133 129
Chris@193 130 float *values = new float[mh];
Chris@193 131 int divisor = 0;
Chris@193 132
Chris@193 133 for (size_t bin = 0; bin < mh; ++bin) {
Chris@193 134 values[bin] = 0.f;
Chris@193 135 }
Chris@193 136
Chris@193 137 size_t f0 = v->getCentreFrame();
Chris@193 138 int f0x = v->getXForFrame(f0);
Chris@195 139 f0 = v->getFrameForX(f0x);
Chris@193 140 size_t f1 = v->getFrameForX(f0x + 1);
Chris@195 141 if (f1 > f0) --f1;
Chris@193 142
Chris@193 143 size_t col0 = f0 / m_sliceableModel->getResolution();
Chris@193 144 size_t col1 = col0;
Chris@193 145 if (m_samplingMode != NearestSample) {
Chris@193 146 col1 = f1 / m_sliceableModel->getResolution();
Chris@193 147 }
Chris@195 148 f0 = col0 * m_sliceableModel->getResolution();
Chris@195 149 f1 = (col1 + 1) * m_sliceableModel->getResolution() - 1;
Chris@193 150
Chris@195 151 for (size_t col = col0; col <= col1; ++col) {
Chris@193 152 for (size_t bin = 0; bin < mh; ++bin) {
Chris@193 153 float value = m_sliceableModel->getValueAt(col, bin);
Chris@193 154 if (m_bias) value *= bin + 1;
Chris@193 155 if (m_samplingMode == SamplePeak) {
Chris@193 156 if (value > values[bin]) values[bin] = value;
Chris@193 157 } else {
Chris@193 158 values[bin] += value;
Chris@193 159 }
Chris@153 160 }
Chris@193 161 ++divisor;
Chris@193 162 }
Chris@193 163
Chris@193 164 float max = 0.f;
Chris@193 165 for (size_t bin = 0; bin < mh; ++bin) {
Chris@193 166 if (m_samplingMode == SampleMean) values[bin] /= divisor;
Chris@193 167 if (values[bin] > max) max = values[bin];
Chris@193 168 }
Chris@193 169 if (max != 0.f && m_normalize) {
Chris@193 170 for (size_t bin = 0; bin < mh; ++bin) {
Chris@193 171 values[bin] /= max;
Chris@193 172 }
Chris@193 173 }
Chris@193 174
Chris@193 175 float py = 0;
Chris@193 176 float nx = xorigin;
Chris@193 177
Chris@193 178 for (size_t bin = 0; bin < mh; ++bin) {
Chris@193 179
Chris@193 180 float x;
Chris@193 181
Chris@193 182 switch (m_binScale) {
Chris@193 183
Chris@193 184 case LinearBins:
Chris@193 185 x = nx;
Chris@193 186 nx = xorigin + (float(w) * (bin + 1)) / mh;
Chris@193 187 break;
Chris@193 188
Chris@193 189 case LogBins:
Chris@193 190 x = nx;
Chris@193 191 nx = xorigin + (float(w) * (log10f(bin + 2) - log10f(1))) /
Chris@193 192 (log10f(mh + 1) - log10f(1));
Chris@193 193 break;
Chris@193 194
Chris@193 195 case InvertedLogBins:
Chris@193 196 x = nx;
Chris@193 197 nx = xorigin + w - (float(w) * (log10f(mh - bin) - log10f(1))) /
Chris@193 198 (log10f(mh) - log10f(1));
Chris@193 199 break;
Chris@193 200 }
Chris@193 201
Chris@193 202 float value = values[bin];
Chris@193 203
Chris@193 204 value *= m_gain;
Chris@153 205 float y = 0.f;
Chris@153 206
Chris@153 207 switch (m_energyScale) {
Chris@153 208
Chris@153 209 case dBScale:
Chris@153 210 {
Chris@153 211 float db = thresh;
Chris@193 212 if (value > 0.f) db = 10.f * log10f(value);
Chris@153 213 if (db < thresh) db = thresh;
Chris@153 214 float val = (db - thresh) / -thresh;
Chris@153 215 y = yorigin - (float(h) * val);
Chris@153 216 break;
Chris@153 217 }
Chris@153 218
Chris@153 219 case MeterScale:
Chris@193 220 y = yorigin - AudioLevel::multiplier_to_preview(value, h);
Chris@153 221 break;
Chris@153 222
Chris@153 223 default:
Chris@193 224 y = yorigin - (float(h) * value);
Chris@153 225 break;
Chris@153 226 }
Chris@133 227
Chris@193 228 if (m_plotStyle == PlotLines) {
Chris@193 229
Chris@193 230 if (bin == 0) {
Chris@193 231 path.moveTo(x, y);
Chris@193 232 } else {
Chris@193 233 path.lineTo(x, y);
Chris@193 234 }
Chris@193 235
Chris@193 236 } else if (m_plotStyle == PlotSteps) {
Chris@193 237
Chris@193 238 if (bin == 0) {
Chris@193 239 path.moveTo(x, y);
Chris@193 240 } else {
Chris@193 241 path.lineTo(x, y);
Chris@193 242 }
Chris@193 243 path.lineTo(nx, y);
Chris@193 244
Chris@193 245 } else if (m_plotStyle == PlotBlocks) {
Chris@193 246
Chris@193 247 path.moveTo(x, yorigin);
Chris@133 248 path.lineTo(x, y);
Chris@193 249 path.lineTo(nx, y);
Chris@193 250 path.lineTo(nx, yorigin);
Chris@193 251 path.lineTo(x, yorigin);
Chris@133 252 }
Chris@193 253
Chris@193 254 py = y;
Chris@133 255 }
Chris@133 256
Chris@133 257 paint.drawPath(path);
Chris@133 258 paint.restore();
Chris@133 259
Chris@195 260 if (v->getViewManager() && v->getViewManager()->shouldShowFrameCount()) {
Chris@195 261
Chris@195 262 int sampleRate = m_sliceableModel->getSampleRate();
Chris@195 263
Chris@195 264 QString startText = QString("%1 / %2")
Chris@195 265 .arg(QString::fromStdString
Chris@195 266 (RealTime::frame2RealTime
Chris@195 267 (f0, sampleRate).toText(true)))
Chris@195 268 .arg(f0);
Chris@195 269
Chris@195 270 QString endText = QString(" %1 / %2")
Chris@195 271 .arg(QString::fromStdString
Chris@195 272 (RealTime::frame2RealTime
Chris@195 273 (f1, sampleRate).toText(true)))
Chris@195 274 .arg(f1);
Chris@195 275
Chris@195 276 QString durationText = QString("(%1 / %2) ")
Chris@195 277 .arg(QString::fromStdString
Chris@195 278 (RealTime::frame2RealTime
Chris@195 279 (f1 - f0 + 1, sampleRate).toText(true)))
Chris@195 280 .arg(f1 - f0 + 1);
Chris@195 281
Chris@195 282 v->drawVisibleText
Chris@195 283 (paint, xorigin + 5,
Chris@195 284 paint.fontMetrics().ascent() + 5,
Chris@195 285 startText, View::OutlinedText);
Chris@195 286
Chris@195 287 v->drawVisibleText
Chris@195 288 (paint, xorigin + 5,
Chris@195 289 paint.fontMetrics().ascent() + paint.fontMetrics().height() + 10,
Chris@195 290 endText, View::OutlinedText);
Chris@195 291
Chris@195 292 v->drawVisibleText
Chris@195 293 (paint, xorigin + 5,
Chris@195 294 paint.fontMetrics().ascent() + 2*paint.fontMetrics().height() + 15,
Chris@195 295 durationText, View::OutlinedText);
Chris@195 296 }
Chris@195 297
Chris@195 298 /*
Chris@195 299
Chris@195 300 QString frameRange;
Chris@195 301 if (f1 != f0) {
Chris@195 302 frameRange = QString("%1 - %2").arg(f0).arg(f1);
Chris@195 303 } else {
Chris@195 304 frameRange = QString("%1").arg(f0);
Chris@195 305 }
Chris@195 306
Chris@195 307 QString colRange;
Chris@195 308 if (col1 != col0) {
Chris@195 309 colRange = tr("%1 hops").arg(col1 - col0 + 1);
Chris@195 310 } else {
Chris@195 311 colRange = tr("1 hop");
Chris@195 312 }
Chris@195 313
Chris@195 314 if (v->getViewManager() && v->getViewManager()->shouldShowFrameCount()) {
Chris@195 315
Chris@195 316 v->drawVisibleText
Chris@195 317 (paint, xorigin + 5,
Chris@195 318 paint.fontMetrics().ascent() + 5,
Chris@195 319 frameRange, View::OutlinedText);
Chris@195 320
Chris@195 321 v->drawVisibleText
Chris@195 322 (paint, xorigin + 5,
Chris@195 323 paint.fontMetrics().ascent() + paint.fontMetrics().height() + 10,
Chris@195 324 colRange, View::OutlinedText);
Chris@195 325 }
Chris@195 326 */
Chris@195 327 }
Chris@195 328
Chris@195 329 int
Chris@195 330 SliceLayer::getVerticalScaleWidth(View *v, QPainter &paint) const
Chris@195 331 {
Chris@195 332 if (m_energyScale == LinearScale) {
Chris@195 333 return paint.fontMetrics().width("0.0") + 13;
Chris@195 334 } else {
Chris@195 335 return std::max(paint.fontMetrics().width(tr("0dB")),
Chris@195 336 paint.fontMetrics().width(tr("-Inf"))) + 13;
Chris@195 337 }
Chris@195 338 }
Chris@195 339
Chris@195 340 void
Chris@195 341 SliceLayer::paintVerticalScale(View *v, QPainter &paint, QRect rect) const
Chris@195 342 {
Chris@195 343 float thresh = 0;
Chris@195 344 if (m_energyScale != LinearScale) {
Chris@195 345 thresh = AudioLevel::dB_to_multiplier(-80); //!!! thresh
Chris@195 346 }
Chris@195 347
Chris@195 348 // int h = (rect.height() * 3) / 4;
Chris@195 349 // int y = (rect.height() / 2) - (h / 2);
Chris@195 350
Chris@195 351 int yorigin = v->height() - 20 - paint.fontMetrics().height() - 6;
Chris@195 352 int h = yorigin - paint.fontMetrics().height() - 8;
Chris@195 353 if (h < 0) return;
Chris@195 354
Chris@195 355 QRect actual(rect.x(), rect.y() + yorigin - h, rect.width(), h);
Chris@195 356
Chris@195 357 PaintAssistant::paintVerticalLevelScale
Chris@195 358 (paint, actual, thresh, 1.0 / m_gain,
Chris@195 359 PaintAssistant::Scale(m_energyScale),
Chris@195 360 const_cast<std::vector<int> *>(&m_scalePoints));
Chris@133 361 }
Chris@133 362
Chris@153 363 Layer::PropertyList
Chris@193 364 SliceLayer::getProperties() const
Chris@153 365 {
Chris@153 366 PropertyList list;
Chris@153 367 list.push_back("Colour");
Chris@193 368 list.push_back("Plot Type");
Chris@193 369 list.push_back("Sampling Mode");
Chris@153 370 list.push_back("Scale");
Chris@153 371 list.push_back("Normalize");
Chris@153 372 list.push_back("Gain");
Chris@193 373 list.push_back("Bin Scale");
Chris@153 374
Chris@153 375 return list;
Chris@153 376 }
Chris@153 377
Chris@153 378 QString
Chris@193 379 SliceLayer::getPropertyLabel(const PropertyName &name) const
Chris@153 380 {
Chris@153 381 if (name == "Colour") return tr("Colour");
Chris@193 382 if (name == "Plot Type") return tr("Plot Type");
Chris@153 383 if (name == "Energy Scale") return tr("Scale");
Chris@153 384 if (name == "Normalize") return tr("Normalize");
Chris@153 385 if (name == "Gain") return tr("Gain");
Chris@193 386 if (name == "Sampling Mode") return tr("Sampling Mode");
Chris@193 387 if (name == "Bin Scale") return tr("Plot X Scale");
Chris@153 388 return "";
Chris@153 389 }
Chris@153 390
Chris@153 391 Layer::PropertyType
Chris@193 392 SliceLayer::getPropertyType(const PropertyName &name) const
Chris@153 393 {
Chris@153 394 if (name == "Gain") return RangeProperty;
Chris@153 395 if (name == "Normalize") return ToggleProperty;
Chris@153 396 return ValueProperty;
Chris@153 397 }
Chris@153 398
Chris@153 399 QString
Chris@193 400 SliceLayer::getPropertyGroupName(const PropertyName &name) const
Chris@153 401 {
Chris@153 402 if (name == "Scale" ||
Chris@153 403 name == "Normalize" ||
Chris@193 404 name == "Sampling Mode" ||
Chris@193 405 name == "Gain") return tr("Scale");
Chris@193 406 if (name == "Plot Type" ||
Chris@193 407 name == "Bin Scale") return tr("Plot Type");
Chris@153 408 return QString();
Chris@153 409 }
Chris@153 410
Chris@153 411 int
Chris@193 412 SliceLayer::getPropertyRangeAndValue(const PropertyName &name,
Chris@153 413 int *min, int *max) const
Chris@153 414 {
Chris@153 415 int deft = 0;
Chris@153 416
Chris@153 417 int garbage0, garbage1;
Chris@153 418 if (!min) min = &garbage0;
Chris@153 419 if (!max) max = &garbage1;
Chris@153 420
Chris@153 421 if (name == "Gain") {
Chris@153 422
Chris@153 423 *min = -50;
Chris@153 424 *max = 50;
Chris@153 425
Chris@193 426 std::cerr << "gain is " << m_gain << ", mode is " << m_samplingMode << std::endl;
Chris@193 427
Chris@153 428 deft = lrint(log10(m_gain) * 20.0);
Chris@153 429 if (deft < *min) deft = *min;
Chris@153 430 if (deft > *max) deft = *max;
Chris@153 431
Chris@153 432 } else if (name == "Normalize") {
Chris@153 433
Chris@153 434 deft = (m_normalize ? 1 : 0);
Chris@153 435
Chris@153 436 } else if (name == "Colour") {
Chris@153 437
Chris@153 438 *min = 0;
Chris@153 439 *max = 5;
Chris@153 440
Chris@153 441 if (m_colour == Qt::black) deft = 0;
Chris@153 442 else if (m_colour == Qt::darkRed) deft = 1;
Chris@153 443 else if (m_colour == Qt::darkBlue) deft = 2;
Chris@153 444 else if (m_colour == Qt::darkGreen) deft = 3;
Chris@153 445 else if (m_colour == QColor(200, 50, 255)) deft = 4;
Chris@153 446 else if (m_colour == QColor(255, 150, 50)) deft = 5;
Chris@153 447
Chris@153 448 } else if (name == "Scale") {
Chris@153 449
Chris@153 450 *min = 0;
Chris@153 451 *max = 2;
Chris@153 452
Chris@153 453 deft = (int)m_energyScale;
Chris@153 454
Chris@193 455 } else if (name == "Sampling Mode") {
Chris@153 456
Chris@153 457 *min = 0;
Chris@193 458 *max = 2;
Chris@193 459
Chris@193 460 deft = (int)m_samplingMode;
Chris@153 461
Chris@193 462 } else if (name == "Plot Type") {
Chris@193 463
Chris@193 464 *min = 0;
Chris@193 465 *max = 2;
Chris@193 466
Chris@193 467 deft = (int)m_plotStyle;
Chris@193 468
Chris@193 469 } else if (name == "Bin Scale") {
Chris@193 470
Chris@193 471 *min = 0;
Chris@193 472 *max = 2;
Chris@193 473
Chris@193 474 deft = (int)m_binScale;
Chris@193 475
Chris@153 476 } else {
Chris@153 477 deft = Layer::getPropertyRangeAndValue(name, min, max);
Chris@153 478 }
Chris@153 479
Chris@153 480 return deft;
Chris@153 481 }
Chris@153 482
Chris@153 483 QString
Chris@193 484 SliceLayer::getPropertyValueLabel(const PropertyName &name,
Chris@153 485 int value) const
Chris@153 486 {
Chris@153 487 if (name == "Colour") {
Chris@153 488 switch (value) {
Chris@153 489 default:
Chris@153 490 case 0: return tr("Black");
Chris@153 491 case 1: return tr("Red");
Chris@153 492 case 2: return tr("Blue");
Chris@153 493 case 3: return tr("Green");
Chris@153 494 case 4: return tr("Purple");
Chris@153 495 case 5: return tr("Orange");
Chris@153 496 }
Chris@153 497 }
Chris@153 498 if (name == "Scale") {
Chris@153 499 switch (value) {
Chris@153 500 default:
Chris@153 501 case 0: return tr("Linear");
Chris@153 502 case 1: return tr("Meter");
Chris@153 503 case 2: return tr("dB");
Chris@153 504 }
Chris@153 505 }
Chris@193 506 if (name == "Sampling Mode") {
Chris@153 507 switch (value) {
Chris@153 508 default:
Chris@193 509 case 0: return tr("Any");
Chris@193 510 case 1: return tr("Mean");
Chris@193 511 case 2: return tr("Peak");
Chris@193 512 }
Chris@193 513 }
Chris@193 514 if (name == "Plot Type") {
Chris@193 515 switch (value) {
Chris@193 516 default:
Chris@193 517 case 0: return tr("Lines");
Chris@193 518 case 1: return tr("Steps");
Chris@193 519 case 2: return tr("Blocks");
Chris@193 520 }
Chris@193 521 }
Chris@193 522 if (name == "Bin Scale") {
Chris@193 523 switch (value) {
Chris@193 524 default:
Chris@193 525 case 0: return tr("Linear");
Chris@193 526 case 1: return tr("Log");
Chris@193 527 case 2: return tr("Rev Log");
Chris@153 528 }
Chris@153 529 }
Chris@153 530 return tr("<unknown>");
Chris@153 531 }
Chris@153 532
Chris@167 533 RangeMapper *
Chris@193 534 SliceLayer::getNewPropertyRangeMapper(const PropertyName &name) const
Chris@167 535 {
Chris@167 536 if (name == "Gain") {
Chris@167 537 return new LinearRangeMapper(-50, 50, -25, 25, tr("dB"));
Chris@167 538 }
Chris@167 539 return 0;
Chris@167 540 }
Chris@167 541
Chris@133 542 void
Chris@193 543 SliceLayer::setProperty(const PropertyName &name, int value)
Chris@133 544 {
Chris@153 545 if (name == "Gain") {
Chris@153 546 setGain(pow(10, float(value)/20.0));
Chris@153 547 } else if (name == "Colour") {
Chris@153 548 switch (value) {
Chris@153 549 default:
Chris@153 550 case 0: setBaseColour(Qt::black); break;
Chris@153 551 case 1: setBaseColour(Qt::darkRed); break;
Chris@153 552 case 2: setBaseColour(Qt::darkBlue); break;
Chris@153 553 case 3: setBaseColour(Qt::darkGreen); break;
Chris@153 554 case 4: setBaseColour(QColor(200, 50, 255)); break;
Chris@153 555 case 5: setBaseColour(QColor(255, 150, 50)); break;
Chris@153 556 }
Chris@153 557 } else if (name == "Scale") {
Chris@153 558 switch (value) {
Chris@153 559 default:
Chris@153 560 case 0: setEnergyScale(LinearScale); break;
Chris@153 561 case 1: setEnergyScale(MeterScale); break;
Chris@153 562 case 2: setEnergyScale(dBScale); break;
Chris@153 563 }
Chris@193 564 } else if (name == "Plot Type") {
Chris@193 565 setPlotStyle(PlotStyle(value));
Chris@193 566 } else if (name == "Sampling Mode") {
Chris@193 567 switch (value) {
Chris@193 568 default:
Chris@193 569 case 0: setSamplingMode(NearestSample); break;
Chris@193 570 case 1: setSamplingMode(SampleMean); break;
Chris@193 571 case 2: setSamplingMode(SamplePeak); break;
Chris@193 572 }
Chris@193 573 } else if (name == "Bin Scale") {
Chris@193 574 switch (value) {
Chris@193 575 default:
Chris@193 576 case 0: setBinScale(LinearBins); break;
Chris@193 577 case 1: setBinScale(LogBins); break;
Chris@193 578 case 2: setBinScale(InvertedLogBins); break;
Chris@193 579 }
Chris@153 580 } else if (name == "Normalize") {
Chris@153 581 setNormalize(value ? true : false);
Chris@153 582 }
Chris@153 583 }
Chris@153 584
Chris@153 585 void
Chris@193 586 SliceLayer::setBaseColour(QColor colour)
Chris@153 587 {
Chris@153 588 if (m_colour == colour) return;
Chris@153 589 m_colour = colour;
Chris@153 590 emit layerParametersChanged();
Chris@153 591 }
Chris@153 592
Chris@153 593 void
Chris@193 594 SliceLayer::setEnergyScale(EnergyScale scale)
Chris@153 595 {
Chris@153 596 if (m_energyScale == scale) return;
Chris@153 597 m_energyScale = scale;
Chris@153 598 emit layerParametersChanged();
Chris@153 599 }
Chris@153 600
Chris@153 601 void
Chris@193 602 SliceLayer::setSamplingMode(SamplingMode mode)
Chris@153 603 {
Chris@193 604 if (m_samplingMode == mode) return;
Chris@193 605 m_samplingMode = mode;
Chris@153 606 emit layerParametersChanged();
Chris@153 607 }
Chris@153 608
Chris@153 609 void
Chris@193 610 SliceLayer::setPlotStyle(PlotStyle style)
Chris@153 611 {
Chris@193 612 if (m_plotStyle == style) return;
Chris@193 613 m_plotStyle = style;
Chris@153 614 emit layerParametersChanged();
Chris@153 615 }
Chris@153 616
Chris@153 617 void
Chris@193 618 SliceLayer::setBinScale(BinScale scale)
Chris@153 619 {
Chris@193 620 if (m_binScale == scale) return;
Chris@193 621 m_binScale = scale;
Chris@153 622 emit layerParametersChanged();
Chris@153 623 }
Chris@153 624
Chris@153 625 void
Chris@193 626 SliceLayer::setNormalize(bool n)
Chris@153 627 {
Chris@153 628 if (m_normalize == n) return;
Chris@153 629 m_normalize = n;
Chris@153 630 emit layerParametersChanged();
Chris@153 631 }
Chris@153 632
Chris@153 633 void
Chris@193 634 SliceLayer::setGain(float gain)
Chris@153 635 {
Chris@153 636 if (m_gain == gain) return;
Chris@153 637 m_gain = gain;
Chris@153 638 emit layerParametersChanged();
Chris@153 639 }
Chris@153 640
Chris@153 641 QString
Chris@193 642 SliceLayer::toXmlString(QString indent, QString extraAttributes) const
Chris@153 643 {
Chris@153 644 QString s;
Chris@153 645
Chris@153 646 s += QString("colour=\"%1\" "
Chris@193 647 "energyScale=\"%2\" "
Chris@193 648 "samplingMode=\"%3\" "
Chris@193 649 "gain=\"%4\" "
Chris@193 650 "normalize=\"%5\"")
Chris@153 651 .arg(encodeColour(m_colour))
Chris@153 652 .arg(m_energyScale)
Chris@193 653 .arg(m_samplingMode)
Chris@153 654 .arg(m_gain)
Chris@153 655 .arg(m_normalize ? "true" : "false");
Chris@153 656
Chris@153 657 return Layer::toXmlString(indent, extraAttributes + " " + s);
Chris@153 658 }
Chris@153 659
Chris@153 660 void
Chris@193 661 SliceLayer::setProperties(const QXmlAttributes &attributes)
Chris@153 662 {
Chris@153 663 bool ok = false;
Chris@153 664
Chris@153 665 QString colourSpec = attributes.value("colour");
Chris@153 666 if (colourSpec != "") {
Chris@153 667 QColor colour(colourSpec);
Chris@153 668 if (colour.isValid()) {
Chris@153 669 setBaseColour(QColor(colourSpec));
Chris@153 670 }
Chris@153 671 }
Chris@153 672
Chris@153 673 EnergyScale scale = (EnergyScale)
Chris@153 674 attributes.value("energyScale").toInt(&ok);
Chris@153 675 if (ok) setEnergyScale(scale);
Chris@153 676
Chris@193 677 SamplingMode mode = (SamplingMode)
Chris@193 678 attributes.value("samplingMode").toInt(&ok);
Chris@193 679 if (ok) setSamplingMode(mode);
Chris@153 680
Chris@153 681 float gain = attributes.value("gain").toFloat(&ok);
Chris@153 682 if (ok) setGain(gain);
Chris@153 683
Chris@153 684 bool normalize = (attributes.value("normalize").trimmed() == "true");
Chris@153 685 setNormalize(normalize);
Chris@133 686 }
Chris@133 687
Chris@133 688 bool
Chris@193 689 SliceLayer::getValueExtents(float &min, float &max, bool &logarithmic,
Chris@133 690 QString &units) const
Chris@133 691 {
Chris@133 692 return false;
Chris@133 693 }
Chris@133 694