annotate layer/TimeValueLayer.cpp @ 77:fd348f36c0d3

* Implement harmonic cursor in spectrogram * Implement layer export. This doesn't quite do the right thing for the SV XML layer export yet -- it doesn't include layer display information, so when imported, it only creates an invisible model. Could also do with fixing CSV file import so as to work correctly for note and text layers.
author Chris Cannam
date Mon, 10 Apr 2006 17:22:59 +0000
parents 45ba0b381c5d
children 19bf27e4fb29
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 "TimeValueLayer.h"
Chris@0 17
Chris@0 18 #include "base/Model.h"
Chris@0 19 #include "base/RealTime.h"
Chris@0 20 #include "base/Profiler.h"
Chris@0 21 #include "base/View.h"
Chris@0 22
Chris@0 23 #include "model/SparseTimeValueModel.h"
Chris@0 24
Chris@70 25 #include "widgets/ItemEditDialog.h"
Chris@70 26
Chris@66 27 #include "SpectrogramLayer.h" // for optional frequency alignment
Chris@66 28
Chris@0 29 #include <QPainter>
Chris@6 30 #include <QPainterPath>
Chris@21 31 #include <QMouseEvent>
Chris@0 32
Chris@0 33 #include <iostream>
Chris@0 34 #include <cmath>
Chris@0 35
Chris@44 36 TimeValueLayer::TimeValueLayer() :
Chris@44 37 Layer(),
Chris@0 38 m_model(0),
Chris@21 39 m_editing(false),
Chris@23 40 m_originalPoint(0, 0.0, tr("New Point")),
Chris@21 41 m_editingPoint(0, 0.0, tr("New Point")),
Chris@22 42 m_editingCommand(0),
Chris@67 43 m_colour(Qt::darkGreen),
Chris@66 44 m_plotStyle(PlotConnectedPoints),
Chris@66 45 m_verticalScale(LinearScale)
Chris@0 46 {
Chris@44 47
Chris@0 48 }
Chris@0 49
Chris@0 50 void
Chris@0 51 TimeValueLayer::setModel(SparseTimeValueModel *model)
Chris@0 52 {
Chris@0 53 if (m_model == model) return;
Chris@0 54 m_model = model;
Chris@0 55
Chris@0 56 connect(m_model, SIGNAL(modelChanged()), this, SIGNAL(modelChanged()));
Chris@0 57 connect(m_model, SIGNAL(modelChanged(size_t, size_t)),
Chris@0 58 this, SIGNAL(modelChanged(size_t, size_t)));
Chris@0 59
Chris@0 60 connect(m_model, SIGNAL(completionChanged()),
Chris@0 61 this, SIGNAL(modelCompletionChanged()));
Chris@0 62
Chris@0 63 std::cerr << "TimeValueLayer::setModel(" << model << ")" << std::endl;
Chris@0 64
Chris@0 65 emit modelReplaced();
Chris@0 66 }
Chris@0 67
Chris@0 68 Layer::PropertyList
Chris@0 69 TimeValueLayer::getProperties() const
Chris@0 70 {
Chris@0 71 PropertyList list;
Chris@0 72 list.push_back(tr("Colour"));
Chris@0 73 list.push_back(tr("Plot Type"));
Chris@66 74 list.push_back(tr("Vertical Scale"));
Chris@0 75 return list;
Chris@0 76 }
Chris@0 77
Chris@0 78 Layer::PropertyType
Chris@0 79 TimeValueLayer::getPropertyType(const PropertyName &name) const
Chris@0 80 {
Chris@0 81 return ValueProperty;
Chris@0 82 }
Chris@0 83
Chris@0 84 int
Chris@0 85 TimeValueLayer::getPropertyRangeAndValue(const PropertyName &name,
Chris@0 86 int *min, int *max) const
Chris@0 87 {
Chris@0 88 //!!! factor this colour handling stuff out into a colour manager class
Chris@0 89
Chris@0 90 int deft = 0;
Chris@0 91
Chris@0 92 if (name == tr("Colour")) {
Chris@0 93
Chris@10 94 if (min) *min = 0;
Chris@10 95 if (max) *max = 5;
Chris@0 96
Chris@0 97 if (m_colour == Qt::black) deft = 0;
Chris@0 98 else if (m_colour == Qt::darkRed) deft = 1;
Chris@0 99 else if (m_colour == Qt::darkBlue) deft = 2;
Chris@0 100 else if (m_colour == Qt::darkGreen) deft = 3;
Chris@0 101 else if (m_colour == QColor(200, 50, 255)) deft = 4;
Chris@0 102 else if (m_colour == QColor(255, 150, 50)) deft = 5;
Chris@0 103
Chris@0 104 } else if (name == tr("Plot Type")) {
Chris@0 105
Chris@10 106 if (min) *min = 0;
Chris@26 107 if (max) *max = 5;
Chris@0 108
Chris@0 109 deft = int(m_plotStyle);
Chris@0 110
Chris@66 111 } else if (name == tr("Vertical Scale")) {
Chris@66 112
Chris@66 113 if (min) *min = 0;
Chris@66 114 if (max) *max = 3;
Chris@66 115
Chris@66 116 deft = int(m_verticalScale);
Chris@66 117
Chris@0 118 } else {
Chris@0 119
Chris@0 120 deft = Layer::getPropertyRangeAndValue(name, min, max);
Chris@0 121 }
Chris@0 122
Chris@0 123 return deft;
Chris@0 124 }
Chris@0 125
Chris@0 126 QString
Chris@0 127 TimeValueLayer::getPropertyValueLabel(const PropertyName &name,
Chris@0 128 int value) const
Chris@0 129 {
Chris@0 130 if (name == tr("Colour")) {
Chris@0 131 switch (value) {
Chris@0 132 default:
Chris@0 133 case 0: return tr("Black");
Chris@0 134 case 1: return tr("Red");
Chris@0 135 case 2: return tr("Blue");
Chris@0 136 case 3: return tr("Green");
Chris@0 137 case 4: return tr("Purple");
Chris@0 138 case 5: return tr("Orange");
Chris@0 139 }
Chris@0 140 } else if (name == tr("Plot Type")) {
Chris@0 141 switch (value) {
Chris@0 142 default:
Chris@0 143 case 0: return tr("Points");
Chris@0 144 case 1: return tr("Stems");
Chris@6 145 case 2: return tr("Connected Points");
Chris@6 146 case 3: return tr("Lines");
Chris@6 147 case 4: return tr("Curve");
Chris@26 148 case 5: return tr("Segmentation");
Chris@0 149 }
Chris@66 150 } else if (name == tr("Vertical Scale")) {
Chris@66 151 switch (value) {
Chris@66 152 default:
Chris@66 153 case 0: return tr("Linear Scale");
Chris@66 154 case 1: return tr("Log Scale");
Chris@66 155 case 2: return tr("+/-1 Scale");
Chris@66 156 case 3: return tr("Frequency Scale");
Chris@66 157 }
Chris@0 158 }
Chris@0 159 return tr("<unknown>");
Chris@0 160 }
Chris@0 161
Chris@0 162 void
Chris@0 163 TimeValueLayer::setProperty(const PropertyName &name, int value)
Chris@0 164 {
Chris@0 165 if (name == tr("Colour")) {
Chris@0 166 switch (value) {
Chris@0 167 default:
Chris@0 168 case 0: setBaseColour(Qt::black); break;
Chris@0 169 case 1: setBaseColour(Qt::darkRed); break;
Chris@0 170 case 2: setBaseColour(Qt::darkBlue); break;
Chris@0 171 case 3: setBaseColour(Qt::darkGreen); break;
Chris@0 172 case 4: setBaseColour(QColor(200, 50, 255)); break;
Chris@0 173 case 5: setBaseColour(QColor(255, 150, 50)); break;
Chris@0 174 }
Chris@0 175 } else if (name == tr("Plot Type")) {
Chris@0 176 setPlotStyle(PlotStyle(value));
Chris@66 177 } else if (name == tr("Vertical Scale")) {
Chris@66 178 setVerticalScale(VerticalScale(value));
Chris@0 179 }
Chris@0 180 }
Chris@0 181
Chris@0 182 void
Chris@0 183 TimeValueLayer::setBaseColour(QColor colour)
Chris@0 184 {
Chris@0 185 if (m_colour == colour) return;
Chris@0 186 m_colour = colour;
Chris@0 187 emit layerParametersChanged();
Chris@0 188 }
Chris@0 189
Chris@0 190 void
Chris@0 191 TimeValueLayer::setPlotStyle(PlotStyle style)
Chris@0 192 {
Chris@0 193 if (m_plotStyle == style) return;
Chris@0 194 m_plotStyle = style;
Chris@0 195 emit layerParametersChanged();
Chris@0 196 }
Chris@0 197
Chris@66 198 void
Chris@66 199 TimeValueLayer::setVerticalScale(VerticalScale scale)
Chris@66 200 {
Chris@66 201 if (m_verticalScale == scale) return;
Chris@66 202 m_verticalScale = scale;
Chris@66 203 emit layerParametersChanged();
Chris@66 204 }
Chris@66 205
Chris@0 206 bool
Chris@44 207 TimeValueLayer::isLayerScrollable(const View *v) const
Chris@0 208 {
Chris@6 209 // We don't illuminate sections in the line or curve modes, so
Chris@6 210 // they're always scrollable
Chris@6 211
Chris@6 212 if (m_plotStyle == PlotLines ||
Chris@6 213 m_plotStyle == PlotCurve) return true;
Chris@6 214
Chris@0 215 QPoint discard;
Chris@44 216 return !v->shouldIlluminateLocalFeatures(this, discard);
Chris@0 217 }
Chris@0 218
Chris@0 219 SparseTimeValueModel::PointList
Chris@44 220 TimeValueLayer::getLocalPoints(View *v, int x) const
Chris@0 221 {
Chris@0 222 if (!m_model) return SparseTimeValueModel::PointList();
Chris@0 223
Chris@44 224 long frame = v->getFrameForX(x);
Chris@0 225
Chris@0 226 SparseTimeValueModel::PointList onPoints =
Chris@0 227 m_model->getPoints(frame);
Chris@0 228
Chris@0 229 if (!onPoints.empty()) {
Chris@0 230 return onPoints;
Chris@0 231 }
Chris@0 232
Chris@0 233 SparseTimeValueModel::PointList prevPoints =
Chris@0 234 m_model->getPreviousPoints(frame);
Chris@0 235 SparseTimeValueModel::PointList nextPoints =
Chris@0 236 m_model->getNextPoints(frame);
Chris@0 237
Chris@0 238 SparseTimeValueModel::PointList usePoints = prevPoints;
Chris@0 239
Chris@0 240 if (prevPoints.empty()) {
Chris@0 241 usePoints = nextPoints;
Chris@44 242 } else if (prevPoints.begin()->frame < v->getStartFrame() &&
Chris@44 243 !(nextPoints.begin()->frame > v->getEndFrame())) {
Chris@0 244 usePoints = nextPoints;
Chris@0 245 } else if (nextPoints.begin()->frame - frame <
Chris@0 246 frame - prevPoints.begin()->frame) {
Chris@0 247 usePoints = nextPoints;
Chris@0 248 }
Chris@0 249
Chris@28 250 if (!usePoints.empty()) {
Chris@28 251 int fuzz = 2;
Chris@44 252 int px = v->getXForFrame(usePoints.begin()->frame);
Chris@28 253 if ((px > x && px - x > fuzz) ||
Chris@28 254 (px < x && x - px > fuzz + 1)) {
Chris@28 255 usePoints.clear();
Chris@28 256 }
Chris@28 257 }
Chris@28 258
Chris@0 259 return usePoints;
Chris@0 260 }
Chris@0 261
Chris@25 262 QString
Chris@44 263 TimeValueLayer::getFeatureDescription(View *v, QPoint &pos) const
Chris@0 264 {
Chris@25 265 int x = pos.x();
Chris@0 266
Chris@25 267 if (!m_model || !m_model->getSampleRate()) return "";
Chris@0 268
Chris@44 269 SparseTimeValueModel::PointList points = getLocalPoints(v, x);
Chris@0 270
Chris@0 271 if (points.empty()) {
Chris@0 272 if (!m_model->isReady()) {
Chris@25 273 return tr("In progress");
Chris@25 274 } else {
Chris@25 275 return tr("No local points");
Chris@0 276 }
Chris@0 277 }
Chris@0 278
Chris@0 279 long useFrame = points.begin()->frame;
Chris@0 280
Chris@0 281 RealTime rt = RealTime::frame2RealTime(useFrame, m_model->getSampleRate());
Chris@25 282
Chris@25 283 QString text;
Chris@0 284
Chris@25 285 if (points.begin()->label == "") {
Chris@25 286 text = QString(tr("Time:\t%1\nValue:\t%2\nNo label"))
Chris@25 287 .arg(rt.toText(true).c_str())
Chris@25 288 .arg(points.begin()->value);
Chris@25 289 } else {
Chris@25 290 text = QString(tr("Time:\t%1\nValue:\t%2\nLabel:\t%3"))
Chris@25 291 .arg(rt.toText(true).c_str())
Chris@25 292 .arg(points.begin()->value)
Chris@25 293 .arg(points.begin()->label);
Chris@25 294 }
Chris@0 295
Chris@44 296 pos = QPoint(v->getXForFrame(useFrame),
Chris@44 297 getYForValue(v, points.begin()->value));
Chris@25 298 return text;
Chris@0 299 }
Chris@0 300
Chris@28 301 bool
Chris@44 302 TimeValueLayer::snapToFeatureFrame(View *v, int &frame,
Chris@28 303 size_t &resolution,
Chris@28 304 SnapType snap) const
Chris@13 305 {
Chris@13 306 if (!m_model) {
Chris@44 307 return Layer::snapToFeatureFrame(v, frame, resolution, snap);
Chris@13 308 }
Chris@13 309
Chris@13 310 resolution = m_model->getResolution();
Chris@28 311 SparseTimeValueModel::PointList points;
Chris@13 312
Chris@28 313 if (snap == SnapNeighbouring) {
Chris@28 314
Chris@44 315 points = getLocalPoints(v, v->getXForFrame(frame));
Chris@28 316 if (points.empty()) return false;
Chris@28 317 frame = points.begin()->frame;
Chris@28 318 return true;
Chris@28 319 }
Chris@28 320
Chris@28 321 points = m_model->getPoints(frame, frame);
Chris@28 322 int snapped = frame;
Chris@28 323 bool found = false;
Chris@13 324
Chris@13 325 for (SparseTimeValueModel::PointList::const_iterator i = points.begin();
Chris@13 326 i != points.end(); ++i) {
Chris@13 327
Chris@28 328 if (snap == SnapRight) {
Chris@28 329
Chris@13 330 if (i->frame > frame) {
Chris@28 331 snapped = i->frame;
Chris@28 332 found = true;
Chris@13 333 break;
Chris@13 334 }
Chris@28 335
Chris@28 336 } else if (snap == SnapLeft) {
Chris@28 337
Chris@13 338 if (i->frame <= frame) {
Chris@28 339 snapped = i->frame;
Chris@28 340 found = true; // don't break, as the next may be better
Chris@28 341 } else {
Chris@28 342 break;
Chris@28 343 }
Chris@28 344
Chris@28 345 } else { // nearest
Chris@28 346
Chris@28 347 SparseTimeValueModel::PointList::const_iterator j = i;
Chris@28 348 ++j;
Chris@28 349
Chris@28 350 if (j == points.end()) {
Chris@28 351
Chris@28 352 snapped = i->frame;
Chris@28 353 found = true;
Chris@28 354 break;
Chris@28 355
Chris@28 356 } else if (j->frame >= frame) {
Chris@28 357
Chris@28 358 if (j->frame - frame < frame - i->frame) {
Chris@28 359 snapped = j->frame;
Chris@28 360 } else {
Chris@28 361 snapped = i->frame;
Chris@28 362 }
Chris@28 363 found = true;
Chris@28 364 break;
Chris@13 365 }
Chris@13 366 }
Chris@13 367 }
Chris@13 368
Chris@28 369 frame = snapped;
Chris@28 370 return found;
Chris@13 371 }
Chris@13 372
Chris@21 373 int
Chris@66 374 TimeValueLayer::getYForValue(View *v, float val) const
Chris@21 375 {
Chris@21 376 float min = m_model->getValueMinimum();
Chris@21 377 float max = m_model->getValueMaximum();
Chris@21 378 if (max == min) max = min + 1.0;
Chris@21 379
Chris@44 380 int h = v->height();
Chris@21 381
Chris@66 382 if (m_verticalScale == FrequencyScale || m_verticalScale == LogScale) {
Chris@66 383
Chris@66 384 if (m_verticalScale == FrequencyScale) {
Chris@66 385 // If we have a spectrogram layer on the same view as us, align
Chris@66 386 // ourselves with it...
Chris@66 387 for (int i = 0; i < v->getLayerCount(); ++i) {
Chris@66 388 SpectrogramLayer *spectrogram = dynamic_cast<SpectrogramLayer *>
Chris@66 389 (v->getLayer(i));
Chris@66 390 if (spectrogram) {
Chris@66 391 return spectrogram->getYForFrequency(v, val);
Chris@66 392 }
Chris@66 393 }
Chris@66 394 }
Chris@66 395
Chris@66 396 min = (min < 0.0) ? -log10(-min) : (min == 0.0) ? 0.0 : log10(min);
Chris@66 397 max = (max < 0.0) ? -log10(-max) : (max == 0.0) ? 0.0 : log10(max);
Chris@66 398 val = (val < 0.0) ? -log10(-val) : (val == 0.0) ? 0.0 : log10(val);
Chris@66 399
Chris@66 400 } else if (m_verticalScale == PlusMinusOneScale) {
Chris@66 401 min = -1.0;
Chris@66 402 max = 1.0;
Chris@66 403 }
Chris@66 404
Chris@66 405 return int(h - ((val - min) * h) / (max - min));
Chris@21 406 }
Chris@21 407
Chris@21 408 float
Chris@44 409 TimeValueLayer::getValueForY(View *v, int y) const
Chris@21 410 {
Chris@66 411 //!!!
Chris@66 412
Chris@21 413 float min = m_model->getValueMinimum();
Chris@21 414 float max = m_model->getValueMaximum();
Chris@21 415 if (max == min) max = min + 1.0;
Chris@21 416
Chris@44 417 int h = v->height();
Chris@21 418
Chris@21 419 return min + (float(h - y) * float(max - min)) / h;
Chris@21 420 }
Chris@21 421
Chris@68 422 QColor
Chris@68 423 TimeValueLayer::getColourForValue(float val) const
Chris@68 424 {
Chris@68 425 float min = m_model->getValueMinimum();
Chris@68 426 float max = m_model->getValueMaximum();
Chris@68 427 if (max == min) max = min + 1.0;
Chris@68 428
Chris@68 429 if (m_verticalScale == FrequencyScale || m_verticalScale == LogScale) {
Chris@68 430 min = (min < 0.0) ? -log10(-min) : (min == 0.0) ? 0.0 : log10(min);
Chris@68 431 max = (max < 0.0) ? -log10(-max) : (max == 0.0) ? 0.0 : log10(max);
Chris@68 432 val = (val < 0.0) ? -log10(-val) : (val == 0.0) ? 0.0 : log10(val);
Chris@68 433 } else if (m_verticalScale == PlusMinusOneScale) {
Chris@68 434 min = -1.0;
Chris@68 435 max = 1.0;
Chris@68 436 }
Chris@68 437
Chris@68 438 int iv = ((val - min) / (max - min)) * 255.999;
Chris@68 439
Chris@68 440 QColor colour = QColor::fromHsv(256 - iv, iv / 2 + 128, iv);
Chris@68 441 return QColor(colour.red(), colour.green(), colour.blue(), 120);
Chris@68 442 }
Chris@68 443
Chris@0 444 void
Chris@44 445 TimeValueLayer::paint(View *v, QPainter &paint, QRect rect) const
Chris@0 446 {
Chris@0 447 if (!m_model || !m_model->isOK()) return;
Chris@0 448
Chris@0 449 int sampleRate = m_model->getSampleRate();
Chris@0 450 if (!sampleRate) return;
Chris@0 451
Chris@0 452 // Profiler profiler("TimeValueLayer::paint", true);
Chris@0 453
Chris@0 454 int x0 = rect.left(), x1 = rect.right();
Chris@44 455 long frame0 = v->getFrameForX(x0);
Chris@44 456 long frame1 = v->getFrameForX(x1);
Chris@0 457
Chris@0 458 SparseTimeValueModel::PointList points(m_model->getPoints
Chris@0 459 (frame0, frame1));
Chris@11 460 if (points.empty()) return;
Chris@0 461
Chris@0 462 paint.setPen(m_colour);
Chris@0 463
Chris@0 464 QColor brushColour(m_colour);
Chris@0 465 brushColour.setAlpha(80);
Chris@0 466 paint.setBrush(brushColour);
Chris@0 467
Chris@0 468 // std::cerr << "TimeValueLayer::paint: resolution is "
Chris@0 469 // << m_model->getResolution() << " frames" << std::endl;
Chris@0 470
Chris@0 471 float min = m_model->getValueMinimum();
Chris@0 472 float max = m_model->getValueMaximum();
Chris@0 473 if (max == min) max = min + 1.0;
Chris@0 474
Chris@44 475 int origin = int(nearbyint(v->height() -
Chris@44 476 (-min * v->height()) / (max - min)));
Chris@0 477
Chris@0 478 QPoint localPos;
Chris@0 479 long illuminateFrame = -1;
Chris@0 480
Chris@44 481 if (v->shouldIlluminateLocalFeatures(this, localPos)) {
Chris@0 482 SparseTimeValueModel::PointList localPoints =
Chris@44 483 getLocalPoints(v, localPos.x());
Chris@0 484 if (!localPoints.empty()) illuminateFrame = localPoints.begin()->frame;
Chris@0 485 }
Chris@6 486
Chris@20 487 int w =
Chris@44 488 v->getXForFrame(frame0 + m_model->getResolution()) -
Chris@44 489 v->getXForFrame(frame0);
Chris@7 490
Chris@6 491 paint.save();
Chris@6 492
Chris@6 493 QPainterPath path;
Chris@55 494 int pointCount = 0;
Chris@6 495
Chris@0 496 for (SparseTimeValueModel::PointList::const_iterator i = points.begin();
Chris@0 497 i != points.end(); ++i) {
Chris@0 498
Chris@0 499 const SparseTimeValueModel::Point &p(*i);
Chris@0 500
Chris@44 501 int x = v->getXForFrame(p.frame);
Chris@44 502 int y = getYForValue(v, p.value);
Chris@0 503
Chris@34 504 bool haveNext = false;
Chris@76 505 int nx = v->getXForFrame(v->getModelsEndFrame());
Chris@76 506 // m_model->getEndFrame());
Chris@34 507 int ny = y;
Chris@34 508
Chris@34 509 SparseTimeValueModel::PointList::const_iterator j = i;
Chris@34 510 ++j;
Chris@34 511
Chris@34 512 if (j != points.end()) {
Chris@34 513 const SparseTimeValueModel::Point &q(*j);
Chris@44 514 nx = v->getXForFrame(q.frame);
Chris@44 515 ny = getYForValue(v, q.value);
Chris@34 516 haveNext = true;
Chris@76 517 }
Chris@76 518
Chris@76 519 // std::cout << "frame = " << p.frame << ", x = " << x << ", haveNext = " << haveNext
Chris@76 520 // << ", nx = " << nx << std::endl;
Chris@34 521
Chris@34 522 int labelY = y;
Chris@34 523
Chris@0 524 if (w < 1) w = 1;
Chris@26 525 paint.setPen(m_colour);
Chris@0 526
Chris@26 527 if (m_plotStyle == PlotSegmentation) {
Chris@68 528 paint.setBrush(getColourForValue(p.value));
Chris@44 529 labelY = v->height();
Chris@26 530 } else if (m_plotStyle == PlotLines ||
Chris@26 531 m_plotStyle == PlotCurve) {
Chris@6 532 paint.setBrush(Qt::NoBrush);
Chris@3 533 } else {
Chris@6 534 paint.setBrush(brushColour);
Chris@3 535 }
Chris@0 536
Chris@0 537 if (m_plotStyle == PlotStems) {
Chris@0 538 paint.setPen(brushColour);
Chris@0 539 if (y < origin - 1) {
Chris@0 540 paint.drawRect(x + w/2, y + 1, 1, origin - y);
Chris@0 541 } else if (y > origin + 1) {
Chris@0 542 paint.drawRect(x + w/2, origin, 1, y - origin - 1);
Chris@0 543 }
Chris@0 544 paint.setPen(m_colour);
Chris@0 545 }
Chris@0 546
Chris@0 547 if (illuminateFrame == p.frame) {
Chris@6 548
Chris@0 549 //!!! aside from the problem of choosing a colour, it'd be
Chris@0 550 //better to save the highlighted rects and draw them at
Chris@0 551 //the end perhaps
Chris@6 552
Chris@6 553 //!!! not equipped to illuminate the right section in line
Chris@6 554 //or curve mode
Chris@6 555
Chris@6 556 if (m_plotStyle != PlotCurve &&
Chris@6 557 m_plotStyle != PlotLines) {
Chris@6 558 paint.setPen(Qt::black);//!!!
Chris@26 559 if (m_plotStyle != PlotSegmentation) {
Chris@26 560 paint.setBrush(Qt::black);//!!!
Chris@26 561 }
Chris@6 562 }
Chris@0 563 }
Chris@0 564
Chris@6 565 if (m_plotStyle != PlotLines &&
Chris@26 566 m_plotStyle != PlotCurve &&
Chris@26 567 m_plotStyle != PlotSegmentation) {
Chris@3 568 paint.drawRect(x, y - 1, w, 2);
Chris@3 569 }
Chris@0 570
Chris@6 571 if (m_plotStyle == PlotConnectedPoints ||
Chris@6 572 m_plotStyle == PlotLines ||
Chris@6 573 m_plotStyle == PlotCurve) {
Chris@0 574
Chris@34 575 if (haveNext) {
Chris@3 576
Chris@6 577 if (m_plotStyle == PlotConnectedPoints) {
Chris@34 578
Chris@3 579 paint.setPen(brushColour);
Chris@3 580 paint.drawLine(x + w, y, nx, ny);
Chris@6 581
Chris@6 582 } else if (m_plotStyle == PlotLines) {
Chris@6 583
Chris@6 584 paint.drawLine(x + w/2, y, nx + w/2, ny);
Chris@6 585
Chris@3 586 } else {
Chris@6 587
Chris@55 588 float x0 = x + float(w)/2;
Chris@55 589 float x1 = nx + float(w)/2;
Chris@55 590
Chris@55 591 float y0 = y;
Chris@55 592 float y1 = ny;
Chris@55 593
Chris@55 594 if (pointCount == 0) {
Chris@55 595 path.moveTo((x0 + x1) / 2, (y0 + y1) / 2);
Chris@6 596 }
Chris@55 597 ++pointCount;
Chris@6 598
Chris@6 599 if (nx - x > 5) {
Chris@55 600 path.cubicTo(x0, y0,
Chris@55 601 x0, y0,
Chris@55 602 (x0 + x1) / 2, (y0 + y1) / 2);
Chris@55 603
Chris@55 604 // // or
Chris@55 605 // path.quadTo(x0, y0, (x0 + x1) / 2, (y0 + y1) / 2);
Chris@55 606
Chris@6 607 } else {
Chris@55 608 path.lineTo((x0 + x1) / 2, (y0 + y1) / 2);
Chris@6 609 }
Chris@3 610 }
Chris@0 611 }
Chris@0 612 }
Chris@0 613
Chris@26 614 if (m_plotStyle == PlotSegmentation) {
Chris@76 615
Chris@76 616 // std::cerr << "drawing rect" << std::endl;
Chris@26 617
Chris@27 618 if (nx <= x) continue;
Chris@26 619
Chris@28 620 if (illuminateFrame != p.frame &&
Chris@44 621 (nx < x + 5 || x >= v->width() - 1)) {
Chris@27 622 paint.setPen(Qt::NoPen);
Chris@27 623 }
Chris@26 624
Chris@44 625 paint.drawRect(x, -1, nx - x, v->height() + 1);
Chris@26 626 }
Chris@26 627
Chris@55 628 if (p.label != "") {
Chris@55 629 paint.drawText(x + 5, y - paint.fontMetrics().height() + paint.fontMetrics().ascent(), p.label);
Chris@55 630 }
Chris@0 631 }
Chris@6 632
Chris@6 633 if (m_plotStyle == PlotCurve && !path.isEmpty()) {
Chris@55 634 paint.setRenderHint(QPainter::Antialiasing, pointCount <= v->width());
Chris@6 635 paint.drawPath(path);
Chris@6 636 }
Chris@6 637
Chris@6 638 paint.restore();
Chris@6 639
Chris@6 640 // looks like save/restore doesn't deal with this:
Chris@6 641 paint.setRenderHint(QPainter::Antialiasing, false);
Chris@6 642 }
Chris@6 643
Chris@42 644 int
Chris@44 645 TimeValueLayer::getVerticalScaleWidth(View *v, QPainter &paint) const
Chris@42 646 {
Chris@68 647 int w = paint.fontMetrics().width("-000.000");
Chris@68 648 if (m_plotStyle == PlotSegmentation) return w + 20;
Chris@68 649 else return w + 10;
Chris@42 650 }
Chris@42 651
Chris@42 652 void
Chris@44 653 TimeValueLayer::paintVerticalScale(View *v, QPainter &paint, QRect rect) const
Chris@42 654 {
Chris@42 655 if (!m_model) return;
Chris@42 656
Chris@68 657 int h = v->height();
Chris@68 658
Chris@68 659 int n = 10;
Chris@68 660
Chris@68 661 float max = m_model->getValueMaximum();
Chris@68 662 float min = m_model->getValueMinimum();
Chris@68 663 float val = min;
Chris@68 664 float inc = (max - val) / n;
Chris@42 665
Chris@55 666 char buffer[40];
Chris@55 667
Chris@55 668 int w = getVerticalScaleWidth(v, paint);
Chris@55 669
Chris@68 670 int tx = 5;
Chris@68 671
Chris@68 672 int boxx = 5, boxy = 5;
Chris@68 673 if (m_model->getScaleUnits() != "") {
Chris@68 674 boxy += paint.fontMetrics().height();
Chris@68 675 }
Chris@68 676 int boxw = 10, boxh = h - boxy - 5;
Chris@68 677
Chris@68 678 if (m_plotStyle == PlotSegmentation) {
Chris@68 679 tx += boxx + boxw;
Chris@68 680 paint.drawRect(boxx, boxy, boxw, boxh);
Chris@68 681 }
Chris@68 682
Chris@68 683 if (m_plotStyle == PlotSegmentation) {
Chris@68 684 paint.save();
Chris@68 685 for (int y = 0; y < boxh; ++y) {
Chris@68 686 float val = ((boxh - y) * (max - min)) / boxh + min;
Chris@68 687 paint.setPen(getColourForValue(val));
Chris@68 688 paint.drawLine(boxx + 1, y + boxy + 1, boxx + boxw, y + boxy + 1);
Chris@68 689 }
Chris@68 690 paint.restore();
Chris@68 691 }
Chris@68 692
Chris@68 693 for (int i = 0; i < n; ++i) {
Chris@68 694
Chris@68 695 int y, ty;
Chris@68 696 bool drawText = true;
Chris@68 697
Chris@68 698 if (m_plotStyle == PlotSegmentation) {
Chris@68 699 y = boxy + int(boxh - ((val - min) * boxh) / (max - min));
Chris@68 700 ty = y;
Chris@68 701 } else {
Chris@68 702 if (i == n-1) {
Chris@68 703 if (m_model->getScaleUnits() != "") drawText = false;
Chris@68 704 }
Chris@68 705 y = getYForValue(v, val);
Chris@68 706 ty = y - paint.fontMetrics().height() +
Chris@68 707 paint.fontMetrics().ascent();
Chris@68 708 }
Chris@68 709
Chris@68 710 sprintf(buffer, "%.3f", val);
Chris@55 711 QString label = QString(buffer);
Chris@68 712
Chris@68 713 if (m_plotStyle != PlotSegmentation) {
Chris@68 714 paint.drawLine(w - 5, y, w, y);
Chris@68 715 } else {
Chris@68 716 paint.drawLine(boxx + boxw - boxw/3, y, boxx + boxw, y);
Chris@68 717 }
Chris@68 718
Chris@68 719 if (drawText) paint.drawText(tx, ty, label);
Chris@44 720 val += inc;
Chris@42 721 }
Chris@68 722
Chris@67 723 if (m_model->getScaleUnits() != "") {
Chris@67 724 paint.drawText(5, 5 + paint.fontMetrics().ascent(),
Chris@67 725 m_model->getScaleUnits());
Chris@67 726 }
Chris@42 727 }
Chris@42 728
Chris@21 729 void
Chris@44 730 TimeValueLayer::drawStart(View *v, QMouseEvent *e)
Chris@21 731 {
Chris@21 732 std::cerr << "TimeValueLayer::drawStart(" << e->x() << "," << e->y() << ")" << std::endl;
Chris@21 733
Chris@21 734 if (!m_model) return;
Chris@21 735
Chris@44 736 long frame = v->getFrameForX(e->x());
Chris@76 737 long resolution = m_model->getResolution();
Chris@21 738 if (frame < 0) frame = 0;
Chris@76 739 frame = (frame / resolution) * resolution;
Chris@21 740
Chris@44 741 float value = getValueForY(v, e->y());
Chris@21 742
Chris@76 743 bool havePoint = false;
Chris@76 744
Chris@76 745 SparseTimeValueModel::PointList points = getLocalPoints(v, e->x());
Chris@76 746 if (!points.empty()) {
Chris@76 747 for (SparseTimeValueModel::PointList::iterator i = points.begin();
Chris@76 748 i != points.end(); ++i) {
Chris@76 749 if (((i->frame / resolution) * resolution) != frame) {
Chris@76 750 std::cerr << "ignoring out-of-range frame at " << i->frame << std::endl;
Chris@76 751 continue;
Chris@76 752 }
Chris@76 753 m_editingPoint = *i;
Chris@76 754 havePoint = true;
Chris@76 755 }
Chris@76 756 }
Chris@76 757
Chris@76 758 if (!havePoint) {
Chris@76 759 m_editingPoint = SparseTimeValueModel::Point
Chris@76 760 (frame, value, tr("New Point"));
Chris@76 761 }
Chris@76 762
Chris@23 763 m_originalPoint = m_editingPoint;
Chris@22 764
Chris@22 765 if (m_editingCommand) m_editingCommand->finish();
Chris@22 766 m_editingCommand = new SparseTimeValueModel::EditCommand(m_model,
Chris@22 767 tr("Draw Point"));
Chris@76 768 if (!havePoint) {
Chris@76 769 m_editingCommand->addPoint(m_editingPoint);
Chris@76 770 }
Chris@22 771
Chris@21 772 m_editing = true;
Chris@21 773 }
Chris@21 774
Chris@21 775 void
Chris@44 776 TimeValueLayer::drawDrag(View *v, QMouseEvent *e)
Chris@21 777 {
Chris@21 778 std::cerr << "TimeValueLayer::drawDrag(" << e->x() << "," << e->y() << ")" << std::endl;
Chris@21 779
Chris@21 780 if (!m_model || !m_editing) return;
Chris@21 781
Chris@44 782 long frame = v->getFrameForX(e->x());
Chris@76 783 long resolution = m_model->getResolution();
Chris@21 784 if (frame < 0) frame = 0;
Chris@76 785 frame = (frame / resolution) * resolution;
Chris@21 786
Chris@44 787 float value = getValueForY(v, e->y());
Chris@21 788
Chris@76 789 SparseTimeValueModel::PointList points = getLocalPoints(v, e->x());
Chris@76 790
Chris@76 791 std::cerr << points.size() << " points" << std::endl;
Chris@76 792
Chris@76 793 bool havePoint = false;
Chris@76 794
Chris@76 795 if (!points.empty()) {
Chris@76 796 for (SparseTimeValueModel::PointList::iterator i = points.begin();
Chris@76 797 i != points.end(); ++i) {
Chris@76 798 if (i->frame == m_editingPoint.frame &&
Chris@76 799 i->value == m_editingPoint.value) {
Chris@76 800 std::cerr << "ignoring current editing point at " << i->frame << ", " << i->value << std::endl;
Chris@76 801 continue;
Chris@76 802 }
Chris@76 803 if (((i->frame / resolution) * resolution) != frame) {
Chris@76 804 std::cerr << "ignoring out-of-range frame at " << i->frame << std::endl;
Chris@76 805 continue;
Chris@76 806 }
Chris@76 807 std::cerr << "adjusting to new point at " << i->frame << ", " << i->value << std::endl;
Chris@76 808 m_editingPoint = *i;
Chris@76 809 m_originalPoint = m_editingPoint;
Chris@76 810 m_editingCommand->deletePoint(m_editingPoint);
Chris@76 811 havePoint = true;
Chris@76 812 }
Chris@76 813 }
Chris@76 814
Chris@76 815 if (!havePoint) {
Chris@76 816 if (frame == m_editingPoint.frame) {
Chris@76 817 m_editingCommand->deletePoint(m_editingPoint);
Chris@76 818 }
Chris@76 819 }
Chris@76 820
Chris@76 821 // m_editingCommand->deletePoint(m_editingPoint);
Chris@21 822 m_editingPoint.frame = frame;
Chris@21 823 m_editingPoint.value = value;
Chris@22 824 m_editingCommand->addPoint(m_editingPoint);
Chris@21 825 }
Chris@21 826
Chris@21 827 void
Chris@44 828 TimeValueLayer::drawEnd(View *v, QMouseEvent *e)
Chris@21 829 {
Chris@21 830 std::cerr << "TimeValueLayer::drawEnd(" << e->x() << "," << e->y() << ")" << std::endl;
Chris@21 831 if (!m_model || !m_editing) return;
Chris@22 832 m_editingCommand->finish();
Chris@22 833 m_editingCommand = 0;
Chris@21 834 m_editing = false;
Chris@21 835 }
Chris@21 836
Chris@21 837 void
Chris@44 838 TimeValueLayer::editStart(View *v, QMouseEvent *e)
Chris@21 839 {
Chris@21 840 std::cerr << "TimeValueLayer::editStart(" << e->x() << "," << e->y() << ")" << std::endl;
Chris@21 841
Chris@21 842 if (!m_model) return;
Chris@21 843
Chris@44 844 SparseTimeValueModel::PointList points = getLocalPoints(v, e->x());
Chris@21 845 if (points.empty()) return;
Chris@21 846
Chris@21 847 m_editingPoint = *points.begin();
Chris@23 848 m_originalPoint = m_editingPoint;
Chris@22 849
Chris@22 850 if (m_editingCommand) {
Chris@22 851 m_editingCommand->finish();
Chris@22 852 m_editingCommand = 0;
Chris@22 853 }
Chris@22 854
Chris@21 855 m_editing = true;
Chris@21 856 }
Chris@21 857
Chris@21 858 void
Chris@44 859 TimeValueLayer::editDrag(View *v, QMouseEvent *e)
Chris@21 860 {
Chris@21 861 std::cerr << "TimeValueLayer::editDrag(" << e->x() << "," << e->y() << ")" << std::endl;
Chris@21 862
Chris@21 863 if (!m_model || !m_editing) return;
Chris@21 864
Chris@44 865 long frame = v->getFrameForX(e->x());
Chris@21 866 if (frame < 0) frame = 0;
Chris@21 867 frame = frame / m_model->getResolution() * m_model->getResolution();
Chris@21 868
Chris@44 869 float value = getValueForY(v, e->y());
Chris@21 870
Chris@22 871 if (!m_editingCommand) {
Chris@22 872 m_editingCommand = new SparseTimeValueModel::EditCommand(m_model,
Chris@22 873 tr("Drag Point"));
Chris@22 874 }
Chris@22 875
Chris@22 876 m_editingCommand->deletePoint(m_editingPoint);
Chris@21 877 m_editingPoint.frame = frame;
Chris@21 878 m_editingPoint.value = value;
Chris@22 879 m_editingCommand->addPoint(m_editingPoint);
Chris@21 880 }
Chris@21 881
Chris@21 882 void
Chris@44 883 TimeValueLayer::editEnd(View *v, QMouseEvent *e)
Chris@21 884 {
Chris@21 885 std::cerr << "TimeValueLayer::editEnd(" << e->x() << "," << e->y() << ")" << std::endl;
Chris@21 886 if (!m_model || !m_editing) return;
Chris@23 887
Chris@23 888 if (m_editingCommand) {
Chris@23 889
Chris@23 890 QString newName = m_editingCommand->getName();
Chris@23 891
Chris@23 892 if (m_editingPoint.frame != m_originalPoint.frame) {
Chris@23 893 if (m_editingPoint.value != m_originalPoint.value) {
Chris@23 894 newName = tr("Edit Point");
Chris@23 895 } else {
Chris@23 896 newName = tr("Relocate Point");
Chris@23 897 }
Chris@23 898 } else {
Chris@23 899 newName = tr("Change Point Value");
Chris@23 900 }
Chris@23 901
Chris@23 902 m_editingCommand->setName(newName);
Chris@23 903 m_editingCommand->finish();
Chris@23 904 }
Chris@23 905
Chris@22 906 m_editingCommand = 0;
Chris@21 907 m_editing = false;
Chris@21 908 }
Chris@21 909
Chris@43 910 void
Chris@70 911 TimeValueLayer::editOpen(View *v, QMouseEvent *e)
Chris@70 912 {
Chris@70 913 if (!m_model) return;
Chris@70 914
Chris@70 915 SparseTimeValueModel::PointList points = getLocalPoints(v, e->x());
Chris@70 916 if (points.empty()) return;
Chris@70 917
Chris@70 918 SparseTimeValueModel::Point point = *points.begin();
Chris@70 919
Chris@70 920 ItemEditDialog *dialog = new ItemEditDialog
Chris@70 921 (m_model->getSampleRate(),
Chris@70 922 ItemEditDialog::ShowTime |
Chris@70 923 ItemEditDialog::ShowValue |
Chris@73 924 ItemEditDialog::ShowText,
Chris@73 925 m_model->getScaleUnits());
Chris@70 926
Chris@70 927 dialog->setFrameTime(point.frame);
Chris@70 928 dialog->setValue(point.value);
Chris@70 929 dialog->setText(point.label);
Chris@70 930
Chris@70 931 if (dialog->exec() == QDialog::Accepted) {
Chris@70 932
Chris@70 933 SparseTimeValueModel::Point newPoint = point;
Chris@70 934 newPoint.frame = dialog->getFrameTime();
Chris@70 935 newPoint.value = dialog->getValue();
Chris@70 936 newPoint.label = dialog->getText();
Chris@70 937
Chris@70 938 SparseTimeValueModel::EditCommand *command =
Chris@70 939 new SparseTimeValueModel::EditCommand(m_model, tr("Edit Point"));
Chris@70 940 command->deletePoint(point);
Chris@70 941 command->addPoint(newPoint);
Chris@70 942 command->finish();
Chris@70 943 }
Chris@70 944
Chris@70 945 delete dialog;
Chris@70 946 }
Chris@70 947
Chris@70 948 void
Chris@43 949 TimeValueLayer::moveSelection(Selection s, size_t newStartFrame)
Chris@43 950 {
Chris@43 951 SparseTimeValueModel::EditCommand *command =
Chris@43 952 new SparseTimeValueModel::EditCommand(m_model,
Chris@43 953 tr("Drag Selection"));
Chris@43 954
Chris@43 955 SparseTimeValueModel::PointList points =
Chris@43 956 m_model->getPoints(s.getStartFrame(), s.getEndFrame());
Chris@43 957
Chris@43 958 for (SparseTimeValueModel::PointList::iterator i = points.begin();
Chris@43 959 i != points.end(); ++i) {
Chris@43 960
Chris@43 961 if (s.contains(i->frame)) {
Chris@43 962 SparseTimeValueModel::Point newPoint(*i);
Chris@43 963 newPoint.frame = i->frame + newStartFrame - s.getStartFrame();
Chris@43 964 command->deletePoint(*i);
Chris@43 965 command->addPoint(newPoint);
Chris@43 966 }
Chris@43 967 }
Chris@43 968
Chris@43 969 command->finish();
Chris@43 970 }
Chris@43 971
Chris@43 972 void
Chris@43 973 TimeValueLayer::resizeSelection(Selection s, Selection newSize)
Chris@43 974 {
Chris@43 975 SparseTimeValueModel::EditCommand *command =
Chris@43 976 new SparseTimeValueModel::EditCommand(m_model,
Chris@43 977 tr("Resize Selection"));
Chris@43 978
Chris@43 979 SparseTimeValueModel::PointList points =
Chris@43 980 m_model->getPoints(s.getStartFrame(), s.getEndFrame());
Chris@43 981
Chris@43 982 double ratio =
Chris@43 983 double(newSize.getEndFrame() - newSize.getStartFrame()) /
Chris@43 984 double(s.getEndFrame() - s.getStartFrame());
Chris@43 985
Chris@43 986 for (SparseTimeValueModel::PointList::iterator i = points.begin();
Chris@43 987 i != points.end(); ++i) {
Chris@43 988
Chris@43 989 if (s.contains(i->frame)) {
Chris@43 990
Chris@43 991 double target = i->frame;
Chris@43 992 target = newSize.getStartFrame() +
Chris@43 993 double(target - s.getStartFrame()) * ratio;
Chris@43 994
Chris@43 995 SparseTimeValueModel::Point newPoint(*i);
Chris@43 996 newPoint.frame = lrint(target);
Chris@43 997 command->deletePoint(*i);
Chris@43 998 command->addPoint(newPoint);
Chris@43 999 }
Chris@43 1000 }
Chris@43 1001
Chris@43 1002 command->finish();
Chris@43 1003 }
Chris@43 1004
Chris@76 1005 void
Chris@76 1006 TimeValueLayer::deleteSelection(Selection s)
Chris@76 1007 {
Chris@76 1008 SparseTimeValueModel::EditCommand *command =
Chris@76 1009 new SparseTimeValueModel::EditCommand(m_model,
Chris@76 1010 tr("Delete Selected Points"));
Chris@76 1011
Chris@76 1012 SparseTimeValueModel::PointList points =
Chris@76 1013 m_model->getPoints(s.getStartFrame(), s.getEndFrame());
Chris@76 1014
Chris@76 1015 for (SparseTimeValueModel::PointList::iterator i = points.begin();
Chris@76 1016 i != points.end(); ++i) {
Chris@76 1017
Chris@76 1018 if (s.contains(i->frame)) {
Chris@76 1019 command->deletePoint(*i);
Chris@76 1020 }
Chris@76 1021 }
Chris@76 1022
Chris@76 1023 command->finish();
Chris@76 1024 }
Chris@76 1025
Chris@76 1026 void
Chris@76 1027 TimeValueLayer::copy(Selection s, Clipboard &to)
Chris@76 1028 {
Chris@76 1029 SparseTimeValueModel::PointList points =
Chris@76 1030 m_model->getPoints(s.getStartFrame(), s.getEndFrame());
Chris@76 1031
Chris@76 1032 for (SparseTimeValueModel::PointList::iterator i = points.begin();
Chris@76 1033 i != points.end(); ++i) {
Chris@76 1034 if (s.contains(i->frame)) {
Chris@76 1035 Clipboard::Point point(i->frame, i->label);
Chris@76 1036 to.addPoint(point);
Chris@76 1037 }
Chris@76 1038 }
Chris@76 1039 }
Chris@76 1040
Chris@76 1041 void
Chris@76 1042 TimeValueLayer::paste(const Clipboard &from, int frameOffset)
Chris@76 1043 {
Chris@76 1044 const Clipboard::PointList &points = from.getPoints();
Chris@76 1045
Chris@76 1046 SparseTimeValueModel::EditCommand *command =
Chris@76 1047 new SparseTimeValueModel::EditCommand(m_model, tr("Paste"));
Chris@76 1048
Chris@76 1049 for (Clipboard::PointList::const_iterator i = points.begin();
Chris@76 1050 i != points.end(); ++i) {
Chris@76 1051
Chris@76 1052 if (!i->haveFrame()) continue;
Chris@76 1053 size_t frame = 0;
Chris@76 1054 if (frameOffset > 0 || -frameOffset < i->getFrame()) {
Chris@76 1055 frame = i->getFrame() + frameOffset;
Chris@76 1056 }
Chris@76 1057 SparseTimeValueModel::Point newPoint(frame);
Chris@76 1058
Chris@76 1059 if (i->haveLabel()) newPoint.label = i->getLabel();
Chris@76 1060 if (i->haveValue()) newPoint.value = i->getValue();
Chris@76 1061 else newPoint.value = (m_model->getValueMinimum() +
Chris@76 1062 m_model->getValueMaximum()) / 2;
Chris@76 1063
Chris@76 1064 command->addPoint(newPoint);
Chris@76 1065 }
Chris@76 1066
Chris@76 1067 command->finish();
Chris@76 1068 }
Chris@76 1069
Chris@6 1070 QString
Chris@6 1071 TimeValueLayer::toXmlString(QString indent, QString extraAttributes) const
Chris@6 1072 {
Chris@6 1073 return Layer::toXmlString(indent, extraAttributes +
Chris@6 1074 QString(" colour=\"%1\" plotStyle=\"%2\"")
Chris@6 1075 .arg(encodeColour(m_colour)).arg(m_plotStyle));
Chris@0 1076 }
Chris@0 1077
Chris@11 1078 void
Chris@11 1079 TimeValueLayer::setProperties(const QXmlAttributes &attributes)
Chris@11 1080 {
Chris@11 1081 QString colourSpec = attributes.value("colour");
Chris@11 1082 if (colourSpec != "") {
Chris@11 1083 QColor colour(colourSpec);
Chris@11 1084 if (colour.isValid()) {
Chris@11 1085 setBaseColour(QColor(colourSpec));
Chris@11 1086 }
Chris@11 1087 }
Chris@11 1088
Chris@11 1089 bool ok;
Chris@11 1090 PlotStyle style = (PlotStyle)
Chris@11 1091 attributes.value("plotStyle").toInt(&ok);
Chris@11 1092 if (ok) setPlotStyle(style);
Chris@11 1093 }
Chris@11 1094
Chris@0 1095
Chris@0 1096 #ifdef INCLUDE_MOCFILES
Chris@0 1097 #include "TimeValueLayer.moc.cpp"
Chris@0 1098 #endif
Chris@0 1099