annotate layer/TimeValueLayer.cpp @ 101:0f36cdf407a6 sv1-v0.9rc1

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