annotate layer/TimeValueLayer.cpp @ 79:19bf27e4fb29

* Replace crash with warning when a transform could not be automatically re-run * More sensible default paths for Vamp plugin lookup (at least on Linux and OS/X) * A start to making the y coords for time value layers etc align * Set sensible y coords for text labels in time instant and value layers
author Chris Cannam
date Thu, 13 Apr 2006 18:29:10 +0000
parents 45ba0b381c5d
children 01f27a282c90
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@79 219 bool
Chris@79 220 TimeValueLayer::getValueExtents(float &min, float &max, QString &unit) const
Chris@79 221 {
Chris@79 222 min = m_model->getValueMinimum();
Chris@79 223 max = m_model->getValueMaximum();
Chris@79 224 unit = m_model->getScaleUnits();
Chris@79 225 return true;
Chris@79 226 }
Chris@79 227
Chris@0 228 SparseTimeValueModel::PointList
Chris@44 229 TimeValueLayer::getLocalPoints(View *v, int x) const
Chris@0 230 {
Chris@0 231 if (!m_model) return SparseTimeValueModel::PointList();
Chris@0 232
Chris@44 233 long frame = v->getFrameForX(x);
Chris@0 234
Chris@0 235 SparseTimeValueModel::PointList onPoints =
Chris@0 236 m_model->getPoints(frame);
Chris@0 237
Chris@0 238 if (!onPoints.empty()) {
Chris@0 239 return onPoints;
Chris@0 240 }
Chris@0 241
Chris@0 242 SparseTimeValueModel::PointList prevPoints =
Chris@0 243 m_model->getPreviousPoints(frame);
Chris@0 244 SparseTimeValueModel::PointList nextPoints =
Chris@0 245 m_model->getNextPoints(frame);
Chris@0 246
Chris@0 247 SparseTimeValueModel::PointList usePoints = prevPoints;
Chris@0 248
Chris@0 249 if (prevPoints.empty()) {
Chris@0 250 usePoints = nextPoints;
Chris@44 251 } else if (prevPoints.begin()->frame < v->getStartFrame() &&
Chris@44 252 !(nextPoints.begin()->frame > v->getEndFrame())) {
Chris@0 253 usePoints = nextPoints;
Chris@0 254 } else if (nextPoints.begin()->frame - frame <
Chris@0 255 frame - prevPoints.begin()->frame) {
Chris@0 256 usePoints = nextPoints;
Chris@0 257 }
Chris@0 258
Chris@28 259 if (!usePoints.empty()) {
Chris@28 260 int fuzz = 2;
Chris@44 261 int px = v->getXForFrame(usePoints.begin()->frame);
Chris@28 262 if ((px > x && px - x > fuzz) ||
Chris@28 263 (px < x && x - px > fuzz + 1)) {
Chris@28 264 usePoints.clear();
Chris@28 265 }
Chris@28 266 }
Chris@28 267
Chris@0 268 return usePoints;
Chris@0 269 }
Chris@0 270
Chris@25 271 QString
Chris@44 272 TimeValueLayer::getFeatureDescription(View *v, QPoint &pos) const
Chris@0 273 {
Chris@25 274 int x = pos.x();
Chris@0 275
Chris@25 276 if (!m_model || !m_model->getSampleRate()) return "";
Chris@0 277
Chris@44 278 SparseTimeValueModel::PointList points = getLocalPoints(v, x);
Chris@0 279
Chris@0 280 if (points.empty()) {
Chris@0 281 if (!m_model->isReady()) {
Chris@25 282 return tr("In progress");
Chris@25 283 } else {
Chris@25 284 return tr("No local points");
Chris@0 285 }
Chris@0 286 }
Chris@0 287
Chris@0 288 long useFrame = points.begin()->frame;
Chris@0 289
Chris@0 290 RealTime rt = RealTime::frame2RealTime(useFrame, m_model->getSampleRate());
Chris@25 291
Chris@25 292 QString text;
Chris@0 293
Chris@25 294 if (points.begin()->label == "") {
Chris@25 295 text = QString(tr("Time:\t%1\nValue:\t%2\nNo label"))
Chris@25 296 .arg(rt.toText(true).c_str())
Chris@25 297 .arg(points.begin()->value);
Chris@25 298 } else {
Chris@25 299 text = QString(tr("Time:\t%1\nValue:\t%2\nLabel:\t%3"))
Chris@25 300 .arg(rt.toText(true).c_str())
Chris@25 301 .arg(points.begin()->value)
Chris@25 302 .arg(points.begin()->label);
Chris@25 303 }
Chris@0 304
Chris@44 305 pos = QPoint(v->getXForFrame(useFrame),
Chris@44 306 getYForValue(v, points.begin()->value));
Chris@25 307 return text;
Chris@0 308 }
Chris@0 309
Chris@28 310 bool
Chris@44 311 TimeValueLayer::snapToFeatureFrame(View *v, int &frame,
Chris@28 312 size_t &resolution,
Chris@28 313 SnapType snap) const
Chris@13 314 {
Chris@13 315 if (!m_model) {
Chris@44 316 return Layer::snapToFeatureFrame(v, frame, resolution, snap);
Chris@13 317 }
Chris@13 318
Chris@13 319 resolution = m_model->getResolution();
Chris@28 320 SparseTimeValueModel::PointList points;
Chris@13 321
Chris@28 322 if (snap == SnapNeighbouring) {
Chris@28 323
Chris@44 324 points = getLocalPoints(v, v->getXForFrame(frame));
Chris@28 325 if (points.empty()) return false;
Chris@28 326 frame = points.begin()->frame;
Chris@28 327 return true;
Chris@28 328 }
Chris@28 329
Chris@28 330 points = m_model->getPoints(frame, frame);
Chris@28 331 int snapped = frame;
Chris@28 332 bool found = false;
Chris@13 333
Chris@13 334 for (SparseTimeValueModel::PointList::const_iterator i = points.begin();
Chris@13 335 i != points.end(); ++i) {
Chris@13 336
Chris@28 337 if (snap == SnapRight) {
Chris@28 338
Chris@13 339 if (i->frame > frame) {
Chris@28 340 snapped = i->frame;
Chris@28 341 found = true;
Chris@13 342 break;
Chris@13 343 }
Chris@28 344
Chris@28 345 } else if (snap == SnapLeft) {
Chris@28 346
Chris@13 347 if (i->frame <= frame) {
Chris@28 348 snapped = i->frame;
Chris@28 349 found = true; // don't break, as the next may be better
Chris@28 350 } else {
Chris@28 351 break;
Chris@28 352 }
Chris@28 353
Chris@28 354 } else { // nearest
Chris@28 355
Chris@28 356 SparseTimeValueModel::PointList::const_iterator j = i;
Chris@28 357 ++j;
Chris@28 358
Chris@28 359 if (j == points.end()) {
Chris@28 360
Chris@28 361 snapped = i->frame;
Chris@28 362 found = true;
Chris@28 363 break;
Chris@28 364
Chris@28 365 } else if (j->frame >= frame) {
Chris@28 366
Chris@28 367 if (j->frame - frame < frame - i->frame) {
Chris@28 368 snapped = j->frame;
Chris@28 369 } else {
Chris@28 370 snapped = i->frame;
Chris@28 371 }
Chris@28 372 found = true;
Chris@28 373 break;
Chris@13 374 }
Chris@13 375 }
Chris@13 376 }
Chris@13 377
Chris@28 378 frame = snapped;
Chris@28 379 return found;
Chris@13 380 }
Chris@13 381
Chris@21 382 int
Chris@66 383 TimeValueLayer::getYForValue(View *v, float val) const
Chris@21 384 {
Chris@79 385 float min = 0.0, max = 0.0;
Chris@79 386 int h = v->height();
Chris@79 387
Chris@79 388 if (!v->getValueExtents(m_model->getScaleUnits(), min, max)) {
Chris@79 389 min = m_model->getValueMinimum();
Chris@79 390 max = m_model->getValueMaximum();
Chris@79 391 }
Chris@79 392
Chris@79 393 if (max == min) max = min + 1.0;
Chris@79 394
Chris@79 395 /*!!!
Chris@21 396 float min = m_model->getValueMinimum();
Chris@21 397 float max = m_model->getValueMaximum();
Chris@21 398 if (max == min) max = min + 1.0;
Chris@21 399
Chris@44 400 int h = v->height();
Chris@21 401
Chris@66 402 if (m_verticalScale == FrequencyScale || m_verticalScale == LogScale) {
Chris@66 403
Chris@66 404 if (m_verticalScale == FrequencyScale) {
Chris@66 405 // If we have a spectrogram layer on the same view as us, align
Chris@66 406 // ourselves with it...
Chris@66 407 for (int i = 0; i < v->getLayerCount(); ++i) {
Chris@66 408 SpectrogramLayer *spectrogram = dynamic_cast<SpectrogramLayer *>
Chris@66 409 (v->getLayer(i));
Chris@66 410 if (spectrogram) {
Chris@66 411 return spectrogram->getYForFrequency(v, val);
Chris@66 412 }
Chris@66 413 }
Chris@66 414 }
Chris@66 415
Chris@66 416 min = (min < 0.0) ? -log10(-min) : (min == 0.0) ? 0.0 : log10(min);
Chris@66 417 max = (max < 0.0) ? -log10(-max) : (max == 0.0) ? 0.0 : log10(max);
Chris@66 418 val = (val < 0.0) ? -log10(-val) : (val == 0.0) ? 0.0 : log10(val);
Chris@66 419
Chris@66 420 } else if (m_verticalScale == PlusMinusOneScale) {
Chris@66 421 min = -1.0;
Chris@66 422 max = 1.0;
Chris@66 423 }
Chris@79 424 */
Chris@66 425
Chris@66 426 return int(h - ((val - min) * h) / (max - min));
Chris@21 427 }
Chris@21 428
Chris@21 429 float
Chris@44 430 TimeValueLayer::getValueForY(View *v, int y) const
Chris@21 431 {
Chris@66 432 //!!!
Chris@66 433
Chris@21 434 float min = m_model->getValueMinimum();
Chris@21 435 float max = m_model->getValueMaximum();
Chris@21 436 if (max == min) max = min + 1.0;
Chris@21 437
Chris@44 438 int h = v->height();
Chris@21 439
Chris@21 440 return min + (float(h - y) * float(max - min)) / h;
Chris@21 441 }
Chris@21 442
Chris@68 443 QColor
Chris@68 444 TimeValueLayer::getColourForValue(float val) const
Chris@68 445 {
Chris@68 446 float min = m_model->getValueMinimum();
Chris@68 447 float max = m_model->getValueMaximum();
Chris@68 448 if (max == min) max = min + 1.0;
Chris@68 449
Chris@68 450 if (m_verticalScale == FrequencyScale || m_verticalScale == LogScale) {
Chris@68 451 min = (min < 0.0) ? -log10(-min) : (min == 0.0) ? 0.0 : log10(min);
Chris@68 452 max = (max < 0.0) ? -log10(-max) : (max == 0.0) ? 0.0 : log10(max);
Chris@68 453 val = (val < 0.0) ? -log10(-val) : (val == 0.0) ? 0.0 : log10(val);
Chris@68 454 } else if (m_verticalScale == PlusMinusOneScale) {
Chris@68 455 min = -1.0;
Chris@68 456 max = 1.0;
Chris@68 457 }
Chris@68 458
Chris@68 459 int iv = ((val - min) / (max - min)) * 255.999;
Chris@68 460
Chris@68 461 QColor colour = QColor::fromHsv(256 - iv, iv / 2 + 128, iv);
Chris@68 462 return QColor(colour.red(), colour.green(), colour.blue(), 120);
Chris@68 463 }
Chris@68 464
Chris@0 465 void
Chris@44 466 TimeValueLayer::paint(View *v, QPainter &paint, QRect rect) const
Chris@0 467 {
Chris@0 468 if (!m_model || !m_model->isOK()) return;
Chris@0 469
Chris@0 470 int sampleRate = m_model->getSampleRate();
Chris@0 471 if (!sampleRate) return;
Chris@0 472
Chris@0 473 // Profiler profiler("TimeValueLayer::paint", true);
Chris@0 474
Chris@0 475 int x0 = rect.left(), x1 = rect.right();
Chris@44 476 long frame0 = v->getFrameForX(x0);
Chris@44 477 long frame1 = v->getFrameForX(x1);
Chris@0 478
Chris@0 479 SparseTimeValueModel::PointList points(m_model->getPoints
Chris@0 480 (frame0, frame1));
Chris@11 481 if (points.empty()) return;
Chris@0 482
Chris@0 483 paint.setPen(m_colour);
Chris@0 484
Chris@0 485 QColor brushColour(m_colour);
Chris@0 486 brushColour.setAlpha(80);
Chris@0 487 paint.setBrush(brushColour);
Chris@0 488
Chris@0 489 // std::cerr << "TimeValueLayer::paint: resolution is "
Chris@0 490 // << m_model->getResolution() << " frames" << std::endl;
Chris@0 491
Chris@0 492 float min = m_model->getValueMinimum();
Chris@0 493 float max = m_model->getValueMaximum();
Chris@0 494 if (max == min) max = min + 1.0;
Chris@0 495
Chris@44 496 int origin = int(nearbyint(v->height() -
Chris@44 497 (-min * v->height()) / (max - min)));
Chris@0 498
Chris@0 499 QPoint localPos;
Chris@0 500 long illuminateFrame = -1;
Chris@0 501
Chris@44 502 if (v->shouldIlluminateLocalFeatures(this, localPos)) {
Chris@0 503 SparseTimeValueModel::PointList localPoints =
Chris@44 504 getLocalPoints(v, localPos.x());
Chris@0 505 if (!localPoints.empty()) illuminateFrame = localPoints.begin()->frame;
Chris@0 506 }
Chris@6 507
Chris@20 508 int w =
Chris@44 509 v->getXForFrame(frame0 + m_model->getResolution()) -
Chris@44 510 v->getXForFrame(frame0);
Chris@7 511
Chris@6 512 paint.save();
Chris@6 513
Chris@6 514 QPainterPath path;
Chris@55 515 int pointCount = 0;
Chris@79 516
Chris@79 517 int textY = 0;
Chris@79 518 if (m_plotStyle == PlotSegmentation) {
Chris@79 519 textY = v->getTextLabelHeight(this, paint);
Chris@79 520 }
Chris@6 521
Chris@0 522 for (SparseTimeValueModel::PointList::const_iterator i = points.begin();
Chris@0 523 i != points.end(); ++i) {
Chris@0 524
Chris@0 525 const SparseTimeValueModel::Point &p(*i);
Chris@0 526
Chris@44 527 int x = v->getXForFrame(p.frame);
Chris@44 528 int y = getYForValue(v, p.value);
Chris@0 529
Chris@79 530 if (m_plotStyle != PlotSegmentation) {
Chris@79 531 textY = y - paint.fontMetrics().height()
Chris@79 532 + paint.fontMetrics().ascent();
Chris@79 533 }
Chris@79 534
Chris@34 535 bool haveNext = false;
Chris@76 536 int nx = v->getXForFrame(v->getModelsEndFrame());
Chris@76 537 // m_model->getEndFrame());
Chris@34 538 int ny = y;
Chris@34 539
Chris@34 540 SparseTimeValueModel::PointList::const_iterator j = i;
Chris@34 541 ++j;
Chris@34 542
Chris@34 543 if (j != points.end()) {
Chris@34 544 const SparseTimeValueModel::Point &q(*j);
Chris@44 545 nx = v->getXForFrame(q.frame);
Chris@44 546 ny = getYForValue(v, q.value);
Chris@34 547 haveNext = true;
Chris@76 548 }
Chris@76 549
Chris@76 550 // std::cout << "frame = " << p.frame << ", x = " << x << ", haveNext = " << haveNext
Chris@76 551 // << ", nx = " << nx << std::endl;
Chris@34 552
Chris@34 553 int labelY = y;
Chris@34 554
Chris@0 555 if (w < 1) w = 1;
Chris@26 556 paint.setPen(m_colour);
Chris@0 557
Chris@26 558 if (m_plotStyle == PlotSegmentation) {
Chris@68 559 paint.setBrush(getColourForValue(p.value));
Chris@44 560 labelY = v->height();
Chris@26 561 } else if (m_plotStyle == PlotLines ||
Chris@26 562 m_plotStyle == PlotCurve) {
Chris@6 563 paint.setBrush(Qt::NoBrush);
Chris@3 564 } else {
Chris@6 565 paint.setBrush(brushColour);
Chris@3 566 }
Chris@0 567
Chris@0 568 if (m_plotStyle == PlotStems) {
Chris@0 569 paint.setPen(brushColour);
Chris@0 570 if (y < origin - 1) {
Chris@0 571 paint.drawRect(x + w/2, y + 1, 1, origin - y);
Chris@0 572 } else if (y > origin + 1) {
Chris@0 573 paint.drawRect(x + w/2, origin, 1, y - origin - 1);
Chris@0 574 }
Chris@0 575 paint.setPen(m_colour);
Chris@0 576 }
Chris@0 577
Chris@0 578 if (illuminateFrame == p.frame) {
Chris@6 579
Chris@0 580 //!!! aside from the problem of choosing a colour, it'd be
Chris@0 581 //better to save the highlighted rects and draw them at
Chris@0 582 //the end perhaps
Chris@6 583
Chris@6 584 //!!! not equipped to illuminate the right section in line
Chris@6 585 //or curve mode
Chris@6 586
Chris@6 587 if (m_plotStyle != PlotCurve &&
Chris@6 588 m_plotStyle != PlotLines) {
Chris@6 589 paint.setPen(Qt::black);//!!!
Chris@26 590 if (m_plotStyle != PlotSegmentation) {
Chris@26 591 paint.setBrush(Qt::black);//!!!
Chris@26 592 }
Chris@6 593 }
Chris@0 594 }
Chris@0 595
Chris@6 596 if (m_plotStyle != PlotLines &&
Chris@26 597 m_plotStyle != PlotCurve &&
Chris@26 598 m_plotStyle != PlotSegmentation) {
Chris@3 599 paint.drawRect(x, y - 1, w, 2);
Chris@3 600 }
Chris@0 601
Chris@6 602 if (m_plotStyle == PlotConnectedPoints ||
Chris@6 603 m_plotStyle == PlotLines ||
Chris@6 604 m_plotStyle == PlotCurve) {
Chris@0 605
Chris@34 606 if (haveNext) {
Chris@3 607
Chris@6 608 if (m_plotStyle == PlotConnectedPoints) {
Chris@34 609
Chris@79 610 paint.save();
Chris@3 611 paint.setPen(brushColour);
Chris@3 612 paint.drawLine(x + w, y, nx, ny);
Chris@79 613 paint.restore();
Chris@6 614
Chris@6 615 } else if (m_plotStyle == PlotLines) {
Chris@6 616
Chris@6 617 paint.drawLine(x + w/2, y, nx + w/2, ny);
Chris@6 618
Chris@3 619 } else {
Chris@6 620
Chris@55 621 float x0 = x + float(w)/2;
Chris@55 622 float x1 = nx + float(w)/2;
Chris@55 623
Chris@55 624 float y0 = y;
Chris@55 625 float y1 = ny;
Chris@55 626
Chris@55 627 if (pointCount == 0) {
Chris@55 628 path.moveTo((x0 + x1) / 2, (y0 + y1) / 2);
Chris@6 629 }
Chris@55 630 ++pointCount;
Chris@6 631
Chris@6 632 if (nx - x > 5) {
Chris@55 633 path.cubicTo(x0, y0,
Chris@55 634 x0, y0,
Chris@55 635 (x0 + x1) / 2, (y0 + y1) / 2);
Chris@55 636
Chris@55 637 // // or
Chris@55 638 // path.quadTo(x0, y0, (x0 + x1) / 2, (y0 + y1) / 2);
Chris@55 639
Chris@6 640 } else {
Chris@55 641 path.lineTo((x0 + x1) / 2, (y0 + y1) / 2);
Chris@6 642 }
Chris@3 643 }
Chris@0 644 }
Chris@0 645 }
Chris@0 646
Chris@26 647 if (m_plotStyle == PlotSegmentation) {
Chris@76 648
Chris@76 649 // std::cerr << "drawing rect" << std::endl;
Chris@26 650
Chris@27 651 if (nx <= x) continue;
Chris@26 652
Chris@28 653 if (illuminateFrame != p.frame &&
Chris@44 654 (nx < x + 5 || x >= v->width() - 1)) {
Chris@27 655 paint.setPen(Qt::NoPen);
Chris@27 656 }
Chris@26 657
Chris@44 658 paint.drawRect(x, -1, nx - x, v->height() + 1);
Chris@26 659 }
Chris@26 660
Chris@55 661 if (p.label != "") {
Chris@79 662 if (!haveNext || nx > x + 6 + paint.fontMetrics().width(p.label)) {
Chris@79 663 paint.drawText(x + 5, textY, p.label);
Chris@79 664 }
Chris@55 665 }
Chris@0 666 }
Chris@6 667
Chris@6 668 if (m_plotStyle == PlotCurve && !path.isEmpty()) {
Chris@55 669 paint.setRenderHint(QPainter::Antialiasing, pointCount <= v->width());
Chris@6 670 paint.drawPath(path);
Chris@6 671 }
Chris@6 672
Chris@6 673 paint.restore();
Chris@6 674
Chris@6 675 // looks like save/restore doesn't deal with this:
Chris@6 676 paint.setRenderHint(QPainter::Antialiasing, false);
Chris@6 677 }
Chris@6 678
Chris@42 679 int
Chris@44 680 TimeValueLayer::getVerticalScaleWidth(View *v, QPainter &paint) const
Chris@42 681 {
Chris@68 682 int w = paint.fontMetrics().width("-000.000");
Chris@68 683 if (m_plotStyle == PlotSegmentation) return w + 20;
Chris@68 684 else return w + 10;
Chris@42 685 }
Chris@42 686
Chris@42 687 void
Chris@44 688 TimeValueLayer::paintVerticalScale(View *v, QPainter &paint, QRect rect) const
Chris@42 689 {
Chris@42 690 if (!m_model) return;
Chris@42 691
Chris@68 692 int h = v->height();
Chris@68 693
Chris@68 694 int n = 10;
Chris@68 695
Chris@68 696 float max = m_model->getValueMaximum();
Chris@68 697 float min = m_model->getValueMinimum();
Chris@68 698 float val = min;
Chris@68 699 float inc = (max - val) / n;
Chris@42 700
Chris@55 701 char buffer[40];
Chris@55 702
Chris@55 703 int w = getVerticalScaleWidth(v, paint);
Chris@55 704
Chris@68 705 int tx = 5;
Chris@68 706
Chris@68 707 int boxx = 5, boxy = 5;
Chris@68 708 if (m_model->getScaleUnits() != "") {
Chris@68 709 boxy += paint.fontMetrics().height();
Chris@68 710 }
Chris@68 711 int boxw = 10, boxh = h - boxy - 5;
Chris@68 712
Chris@68 713 if (m_plotStyle == PlotSegmentation) {
Chris@68 714 tx += boxx + boxw;
Chris@68 715 paint.drawRect(boxx, boxy, boxw, boxh);
Chris@68 716 }
Chris@68 717
Chris@68 718 if (m_plotStyle == PlotSegmentation) {
Chris@68 719 paint.save();
Chris@68 720 for (int y = 0; y < boxh; ++y) {
Chris@68 721 float val = ((boxh - y) * (max - min)) / boxh + min;
Chris@68 722 paint.setPen(getColourForValue(val));
Chris@68 723 paint.drawLine(boxx + 1, y + boxy + 1, boxx + boxw, y + boxy + 1);
Chris@68 724 }
Chris@68 725 paint.restore();
Chris@68 726 }
Chris@68 727
Chris@68 728 for (int i = 0; i < n; ++i) {
Chris@68 729
Chris@68 730 int y, ty;
Chris@68 731 bool drawText = true;
Chris@68 732
Chris@68 733 if (m_plotStyle == PlotSegmentation) {
Chris@68 734 y = boxy + int(boxh - ((val - min) * boxh) / (max - min));
Chris@68 735 ty = y;
Chris@68 736 } else {
Chris@68 737 if (i == n-1) {
Chris@68 738 if (m_model->getScaleUnits() != "") drawText = false;
Chris@68 739 }
Chris@68 740 y = getYForValue(v, val);
Chris@68 741 ty = y - paint.fontMetrics().height() +
Chris@68 742 paint.fontMetrics().ascent();
Chris@68 743 }
Chris@68 744
Chris@68 745 sprintf(buffer, "%.3f", val);
Chris@55 746 QString label = QString(buffer);
Chris@68 747
Chris@68 748 if (m_plotStyle != PlotSegmentation) {
Chris@68 749 paint.drawLine(w - 5, y, w, y);
Chris@68 750 } else {
Chris@68 751 paint.drawLine(boxx + boxw - boxw/3, y, boxx + boxw, y);
Chris@68 752 }
Chris@68 753
Chris@68 754 if (drawText) paint.drawText(tx, ty, label);
Chris@44 755 val += inc;
Chris@42 756 }
Chris@68 757
Chris@67 758 if (m_model->getScaleUnits() != "") {
Chris@67 759 paint.drawText(5, 5 + paint.fontMetrics().ascent(),
Chris@67 760 m_model->getScaleUnits());
Chris@67 761 }
Chris@42 762 }
Chris@42 763
Chris@21 764 void
Chris@44 765 TimeValueLayer::drawStart(View *v, QMouseEvent *e)
Chris@21 766 {
Chris@21 767 std::cerr << "TimeValueLayer::drawStart(" << e->x() << "," << e->y() << ")" << std::endl;
Chris@21 768
Chris@21 769 if (!m_model) return;
Chris@21 770
Chris@44 771 long frame = v->getFrameForX(e->x());
Chris@76 772 long resolution = m_model->getResolution();
Chris@21 773 if (frame < 0) frame = 0;
Chris@76 774 frame = (frame / resolution) * resolution;
Chris@21 775
Chris@44 776 float value = getValueForY(v, e->y());
Chris@21 777
Chris@76 778 bool havePoint = false;
Chris@76 779
Chris@76 780 SparseTimeValueModel::PointList points = getLocalPoints(v, e->x());
Chris@76 781 if (!points.empty()) {
Chris@76 782 for (SparseTimeValueModel::PointList::iterator i = points.begin();
Chris@76 783 i != points.end(); ++i) {
Chris@76 784 if (((i->frame / resolution) * resolution) != frame) {
Chris@76 785 std::cerr << "ignoring out-of-range frame at " << i->frame << std::endl;
Chris@76 786 continue;
Chris@76 787 }
Chris@76 788 m_editingPoint = *i;
Chris@76 789 havePoint = true;
Chris@76 790 }
Chris@76 791 }
Chris@76 792
Chris@76 793 if (!havePoint) {
Chris@76 794 m_editingPoint = SparseTimeValueModel::Point
Chris@76 795 (frame, value, tr("New Point"));
Chris@76 796 }
Chris@76 797
Chris@23 798 m_originalPoint = m_editingPoint;
Chris@22 799
Chris@22 800 if (m_editingCommand) m_editingCommand->finish();
Chris@22 801 m_editingCommand = new SparseTimeValueModel::EditCommand(m_model,
Chris@22 802 tr("Draw Point"));
Chris@76 803 if (!havePoint) {
Chris@76 804 m_editingCommand->addPoint(m_editingPoint);
Chris@76 805 }
Chris@22 806
Chris@21 807 m_editing = true;
Chris@21 808 }
Chris@21 809
Chris@21 810 void
Chris@44 811 TimeValueLayer::drawDrag(View *v, QMouseEvent *e)
Chris@21 812 {
Chris@21 813 std::cerr << "TimeValueLayer::drawDrag(" << e->x() << "," << e->y() << ")" << std::endl;
Chris@21 814
Chris@21 815 if (!m_model || !m_editing) return;
Chris@21 816
Chris@44 817 long frame = v->getFrameForX(e->x());
Chris@76 818 long resolution = m_model->getResolution();
Chris@21 819 if (frame < 0) frame = 0;
Chris@76 820 frame = (frame / resolution) * resolution;
Chris@21 821
Chris@44 822 float value = getValueForY(v, e->y());
Chris@21 823
Chris@76 824 SparseTimeValueModel::PointList points = getLocalPoints(v, e->x());
Chris@76 825
Chris@76 826 std::cerr << points.size() << " points" << std::endl;
Chris@76 827
Chris@76 828 bool havePoint = false;
Chris@76 829
Chris@76 830 if (!points.empty()) {
Chris@76 831 for (SparseTimeValueModel::PointList::iterator i = points.begin();
Chris@76 832 i != points.end(); ++i) {
Chris@76 833 if (i->frame == m_editingPoint.frame &&
Chris@76 834 i->value == m_editingPoint.value) {
Chris@76 835 std::cerr << "ignoring current editing point at " << i->frame << ", " << i->value << std::endl;
Chris@76 836 continue;
Chris@76 837 }
Chris@76 838 if (((i->frame / resolution) * resolution) != frame) {
Chris@76 839 std::cerr << "ignoring out-of-range frame at " << i->frame << std::endl;
Chris@76 840 continue;
Chris@76 841 }
Chris@76 842 std::cerr << "adjusting to new point at " << i->frame << ", " << i->value << std::endl;
Chris@76 843 m_editingPoint = *i;
Chris@76 844 m_originalPoint = m_editingPoint;
Chris@76 845 m_editingCommand->deletePoint(m_editingPoint);
Chris@76 846 havePoint = true;
Chris@76 847 }
Chris@76 848 }
Chris@76 849
Chris@76 850 if (!havePoint) {
Chris@76 851 if (frame == m_editingPoint.frame) {
Chris@76 852 m_editingCommand->deletePoint(m_editingPoint);
Chris@76 853 }
Chris@76 854 }
Chris@76 855
Chris@76 856 // m_editingCommand->deletePoint(m_editingPoint);
Chris@21 857 m_editingPoint.frame = frame;
Chris@21 858 m_editingPoint.value = value;
Chris@22 859 m_editingCommand->addPoint(m_editingPoint);
Chris@21 860 }
Chris@21 861
Chris@21 862 void
Chris@44 863 TimeValueLayer::drawEnd(View *v, QMouseEvent *e)
Chris@21 864 {
Chris@21 865 std::cerr << "TimeValueLayer::drawEnd(" << e->x() << "," << e->y() << ")" << std::endl;
Chris@21 866 if (!m_model || !m_editing) return;
Chris@22 867 m_editingCommand->finish();
Chris@22 868 m_editingCommand = 0;
Chris@21 869 m_editing = false;
Chris@21 870 }
Chris@21 871
Chris@21 872 void
Chris@44 873 TimeValueLayer::editStart(View *v, QMouseEvent *e)
Chris@21 874 {
Chris@21 875 std::cerr << "TimeValueLayer::editStart(" << e->x() << "," << e->y() << ")" << std::endl;
Chris@21 876
Chris@21 877 if (!m_model) return;
Chris@21 878
Chris@44 879 SparseTimeValueModel::PointList points = getLocalPoints(v, e->x());
Chris@21 880 if (points.empty()) return;
Chris@21 881
Chris@21 882 m_editingPoint = *points.begin();
Chris@23 883 m_originalPoint = m_editingPoint;
Chris@22 884
Chris@22 885 if (m_editingCommand) {
Chris@22 886 m_editingCommand->finish();
Chris@22 887 m_editingCommand = 0;
Chris@22 888 }
Chris@22 889
Chris@21 890 m_editing = true;
Chris@21 891 }
Chris@21 892
Chris@21 893 void
Chris@44 894 TimeValueLayer::editDrag(View *v, QMouseEvent *e)
Chris@21 895 {
Chris@21 896 std::cerr << "TimeValueLayer::editDrag(" << e->x() << "," << e->y() << ")" << std::endl;
Chris@21 897
Chris@21 898 if (!m_model || !m_editing) return;
Chris@21 899
Chris@44 900 long frame = v->getFrameForX(e->x());
Chris@21 901 if (frame < 0) frame = 0;
Chris@21 902 frame = frame / m_model->getResolution() * m_model->getResolution();
Chris@21 903
Chris@44 904 float value = getValueForY(v, e->y());
Chris@21 905
Chris@22 906 if (!m_editingCommand) {
Chris@22 907 m_editingCommand = new SparseTimeValueModel::EditCommand(m_model,
Chris@22 908 tr("Drag Point"));
Chris@22 909 }
Chris@22 910
Chris@22 911 m_editingCommand->deletePoint(m_editingPoint);
Chris@21 912 m_editingPoint.frame = frame;
Chris@21 913 m_editingPoint.value = value;
Chris@22 914 m_editingCommand->addPoint(m_editingPoint);
Chris@21 915 }
Chris@21 916
Chris@21 917 void
Chris@44 918 TimeValueLayer::editEnd(View *v, QMouseEvent *e)
Chris@21 919 {
Chris@21 920 std::cerr << "TimeValueLayer::editEnd(" << e->x() << "," << e->y() << ")" << std::endl;
Chris@21 921 if (!m_model || !m_editing) return;
Chris@23 922
Chris@23 923 if (m_editingCommand) {
Chris@23 924
Chris@23 925 QString newName = m_editingCommand->getName();
Chris@23 926
Chris@23 927 if (m_editingPoint.frame != m_originalPoint.frame) {
Chris@23 928 if (m_editingPoint.value != m_originalPoint.value) {
Chris@23 929 newName = tr("Edit Point");
Chris@23 930 } else {
Chris@23 931 newName = tr("Relocate Point");
Chris@23 932 }
Chris@23 933 } else {
Chris@23 934 newName = tr("Change Point Value");
Chris@23 935 }
Chris@23 936
Chris@23 937 m_editingCommand->setName(newName);
Chris@23 938 m_editingCommand->finish();
Chris@23 939 }
Chris@23 940
Chris@22 941 m_editingCommand = 0;
Chris@21 942 m_editing = false;
Chris@21 943 }
Chris@21 944
Chris@43 945 void
Chris@70 946 TimeValueLayer::editOpen(View *v, QMouseEvent *e)
Chris@70 947 {
Chris@70 948 if (!m_model) return;
Chris@70 949
Chris@70 950 SparseTimeValueModel::PointList points = getLocalPoints(v, e->x());
Chris@70 951 if (points.empty()) return;
Chris@70 952
Chris@70 953 SparseTimeValueModel::Point point = *points.begin();
Chris@70 954
Chris@70 955 ItemEditDialog *dialog = new ItemEditDialog
Chris@70 956 (m_model->getSampleRate(),
Chris@70 957 ItemEditDialog::ShowTime |
Chris@70 958 ItemEditDialog::ShowValue |
Chris@73 959 ItemEditDialog::ShowText,
Chris@73 960 m_model->getScaleUnits());
Chris@70 961
Chris@70 962 dialog->setFrameTime(point.frame);
Chris@70 963 dialog->setValue(point.value);
Chris@70 964 dialog->setText(point.label);
Chris@70 965
Chris@70 966 if (dialog->exec() == QDialog::Accepted) {
Chris@70 967
Chris@70 968 SparseTimeValueModel::Point newPoint = point;
Chris@70 969 newPoint.frame = dialog->getFrameTime();
Chris@70 970 newPoint.value = dialog->getValue();
Chris@70 971 newPoint.label = dialog->getText();
Chris@70 972
Chris@70 973 SparseTimeValueModel::EditCommand *command =
Chris@70 974 new SparseTimeValueModel::EditCommand(m_model, tr("Edit Point"));
Chris@70 975 command->deletePoint(point);
Chris@70 976 command->addPoint(newPoint);
Chris@70 977 command->finish();
Chris@70 978 }
Chris@70 979
Chris@70 980 delete dialog;
Chris@70 981 }
Chris@70 982
Chris@70 983 void
Chris@43 984 TimeValueLayer::moveSelection(Selection s, size_t newStartFrame)
Chris@43 985 {
Chris@43 986 SparseTimeValueModel::EditCommand *command =
Chris@43 987 new SparseTimeValueModel::EditCommand(m_model,
Chris@43 988 tr("Drag Selection"));
Chris@43 989
Chris@43 990 SparseTimeValueModel::PointList points =
Chris@43 991 m_model->getPoints(s.getStartFrame(), s.getEndFrame());
Chris@43 992
Chris@43 993 for (SparseTimeValueModel::PointList::iterator i = points.begin();
Chris@43 994 i != points.end(); ++i) {
Chris@43 995
Chris@43 996 if (s.contains(i->frame)) {
Chris@43 997 SparseTimeValueModel::Point newPoint(*i);
Chris@43 998 newPoint.frame = i->frame + newStartFrame - s.getStartFrame();
Chris@43 999 command->deletePoint(*i);
Chris@43 1000 command->addPoint(newPoint);
Chris@43 1001 }
Chris@43 1002 }
Chris@43 1003
Chris@43 1004 command->finish();
Chris@43 1005 }
Chris@43 1006
Chris@43 1007 void
Chris@43 1008 TimeValueLayer::resizeSelection(Selection s, Selection newSize)
Chris@43 1009 {
Chris@43 1010 SparseTimeValueModel::EditCommand *command =
Chris@43 1011 new SparseTimeValueModel::EditCommand(m_model,
Chris@43 1012 tr("Resize Selection"));
Chris@43 1013
Chris@43 1014 SparseTimeValueModel::PointList points =
Chris@43 1015 m_model->getPoints(s.getStartFrame(), s.getEndFrame());
Chris@43 1016
Chris@43 1017 double ratio =
Chris@43 1018 double(newSize.getEndFrame() - newSize.getStartFrame()) /
Chris@43 1019 double(s.getEndFrame() - s.getStartFrame());
Chris@43 1020
Chris@43 1021 for (SparseTimeValueModel::PointList::iterator i = points.begin();
Chris@43 1022 i != points.end(); ++i) {
Chris@43 1023
Chris@43 1024 if (s.contains(i->frame)) {
Chris@43 1025
Chris@43 1026 double target = i->frame;
Chris@43 1027 target = newSize.getStartFrame() +
Chris@43 1028 double(target - s.getStartFrame()) * ratio;
Chris@43 1029
Chris@43 1030 SparseTimeValueModel::Point newPoint(*i);
Chris@43 1031 newPoint.frame = lrint(target);
Chris@43 1032 command->deletePoint(*i);
Chris@43 1033 command->addPoint(newPoint);
Chris@43 1034 }
Chris@43 1035 }
Chris@43 1036
Chris@43 1037 command->finish();
Chris@43 1038 }
Chris@43 1039
Chris@76 1040 void
Chris@76 1041 TimeValueLayer::deleteSelection(Selection s)
Chris@76 1042 {
Chris@76 1043 SparseTimeValueModel::EditCommand *command =
Chris@76 1044 new SparseTimeValueModel::EditCommand(m_model,
Chris@76 1045 tr("Delete Selected Points"));
Chris@76 1046
Chris@76 1047 SparseTimeValueModel::PointList points =
Chris@76 1048 m_model->getPoints(s.getStartFrame(), s.getEndFrame());
Chris@76 1049
Chris@76 1050 for (SparseTimeValueModel::PointList::iterator i = points.begin();
Chris@76 1051 i != points.end(); ++i) {
Chris@76 1052
Chris@76 1053 if (s.contains(i->frame)) {
Chris@76 1054 command->deletePoint(*i);
Chris@76 1055 }
Chris@76 1056 }
Chris@76 1057
Chris@76 1058 command->finish();
Chris@76 1059 }
Chris@76 1060
Chris@76 1061 void
Chris@76 1062 TimeValueLayer::copy(Selection s, Clipboard &to)
Chris@76 1063 {
Chris@76 1064 SparseTimeValueModel::PointList points =
Chris@76 1065 m_model->getPoints(s.getStartFrame(), s.getEndFrame());
Chris@76 1066
Chris@76 1067 for (SparseTimeValueModel::PointList::iterator i = points.begin();
Chris@76 1068 i != points.end(); ++i) {
Chris@76 1069 if (s.contains(i->frame)) {
Chris@76 1070 Clipboard::Point point(i->frame, i->label);
Chris@76 1071 to.addPoint(point);
Chris@76 1072 }
Chris@76 1073 }
Chris@76 1074 }
Chris@76 1075
Chris@76 1076 void
Chris@76 1077 TimeValueLayer::paste(const Clipboard &from, int frameOffset)
Chris@76 1078 {
Chris@76 1079 const Clipboard::PointList &points = from.getPoints();
Chris@76 1080
Chris@76 1081 SparseTimeValueModel::EditCommand *command =
Chris@76 1082 new SparseTimeValueModel::EditCommand(m_model, tr("Paste"));
Chris@76 1083
Chris@76 1084 for (Clipboard::PointList::const_iterator i = points.begin();
Chris@76 1085 i != points.end(); ++i) {
Chris@76 1086
Chris@76 1087 if (!i->haveFrame()) continue;
Chris@76 1088 size_t frame = 0;
Chris@76 1089 if (frameOffset > 0 || -frameOffset < i->getFrame()) {
Chris@76 1090 frame = i->getFrame() + frameOffset;
Chris@76 1091 }
Chris@76 1092 SparseTimeValueModel::Point newPoint(frame);
Chris@76 1093
Chris@76 1094 if (i->haveLabel()) newPoint.label = i->getLabel();
Chris@76 1095 if (i->haveValue()) newPoint.value = i->getValue();
Chris@76 1096 else newPoint.value = (m_model->getValueMinimum() +
Chris@76 1097 m_model->getValueMaximum()) / 2;
Chris@76 1098
Chris@76 1099 command->addPoint(newPoint);
Chris@76 1100 }
Chris@76 1101
Chris@76 1102 command->finish();
Chris@76 1103 }
Chris@76 1104
Chris@6 1105 QString
Chris@6 1106 TimeValueLayer::toXmlString(QString indent, QString extraAttributes) const
Chris@6 1107 {
Chris@6 1108 return Layer::toXmlString(indent, extraAttributes +
Chris@6 1109 QString(" colour=\"%1\" plotStyle=\"%2\"")
Chris@6 1110 .arg(encodeColour(m_colour)).arg(m_plotStyle));
Chris@0 1111 }
Chris@0 1112
Chris@11 1113 void
Chris@11 1114 TimeValueLayer::setProperties(const QXmlAttributes &attributes)
Chris@11 1115 {
Chris@11 1116 QString colourSpec = attributes.value("colour");
Chris@11 1117 if (colourSpec != "") {
Chris@11 1118 QColor colour(colourSpec);
Chris@11 1119 if (colour.isValid()) {
Chris@11 1120 setBaseColour(QColor(colourSpec));
Chris@11 1121 }
Chris@11 1122 }
Chris@11 1123
Chris@11 1124 bool ok;
Chris@11 1125 PlotStyle style = (PlotStyle)
Chris@11 1126 attributes.value("plotStyle").toInt(&ok);
Chris@11 1127 if (ok) setPlotStyle(style);
Chris@11 1128 }
Chris@11 1129
Chris@0 1130
Chris@0 1131 #ifdef INCLUDE_MOCFILES
Chris@0 1132 #include "TimeValueLayer.moc.cpp"
Chris@0 1133 #endif
Chris@0 1134