annotate layer/TimeValueLayer.cpp @ 18:d8e6709e9075

add - EasaierSessionManager - Easaier menus - Interval model
author lbajardsilogic
date Mon, 14 May 2007 13:13:14 +0000
parents fc9323a41f5a
children aa81e87c8089
rev   line source
lbajardsilogic@0 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
lbajardsilogic@0 2
lbajardsilogic@0 3 /*
lbajardsilogic@0 4 Sonic Visualiser
lbajardsilogic@0 5 An audio file viewer and annotation editor.
lbajardsilogic@0 6 Centre for Digital Music, Queen Mary, University of London.
lbajardsilogic@0 7 This file copyright 2006 Chris Cannam.
lbajardsilogic@0 8
lbajardsilogic@0 9 This program is free software; you can redistribute it and/or
lbajardsilogic@0 10 modify it under the terms of the GNU General Public License as
lbajardsilogic@0 11 published by the Free Software Foundation; either version 2 of the
lbajardsilogic@0 12 License, or (at your option) any later version. See the file
lbajardsilogic@0 13 COPYING included with this distribution for more information.
lbajardsilogic@0 14 */
lbajardsilogic@0 15
lbajardsilogic@0 16 #include "TimeValueLayer.h"
lbajardsilogic@0 17
lbajardsilogic@0 18 #include "system/System.h"
lbajardsilogic@0 19 #include "data/model/Model.h"
lbajardsilogic@0 20 #include "base/RealTime.h"
lbajardsilogic@0 21 #include "base/Profiler.h"
lbajardsilogic@0 22 #include "base/LogRange.h"
lbajardsilogic@0 23 #include "view/View.h"
lbajardsilogic@0 24
lbajardsilogic@0 25 #include "data/model/SparseTimeValueModel.h"
lbajardsilogic@0 26
lbajardsilogic@0 27 #include "widgets/ItemEditDialog.h"
lbajardsilogic@0 28 #include "widgets/ListInputDialog.h"
lbajardsilogic@0 29
lbajardsilogic@0 30 #include "SpectrogramLayer.h" // for optional frequency alignment
lbajardsilogic@0 31 #include "ColourMapper.h"
lbajardsilogic@0 32
lbajardsilogic@0 33 #include <QPainter>
lbajardsilogic@0 34 #include <QPainterPath>
lbajardsilogic@0 35 #include <QMouseEvent>
lbajardsilogic@0 36 #include <QRegExp>
lbajardsilogic@0 37
lbajardsilogic@0 38 #include <iostream>
lbajardsilogic@0 39 #include <cmath>
lbajardsilogic@0 40
lbajardsilogic@0 41 TimeValueLayer::TimeValueLayer() :
lbajardsilogic@0 42 Layer(),
lbajardsilogic@0 43 m_model(0),
lbajardsilogic@0 44 m_editing(false),
lbajardsilogic@0 45 m_originalPoint(0, 0.0, tr("New Point")),
lbajardsilogic@0 46 m_editingPoint(0, 0.0, tr("New Point")),
lbajardsilogic@0 47 m_editingCommand(0),
lbajardsilogic@0 48 m_colour(Qt::darkGreen),
lbajardsilogic@0 49 m_colourMap(0),
lbajardsilogic@0 50 m_plotStyle(PlotConnectedPoints),
lbajardsilogic@0 51 m_verticalScale(AutoAlignScale)
lbajardsilogic@0 52 {
lbajardsilogic@0 53
lbajardsilogic@0 54 }
lbajardsilogic@0 55
lbajardsilogic@0 56 void
lbajardsilogic@0 57 TimeValueLayer::setModel(SparseTimeValueModel *model)
lbajardsilogic@0 58 {
lbajardsilogic@0 59 if (m_model == model) return;
lbajardsilogic@0 60 m_model = model;
lbajardsilogic@0 61
lbajardsilogic@0 62 connect(m_model, SIGNAL(modelChanged()), this, SIGNAL(modelChanged()));
lbajardsilogic@0 63 connect(m_model, SIGNAL(modelChanged(size_t, size_t)),
lbajardsilogic@0 64 this, SIGNAL(modelChanged(size_t, size_t)));
lbajardsilogic@0 65
lbajardsilogic@0 66 connect(m_model, SIGNAL(completionChanged()),
lbajardsilogic@0 67 this, SIGNAL(modelCompletionChanged()));
lbajardsilogic@0 68
lbajardsilogic@0 69 // std::cerr << "TimeValueLayer::setModel(" << model << ")" << std::endl;
lbajardsilogic@0 70
lbajardsilogic@0 71 emit modelReplaced();
lbajardsilogic@0 72 }
lbajardsilogic@0 73
lbajardsilogic@0 74 Layer::PropertyList
lbajardsilogic@0 75 TimeValueLayer::getProperties() const
lbajardsilogic@0 76 {
lbajardsilogic@0 77 PropertyList list;
lbajardsilogic@0 78 list.push_back("Colour");
lbajardsilogic@0 79 list.push_back("Plot Type");
lbajardsilogic@0 80 list.push_back("Vertical Scale");
lbajardsilogic@0 81 list.push_back("Scale Units");
lbajardsilogic@0 82 return list;
lbajardsilogic@0 83 }
lbajardsilogic@0 84
lbajardsilogic@0 85 QString
lbajardsilogic@0 86 TimeValueLayer::getPropertyLabel(const PropertyName &name) const
lbajardsilogic@0 87 {
lbajardsilogic@0 88 if (name == "Colour") return tr("Colour");
lbajardsilogic@0 89 if (name == "Plot Type") return tr("Plot Type");
lbajardsilogic@0 90 if (name == "Vertical Scale") return tr("Vertical Scale");
lbajardsilogic@0 91 if (name == "Scale Units") return tr("Scale Units");
lbajardsilogic@0 92 return "";
lbajardsilogic@0 93 }
lbajardsilogic@0 94
lbajardsilogic@0 95 Layer::PropertyType
lbajardsilogic@0 96 TimeValueLayer::getPropertyType(const PropertyName &name) const
lbajardsilogic@0 97 {
lbajardsilogic@0 98 if (name == "Scale Units") return UnitsProperty;
lbajardsilogic@0 99 else return ValueProperty;
lbajardsilogic@0 100 }
lbajardsilogic@0 101
lbajardsilogic@0 102 QString
lbajardsilogic@0 103 TimeValueLayer::getPropertyGroupName(const PropertyName &name) const
lbajardsilogic@0 104 {
lbajardsilogic@0 105 if (name == "Vertical Scale" || name == "Scale Units") {
lbajardsilogic@0 106 return tr("Scale");
lbajardsilogic@0 107 }
lbajardsilogic@0 108 return QString();
lbajardsilogic@0 109 }
lbajardsilogic@0 110
lbajardsilogic@0 111 int
lbajardsilogic@0 112 TimeValueLayer::getPropertyRangeAndValue(const PropertyName &name,
lbajardsilogic@0 113 int *min, int *max, int *deflt) const
lbajardsilogic@0 114 {
lbajardsilogic@0 115 //!!! factor this colour handling stuff out into a colour manager class
lbajardsilogic@0 116
lbajardsilogic@0 117 int val = 0;
lbajardsilogic@0 118
lbajardsilogic@0 119 if (name == "Colour") {
lbajardsilogic@0 120
lbajardsilogic@0 121 if (m_plotStyle == PlotSegmentation) {
lbajardsilogic@0 122
lbajardsilogic@0 123 if (min) *min = 0;
lbajardsilogic@0 124 if (max) *max = ColourMapper::getColourMapCount() - 1;
lbajardsilogic@0 125 if (deflt) *deflt = 0;
lbajardsilogic@0 126
lbajardsilogic@0 127 val = m_colourMap;
lbajardsilogic@0 128
lbajardsilogic@0 129 } else {
lbajardsilogic@0 130
lbajardsilogic@0 131 if (min) *min = 0;
lbajardsilogic@0 132 if (max) *max = 5;
lbajardsilogic@0 133 if (deflt) *deflt = 0;
lbajardsilogic@0 134
lbajardsilogic@0 135 if (m_colour == Qt::black) val = 0;
lbajardsilogic@0 136 else if (m_colour == Qt::darkRed) val = 1;
lbajardsilogic@0 137 else if (m_colour == Qt::darkBlue) val = 2;
lbajardsilogic@0 138 else if (m_colour == Qt::darkGreen) val = 3;
lbajardsilogic@0 139 else if (m_colour == QColor(200, 50, 255)) val = 4;
lbajardsilogic@0 140 else if (m_colour == QColor(255, 150, 50)) val = 5;
lbajardsilogic@0 141 }
lbajardsilogic@0 142
lbajardsilogic@0 143 } else if (name == "Plot Type") {
lbajardsilogic@0 144
lbajardsilogic@0 145 if (min) *min = 0;
lbajardsilogic@0 146 if (max) *max = 5;
lbajardsilogic@0 147 if (deflt) *deflt = int(PlotConnectedPoints);
lbajardsilogic@0 148
lbajardsilogic@0 149 val = int(m_plotStyle);
lbajardsilogic@0 150
lbajardsilogic@0 151 } else if (name == "Vertical Scale") {
lbajardsilogic@0 152
lbajardsilogic@0 153 if (min) *min = 0;
lbajardsilogic@0 154 if (max) *max = 3;
lbajardsilogic@0 155 if (deflt) *deflt = int(AutoAlignScale);
lbajardsilogic@0 156
lbajardsilogic@0 157 val = int(m_verticalScale);
lbajardsilogic@0 158
lbajardsilogic@0 159 } else if (name == "Scale Units") {
lbajardsilogic@0 160
lbajardsilogic@0 161 if (deflt) *deflt = 0;
lbajardsilogic@0 162 if (m_model) {
lbajardsilogic@0 163 val = UnitDatabase::getInstance()->getUnitId
lbajardsilogic@0 164 (m_model->getScaleUnits());
lbajardsilogic@0 165 }
lbajardsilogic@0 166
lbajardsilogic@0 167 } else {
lbajardsilogic@0 168
lbajardsilogic@0 169 val = Layer::getPropertyRangeAndValue(name, min, max, deflt);
lbajardsilogic@0 170 }
lbajardsilogic@0 171
lbajardsilogic@0 172 return val;
lbajardsilogic@0 173 }
lbajardsilogic@0 174
lbajardsilogic@0 175 QString
lbajardsilogic@0 176 TimeValueLayer::getPropertyValueLabel(const PropertyName &name,
lbajardsilogic@0 177 int value) const
lbajardsilogic@0 178 {
lbajardsilogic@0 179 if (name == "Colour") {
lbajardsilogic@0 180 if (m_plotStyle == PlotSegmentation) {
lbajardsilogic@0 181 return ColourMapper::getColourMapName(value);
lbajardsilogic@0 182 } else {
lbajardsilogic@0 183 switch (value) {
lbajardsilogic@0 184 default:
lbajardsilogic@0 185 case 0: return tr("Black");
lbajardsilogic@0 186 case 1: return tr("Red");
lbajardsilogic@0 187 case 2: return tr("Blue");
lbajardsilogic@0 188 case 3: return tr("Green");
lbajardsilogic@0 189 case 4: return tr("Purple");
lbajardsilogic@0 190 case 5: return tr("Orange");
lbajardsilogic@0 191 }
lbajardsilogic@0 192 }
lbajardsilogic@0 193 } else if (name == "Plot Type") {
lbajardsilogic@0 194 switch (value) {
lbajardsilogic@0 195 default:
lbajardsilogic@0 196 case 0: return tr("Points");
lbajardsilogic@0 197 case 1: return tr("Stems");
lbajardsilogic@0 198 case 2: return tr("Connected Points");
lbajardsilogic@0 199 case 3: return tr("Lines");
lbajardsilogic@0 200 case 4: return tr("Curve");
lbajardsilogic@0 201 case 5: return tr("Segmentation");
lbajardsilogic@0 202 }
lbajardsilogic@0 203 } else if (name == "Vertical Scale") {
lbajardsilogic@0 204 switch (value) {
lbajardsilogic@0 205 default:
lbajardsilogic@0 206 case 0: return tr("Auto-Align");
lbajardsilogic@0 207 case 1: return tr("Linear");
lbajardsilogic@0 208 case 2: return tr("Log");
lbajardsilogic@0 209 case 3: return tr("+/-1");
lbajardsilogic@0 210 }
lbajardsilogic@0 211 }
lbajardsilogic@0 212 return tr("<unknown>");
lbajardsilogic@0 213 }
lbajardsilogic@0 214
lbajardsilogic@0 215 void
lbajardsilogic@0 216 TimeValueLayer::setProperty(const PropertyName &name, int value)
lbajardsilogic@0 217 {
lbajardsilogic@0 218 if (name == "Colour") {
lbajardsilogic@0 219 if (m_plotStyle == PlotSegmentation) {
lbajardsilogic@0 220 setFillColourMap(value);
lbajardsilogic@0 221 } else {
lbajardsilogic@0 222 switch (value) {
lbajardsilogic@0 223 default:
lbajardsilogic@0 224 case 0: setBaseColour(Qt::black); break;
lbajardsilogic@0 225 case 1: setBaseColour(Qt::darkRed); break;
lbajardsilogic@0 226 case 2: setBaseColour(Qt::darkBlue); break;
lbajardsilogic@0 227 case 3: setBaseColour(Qt::darkGreen); break;
lbajardsilogic@0 228 case 4: setBaseColour(QColor(200, 50, 255)); break;
lbajardsilogic@0 229 case 5: setBaseColour(QColor(255, 150, 50)); break;
lbajardsilogic@0 230 }
lbajardsilogic@0 231 }
lbajardsilogic@0 232 } else if (name == "Plot Type") {
lbajardsilogic@0 233 setPlotStyle(PlotStyle(value));
lbajardsilogic@0 234 } else if (name == "Vertical Scale") {
lbajardsilogic@0 235 setVerticalScale(VerticalScale(value));
lbajardsilogic@0 236 } else if (name == "Scale Units") {
lbajardsilogic@0 237 if (m_model) {
lbajardsilogic@0 238 m_model->setScaleUnits
lbajardsilogic@0 239 (UnitDatabase::getInstance()->getUnitById(value));
lbajardsilogic@0 240 emit modelChanged();
lbajardsilogic@0 241 }
lbajardsilogic@0 242 }
lbajardsilogic@0 243 }
lbajardsilogic@0 244
lbajardsilogic@0 245 void
lbajardsilogic@0 246 TimeValueLayer::setBaseColour(QColor colour)
lbajardsilogic@0 247 {
lbajardsilogic@0 248 if (m_colour == colour) return;
lbajardsilogic@0 249 m_colour = colour;
lbajardsilogic@0 250 emit layerParametersChanged();
lbajardsilogic@0 251 }
lbajardsilogic@0 252
lbajardsilogic@0 253 void
lbajardsilogic@0 254 TimeValueLayer::setFillColourMap(int map)
lbajardsilogic@0 255 {
lbajardsilogic@0 256 if (m_colourMap == map) return;
lbajardsilogic@0 257 m_colourMap = map;
lbajardsilogic@0 258 emit layerParametersChanged();
lbajardsilogic@0 259 }
lbajardsilogic@0 260
lbajardsilogic@0 261 void
lbajardsilogic@0 262 TimeValueLayer::setPlotStyle(PlotStyle style)
lbajardsilogic@0 263 {
lbajardsilogic@0 264 if (m_plotStyle == style) return;
lbajardsilogic@0 265 bool colourTypeChanged = (style == PlotSegmentation ||
lbajardsilogic@0 266 m_plotStyle == PlotSegmentation);
lbajardsilogic@0 267 m_plotStyle = style;
lbajardsilogic@0 268 if (colourTypeChanged) {
lbajardsilogic@0 269 emit layerParameterRangesChanged();
lbajardsilogic@0 270 }
lbajardsilogic@0 271 emit layerParametersChanged();
lbajardsilogic@0 272 }
lbajardsilogic@0 273
lbajardsilogic@0 274 void
lbajardsilogic@0 275 TimeValueLayer::setVerticalScale(VerticalScale scale)
lbajardsilogic@0 276 {
lbajardsilogic@0 277 if (m_verticalScale == scale) return;
lbajardsilogic@0 278 m_verticalScale = scale;
lbajardsilogic@0 279 emit layerParametersChanged();
lbajardsilogic@0 280 }
lbajardsilogic@0 281
lbajardsilogic@0 282 bool
lbajardsilogic@0 283 TimeValueLayer::isLayerScrollable(const View *v) const
lbajardsilogic@0 284 {
lbajardsilogic@0 285 // We don't illuminate sections in the line or curve modes, so
lbajardsilogic@0 286 // they're always scrollable
lbajardsilogic@0 287
lbajardsilogic@0 288 if (m_plotStyle == PlotLines ||
lbajardsilogic@0 289 m_plotStyle == PlotCurve) return true;
lbajardsilogic@0 290
lbajardsilogic@0 291 QPoint discard;
lbajardsilogic@0 292 return !v->shouldIlluminateLocalFeatures(this, discard);
lbajardsilogic@0 293 }
lbajardsilogic@0 294
lbajardsilogic@0 295 bool
lbajardsilogic@0 296 TimeValueLayer::getValueExtents(float &min, float &max,
lbajardsilogic@0 297 bool &logarithmic, QString &unit) const
lbajardsilogic@0 298 {
lbajardsilogic@0 299 if (!m_model) return false;
lbajardsilogic@0 300 min = m_model->getValueMinimum();
lbajardsilogic@0 301 max = m_model->getValueMaximum();
lbajardsilogic@0 302 logarithmic = (m_verticalScale == LogScale);
lbajardsilogic@0 303 unit = m_model->getScaleUnits();
lbajardsilogic@0 304 return true;
lbajardsilogic@0 305 }
lbajardsilogic@0 306
lbajardsilogic@0 307 bool
lbajardsilogic@0 308 TimeValueLayer::getDisplayExtents(float &min, float &max) const
lbajardsilogic@0 309 {
lbajardsilogic@0 310 if (!m_model || m_verticalScale == AutoAlignScale) return false;
lbajardsilogic@0 311
lbajardsilogic@0 312 min = m_model->getValueMinimum();
lbajardsilogic@0 313 max = m_model->getValueMaximum();
lbajardsilogic@0 314 return true;
lbajardsilogic@0 315 }
lbajardsilogic@0 316
lbajardsilogic@0 317 SparseTimeValueModel::PointList
lbajardsilogic@0 318 TimeValueLayer::getLocalPoints(View *v, int x) const
lbajardsilogic@0 319 {
lbajardsilogic@0 320 if (!m_model) return SparseTimeValueModel::PointList();
lbajardsilogic@0 321
lbajardsilogic@0 322 long frame = v->getFrameForX(x);
lbajardsilogic@0 323
lbajardsilogic@0 324 SparseTimeValueModel::PointList onPoints =
lbajardsilogic@0 325 m_model->getPoints(frame);
lbajardsilogic@0 326
lbajardsilogic@0 327 if (!onPoints.empty()) {
lbajardsilogic@0 328 return onPoints;
lbajardsilogic@0 329 }
lbajardsilogic@0 330
lbajardsilogic@0 331 SparseTimeValueModel::PointList prevPoints =
lbajardsilogic@0 332 m_model->getPreviousPoints(frame);
lbajardsilogic@0 333 SparseTimeValueModel::PointList nextPoints =
lbajardsilogic@0 334 m_model->getNextPoints(frame);
lbajardsilogic@0 335
lbajardsilogic@0 336 SparseTimeValueModel::PointList usePoints = prevPoints;
lbajardsilogic@0 337
lbajardsilogic@0 338 if (prevPoints.empty()) {
lbajardsilogic@0 339 usePoints = nextPoints;
lbajardsilogic@0 340 } else if (long(prevPoints.begin()->frame) < v->getStartFrame() &&
lbajardsilogic@0 341 !(nextPoints.begin()->frame > v->getEndFrame())) {
lbajardsilogic@0 342 usePoints = nextPoints;
lbajardsilogic@0 343 } else if (nextPoints.begin()->frame - frame <
lbajardsilogic@0 344 frame - prevPoints.begin()->frame) {
lbajardsilogic@0 345 usePoints = nextPoints;
lbajardsilogic@0 346 }
lbajardsilogic@0 347
lbajardsilogic@0 348 if (!usePoints.empty()) {
lbajardsilogic@0 349 int fuzz = 2;
lbajardsilogic@0 350 int px = v->getXForFrame(usePoints.begin()->frame);
lbajardsilogic@0 351 if ((px > x && px - x > fuzz) ||
lbajardsilogic@0 352 (px < x && x - px > fuzz + 1)) {
lbajardsilogic@0 353 usePoints.clear();
lbajardsilogic@0 354 }
lbajardsilogic@0 355 }
lbajardsilogic@0 356
lbajardsilogic@0 357 return usePoints;
lbajardsilogic@0 358 }
lbajardsilogic@0 359
lbajardsilogic@0 360 QString
lbajardsilogic@0 361 TimeValueLayer::getFeatureDescription(View *v, QPoint &pos) const
lbajardsilogic@0 362 {
lbajardsilogic@0 363 int x = pos.x();
lbajardsilogic@0 364
lbajardsilogic@0 365 if (!m_model || !m_model->getSampleRate()) return "";
lbajardsilogic@0 366
lbajardsilogic@0 367 SparseTimeValueModel::PointList points = getLocalPoints(v, x);
lbajardsilogic@0 368
lbajardsilogic@0 369 if (points.empty()) {
lbajardsilogic@0 370 if (!m_model->isReady()) {
lbajardsilogic@0 371 return tr("In progress");
lbajardsilogic@0 372 } else {
lbajardsilogic@0 373 return tr("No local points");
lbajardsilogic@0 374 }
lbajardsilogic@0 375 }
lbajardsilogic@0 376
lbajardsilogic@0 377 long useFrame = points.begin()->frame;
lbajardsilogic@0 378
lbajardsilogic@0 379 RealTime rt = RealTime::frame2RealTime(useFrame, m_model->getSampleRate());
lbajardsilogic@0 380
lbajardsilogic@0 381 QString text;
lbajardsilogic@0 382 QString unit = m_model->getScaleUnits();
lbajardsilogic@0 383 if (unit != "") unit = " " + unit;
lbajardsilogic@0 384
lbajardsilogic@0 385 if (points.begin()->label == "") {
lbajardsilogic@0 386 text = QString(tr("Time:\t%1\nValue:\t%2%3\nNo label"))
lbajardsilogic@0 387 .arg(rt.toText(true).c_str())
lbajardsilogic@0 388 .arg(points.begin()->value)
lbajardsilogic@0 389 .arg(unit);
lbajardsilogic@0 390 } else {
lbajardsilogic@0 391 text = QString(tr("Time:\t%1\nValue:\t%2%3\nLabel:\t%4"))
lbajardsilogic@0 392 .arg(rt.toText(true).c_str())
lbajardsilogic@0 393 .arg(points.begin()->value)
lbajardsilogic@0 394 .arg(unit)
lbajardsilogic@0 395 .arg(points.begin()->label);
lbajardsilogic@0 396 }
lbajardsilogic@0 397
lbajardsilogic@0 398 pos = QPoint(v->getXForFrame(useFrame),
lbajardsilogic@0 399 getYForValue(v, points.begin()->value));
lbajardsilogic@0 400 return text;
lbajardsilogic@0 401 }
lbajardsilogic@0 402
lbajardsilogic@0 403 bool
lbajardsilogic@0 404 TimeValueLayer::snapToFeatureFrame(View *v, int &frame,
lbajardsilogic@0 405 size_t &resolution,
lbajardsilogic@0 406 SnapType snap) const
lbajardsilogic@0 407 {
lbajardsilogic@0 408 if (!m_model) {
lbajardsilogic@0 409 return Layer::snapToFeatureFrame(v, frame, resolution, snap);
lbajardsilogic@0 410 }
lbajardsilogic@0 411
lbajardsilogic@0 412 resolution = m_model->getResolution();
lbajardsilogic@0 413 SparseTimeValueModel::PointList points;
lbajardsilogic@0 414
lbajardsilogic@0 415 if (snap == SnapNeighbouring) {
lbajardsilogic@0 416
lbajardsilogic@0 417 points = getLocalPoints(v, v->getXForFrame(frame));
lbajardsilogic@0 418 if (points.empty()) return false;
lbajardsilogic@0 419 frame = points.begin()->frame;
lbajardsilogic@0 420 return true;
lbajardsilogic@0 421 }
lbajardsilogic@0 422
lbajardsilogic@0 423 points = m_model->getPoints(frame, frame);
lbajardsilogic@0 424 int snapped = frame;
lbajardsilogic@0 425 bool found = false;
lbajardsilogic@0 426
lbajardsilogic@0 427 for (SparseTimeValueModel::PointList::const_iterator i = points.begin();
lbajardsilogic@0 428 i != points.end(); ++i) {
lbajardsilogic@0 429
lbajardsilogic@0 430 if (snap == SnapRight) {
lbajardsilogic@0 431
lbajardsilogic@0 432 if (i->frame > frame) {
lbajardsilogic@0 433 snapped = i->frame;
lbajardsilogic@0 434 found = true;
lbajardsilogic@0 435 break;
lbajardsilogic@0 436 }
lbajardsilogic@0 437
lbajardsilogic@0 438 } else if (snap == SnapLeft) {
lbajardsilogic@0 439
lbajardsilogic@0 440 if (i->frame <= frame) {
lbajardsilogic@0 441 snapped = i->frame;
lbajardsilogic@0 442 found = true; // don't break, as the next may be better
lbajardsilogic@0 443 } else {
lbajardsilogic@0 444 break;
lbajardsilogic@0 445 }
lbajardsilogic@0 446
lbajardsilogic@0 447 } else { // nearest
lbajardsilogic@0 448
lbajardsilogic@0 449 SparseTimeValueModel::PointList::const_iterator j = i;
lbajardsilogic@0 450 ++j;
lbajardsilogic@0 451
lbajardsilogic@0 452 if (j == points.end()) {
lbajardsilogic@0 453
lbajardsilogic@0 454 snapped = i->frame;
lbajardsilogic@0 455 found = true;
lbajardsilogic@0 456 break;
lbajardsilogic@0 457
lbajardsilogic@0 458 } else if (j->frame >= frame) {
lbajardsilogic@0 459
lbajardsilogic@0 460 if (j->frame - frame < frame - i->frame) {
lbajardsilogic@0 461 snapped = j->frame;
lbajardsilogic@0 462 } else {
lbajardsilogic@0 463 snapped = i->frame;
lbajardsilogic@0 464 }
lbajardsilogic@0 465 found = true;
lbajardsilogic@0 466 break;
lbajardsilogic@0 467 }
lbajardsilogic@0 468 }
lbajardsilogic@0 469 }
lbajardsilogic@0 470
lbajardsilogic@0 471 frame = snapped;
lbajardsilogic@0 472 return found;
lbajardsilogic@0 473 }
lbajardsilogic@0 474
lbajardsilogic@0 475 void
lbajardsilogic@0 476 TimeValueLayer::getScaleExtents(View *v, float &min, float &max, bool &log) const
lbajardsilogic@0 477 {
lbajardsilogic@0 478 min = 0.0;
lbajardsilogic@0 479 max = 0.0;
lbajardsilogic@0 480 log = false;
lbajardsilogic@0 481
lbajardsilogic@0 482 if (m_verticalScale == AutoAlignScale) {
lbajardsilogic@0 483
lbajardsilogic@0 484 if (!v->getValueExtents(m_model->getScaleUnits(), min, max, log)) {
lbajardsilogic@0 485 min = m_model->getValueMinimum();
lbajardsilogic@0 486 max = m_model->getValueMaximum();
lbajardsilogic@0 487 } else if (log) {
lbajardsilogic@0 488 LogRange::mapRange(min, max);
lbajardsilogic@0 489 }
lbajardsilogic@0 490
lbajardsilogic@0 491 } else if (m_verticalScale == PlusMinusOneScale) {
lbajardsilogic@0 492
lbajardsilogic@0 493 min = -1.0;
lbajardsilogic@0 494 max = 1.0;
lbajardsilogic@0 495
lbajardsilogic@0 496 } else {
lbajardsilogic@0 497
lbajardsilogic@0 498 min = m_model->getValueMinimum();
lbajardsilogic@0 499 max = m_model->getValueMaximum();
lbajardsilogic@0 500
lbajardsilogic@0 501 if (m_verticalScale == LogScale) {
lbajardsilogic@0 502 LogRange::mapRange(min, max);
lbajardsilogic@0 503 log = true;
lbajardsilogic@0 504 }
lbajardsilogic@0 505 }
lbajardsilogic@0 506
lbajardsilogic@0 507 if (max == min) max = min + 1.0;
lbajardsilogic@0 508 }
lbajardsilogic@0 509
lbajardsilogic@0 510 int
lbajardsilogic@0 511 TimeValueLayer::getYForValue(View *v, float val) const
lbajardsilogic@0 512 {
lbajardsilogic@0 513 float min = 0.0, max = 0.0;
lbajardsilogic@0 514 bool logarithmic = false;
lbajardsilogic@0 515 int h = v->height();
lbajardsilogic@0 516
lbajardsilogic@0 517 getScaleExtents(v, min, max, logarithmic);
lbajardsilogic@0 518
lbajardsilogic@0 519 // std::cerr << "getYForValue(" << val << "): min " << min << ", max "
lbajardsilogic@0 520 // << max << ", log " << logarithmic << std::endl;
lbajardsilogic@0 521
lbajardsilogic@0 522 if (logarithmic) {
lbajardsilogic@0 523 val = LogRange::map(val);
lbajardsilogic@0 524 }
lbajardsilogic@0 525
lbajardsilogic@0 526 return int(h - ((val - min) * h) / (max - min));
lbajardsilogic@0 527 }
lbajardsilogic@0 528
lbajardsilogic@0 529 float
lbajardsilogic@0 530 TimeValueLayer::getValueForY(View *v, int y) const
lbajardsilogic@0 531 {
lbajardsilogic@0 532 float min = 0.0, max = 0.0;
lbajardsilogic@0 533 bool logarithmic = false;
lbajardsilogic@0 534 int h = v->height();
lbajardsilogic@0 535
lbajardsilogic@0 536 getScaleExtents(v, min, max, logarithmic);
lbajardsilogic@0 537
lbajardsilogic@0 538 float val = min + (float(h - y) * float(max - min)) / h;
lbajardsilogic@0 539
lbajardsilogic@0 540 if (logarithmic) {
lbajardsilogic@0 541 val = powf(10.f, val);
lbajardsilogic@0 542 }
lbajardsilogic@0 543
lbajardsilogic@0 544 return val;
lbajardsilogic@0 545 }
lbajardsilogic@0 546
lbajardsilogic@0 547 QColor
lbajardsilogic@0 548 TimeValueLayer::getColourForValue(View *v, float val) const
lbajardsilogic@0 549 {
lbajardsilogic@0 550 float min, max;
lbajardsilogic@0 551 bool log;
lbajardsilogic@0 552 getScaleExtents(v, min, max, log);
lbajardsilogic@0 553
lbajardsilogic@0 554 if (min > max) std::swap(min, max);
lbajardsilogic@0 555 if (max == min) max = min + 1;
lbajardsilogic@0 556
lbajardsilogic@0 557 if (log) {
lbajardsilogic@0 558 LogRange::mapRange(min, max);
lbajardsilogic@0 559 val = LogRange::map(val);
lbajardsilogic@0 560 }
lbajardsilogic@0 561
lbajardsilogic@0 562 // std::cerr << "TimeValueLayer::getColourForValue: min " << min << ", max "
lbajardsilogic@0 563 // << max << ", log " << log << ", value " << val << std::endl;
lbajardsilogic@0 564
lbajardsilogic@0 565 QColor solid = ColourMapper(m_colourMap, min, max).map(val);
lbajardsilogic@0 566 return QColor(solid.red(), solid.green(), solid.blue(), 120);
lbajardsilogic@0 567 }
lbajardsilogic@0 568
lbajardsilogic@0 569 void
lbajardsilogic@0 570 TimeValueLayer::paint(View *v, QPainter &paint, QRect rect) const
lbajardsilogic@0 571 {
lbajardsilogic@0 572 if (!m_model || !m_model->isOK()) return;
lbajardsilogic@0 573
lbajardsilogic@0 574 int sampleRate = m_model->getSampleRate();
lbajardsilogic@0 575 if (!sampleRate) return;
lbajardsilogic@0 576
lbajardsilogic@0 577 // Profiler profiler("TimeValueLayer::paint", true);
lbajardsilogic@0 578
lbajardsilogic@0 579 int x0 = rect.left(), x1 = rect.right();
lbajardsilogic@0 580 long frame0 = v->getFrameForX(x0);
lbajardsilogic@0 581 long frame1 = v->getFrameForX(x1);
lbajardsilogic@0 582
lbajardsilogic@0 583 SparseTimeValueModel::PointList points(m_model->getPoints
lbajardsilogic@0 584 (frame0, frame1));
lbajardsilogic@0 585 if (points.empty()) return;
lbajardsilogic@0 586
lbajardsilogic@0 587 paint.setPen(m_colour);
lbajardsilogic@0 588
lbajardsilogic@0 589 QColor brushColour(m_colour);
lbajardsilogic@0 590 brushColour.setAlpha(80);
lbajardsilogic@0 591 paint.setBrush(brushColour);
lbajardsilogic@0 592
lbajardsilogic@0 593 // std::cerr << "TimeValueLayer::paint: resolution is "
lbajardsilogic@0 594 // << m_model->getResolution() << " frames" << std::endl;
lbajardsilogic@0 595
lbajardsilogic@0 596 float min = m_model->getValueMinimum();
lbajardsilogic@0 597 float max = m_model->getValueMaximum();
lbajardsilogic@0 598 if (max == min) max = min + 1.0;
lbajardsilogic@0 599
lbajardsilogic@0 600 int origin = int(nearbyint(v->height() -
lbajardsilogic@0 601 (-min * v->height()) / (max - min)));
lbajardsilogic@0 602
lbajardsilogic@0 603 QPoint localPos;
lbajardsilogic@0 604 long illuminateFrame = -1;
lbajardsilogic@0 605
lbajardsilogic@0 606 if (v->shouldIlluminateLocalFeatures(this, localPos)) {
lbajardsilogic@0 607 SparseTimeValueModel::PointList localPoints =
lbajardsilogic@0 608 getLocalPoints(v, localPos.x());
lbajardsilogic@0 609 if (!localPoints.empty()) illuminateFrame = localPoints.begin()->frame;
lbajardsilogic@0 610 }
lbajardsilogic@0 611
lbajardsilogic@0 612 int w =
lbajardsilogic@0 613 v->getXForFrame(frame0 + m_model->getResolution()) -
lbajardsilogic@0 614 v->getXForFrame(frame0);
lbajardsilogic@0 615
lbajardsilogic@0 616 paint.save();
lbajardsilogic@0 617
lbajardsilogic@0 618 QPainterPath path;
lbajardsilogic@0 619 int pointCount = 0;
lbajardsilogic@0 620
lbajardsilogic@0 621 int textY = 0;
lbajardsilogic@0 622 if (m_plotStyle == PlotSegmentation) {
lbajardsilogic@0 623 textY = v->getTextLabelHeight(this, paint);
lbajardsilogic@0 624 }
lbajardsilogic@0 625
lbajardsilogic@0 626 for (SparseTimeValueModel::PointList::const_iterator i = points.begin();
lbajardsilogic@0 627 i != points.end(); ++i) {
lbajardsilogic@0 628
lbajardsilogic@0 629 const SparseTimeValueModel::Point &p(*i);
lbajardsilogic@0 630
lbajardsilogic@0 631 int x = v->getXForFrame(p.frame);
lbajardsilogic@0 632 int y = getYForValue(v, p.value);
lbajardsilogic@0 633
lbajardsilogic@0 634 if (m_plotStyle != PlotSegmentation) {
lbajardsilogic@0 635 textY = y - paint.fontMetrics().height()
lbajardsilogic@0 636 + paint.fontMetrics().ascent();
lbajardsilogic@0 637 }
lbajardsilogic@0 638
lbajardsilogic@0 639 bool haveNext = false;
lbajardsilogic@0 640 int nx = v->getXForFrame(v->getModelsEndFrame());
lbajardsilogic@0 641 // m_model->getEndFrame());
lbajardsilogic@0 642 int ny = y;
lbajardsilogic@0 643
lbajardsilogic@0 644 SparseTimeValueModel::PointList::const_iterator j = i;
lbajardsilogic@0 645 ++j;
lbajardsilogic@0 646
lbajardsilogic@0 647 if (j != points.end()) {
lbajardsilogic@0 648 const SparseTimeValueModel::Point &q(*j);
lbajardsilogic@0 649 nx = v->getXForFrame(q.frame);
lbajardsilogic@0 650 ny = getYForValue(v, q.value);
lbajardsilogic@0 651 haveNext = true;
lbajardsilogic@0 652 }
lbajardsilogic@0 653
lbajardsilogic@0 654 // std::cout << "frame = " << p.frame << ", x = " << x << ", haveNext = " << haveNext
lbajardsilogic@0 655 // << ", nx = " << nx << std::endl;
lbajardsilogic@0 656
lbajardsilogic@0 657 int labelY = y;
lbajardsilogic@0 658
lbajardsilogic@0 659 if (w < 1) w = 1;
lbajardsilogic@0 660 paint.setPen(m_colour);
lbajardsilogic@0 661
lbajardsilogic@0 662 if (m_plotStyle == PlotSegmentation) {
lbajardsilogic@0 663 paint.setPen(Qt::black);
lbajardsilogic@0 664 paint.setBrush(getColourForValue(v, p.value));
lbajardsilogic@0 665 labelY = v->height();
lbajardsilogic@0 666 } else if (m_plotStyle == PlotLines ||
lbajardsilogic@0 667 m_plotStyle == PlotCurve) {
lbajardsilogic@0 668 paint.setBrush(Qt::NoBrush);
lbajardsilogic@0 669 } else {
lbajardsilogic@0 670 paint.setBrush(brushColour);
lbajardsilogic@0 671 }
lbajardsilogic@0 672
lbajardsilogic@0 673 if (m_plotStyle == PlotStems) {
lbajardsilogic@0 674 paint.setPen(brushColour);
lbajardsilogic@0 675 if (y < origin - 1) {
lbajardsilogic@0 676 paint.drawRect(x + w/2, y + 1, 1, origin - y);
lbajardsilogic@0 677 } else if (y > origin + 1) {
lbajardsilogic@0 678 paint.drawRect(x + w/2, origin, 1, y - origin - 1);
lbajardsilogic@0 679 }
lbajardsilogic@0 680 paint.setPen(m_colour);
lbajardsilogic@0 681 }
lbajardsilogic@0 682
lbajardsilogic@0 683 if (illuminateFrame == p.frame) {
lbajardsilogic@0 684
lbajardsilogic@0 685 //!!! aside from the problem of choosing a colour, it'd be
lbajardsilogic@0 686 //better to save the highlighted rects and draw them at
lbajardsilogic@0 687 //the end perhaps
lbajardsilogic@0 688
lbajardsilogic@0 689 //!!! not equipped to illuminate the right section in line
lbajardsilogic@0 690 //or curve mode
lbajardsilogic@0 691
lbajardsilogic@0 692 if (m_plotStyle != PlotCurve &&
lbajardsilogic@0 693 m_plotStyle != PlotLines) {
lbajardsilogic@0 694 paint.setPen(Qt::black);//!!!
lbajardsilogic@0 695 if (m_plotStyle != PlotSegmentation) {
lbajardsilogic@0 696 paint.setBrush(Qt::black);//!!!
lbajardsilogic@0 697 }
lbajardsilogic@0 698 }
lbajardsilogic@0 699 }
lbajardsilogic@0 700
lbajardsilogic@0 701 if (m_plotStyle != PlotLines &&
lbajardsilogic@0 702 m_plotStyle != PlotCurve &&
lbajardsilogic@0 703 m_plotStyle != PlotSegmentation) {
lbajardsilogic@0 704 paint.drawRect(x, y - 1, w, 2);
lbajardsilogic@0 705 }
lbajardsilogic@0 706
lbajardsilogic@0 707 if (m_plotStyle == PlotConnectedPoints ||
lbajardsilogic@0 708 m_plotStyle == PlotLines ||
lbajardsilogic@0 709 m_plotStyle == PlotCurve) {
lbajardsilogic@0 710
lbajardsilogic@0 711 if (haveNext) {
lbajardsilogic@0 712
lbajardsilogic@0 713 if (m_plotStyle == PlotConnectedPoints) {
lbajardsilogic@0 714
lbajardsilogic@0 715 paint.save();
lbajardsilogic@0 716 paint.setPen(brushColour);
lbajardsilogic@0 717 paint.drawLine(x + w, y, nx, ny);
lbajardsilogic@0 718 paint.restore();
lbajardsilogic@0 719
lbajardsilogic@0 720 } else if (m_plotStyle == PlotLines) {
lbajardsilogic@0 721
lbajardsilogic@0 722 paint.drawLine(x + w/2, y, nx + w/2, ny);
lbajardsilogic@0 723
lbajardsilogic@0 724 } else {
lbajardsilogic@0 725
lbajardsilogic@0 726 float x0 = x + float(w)/2;
lbajardsilogic@0 727 float x1 = nx + float(w)/2;
lbajardsilogic@0 728
lbajardsilogic@0 729 float y0 = y;
lbajardsilogic@0 730 float y1 = ny;
lbajardsilogic@0 731
lbajardsilogic@0 732 if (pointCount == 0) {
lbajardsilogic@0 733 path.moveTo((x0 + x1) / 2, (y0 + y1) / 2);
lbajardsilogic@0 734 }
lbajardsilogic@0 735 ++pointCount;
lbajardsilogic@0 736
lbajardsilogic@0 737 if (nx - x > 5) {
lbajardsilogic@0 738 path.cubicTo(x0, y0,
lbajardsilogic@0 739 x0, y0,
lbajardsilogic@0 740 (x0 + x1) / 2, (y0 + y1) / 2);
lbajardsilogic@0 741
lbajardsilogic@0 742 // // or
lbajardsilogic@0 743 // path.quadTo(x0, y0, (x0 + x1) / 2, (y0 + y1) / 2);
lbajardsilogic@0 744
lbajardsilogic@0 745 } else {
lbajardsilogic@0 746 path.lineTo((x0 + x1) / 2, (y0 + y1) / 2);
lbajardsilogic@0 747 }
lbajardsilogic@0 748 }
lbajardsilogic@0 749 }
lbajardsilogic@0 750 }
lbajardsilogic@0 751
lbajardsilogic@0 752 if (m_plotStyle == PlotSegmentation) {
lbajardsilogic@0 753
lbajardsilogic@0 754 // std::cerr << "drawing rect" << std::endl;
lbajardsilogic@0 755
lbajardsilogic@0 756 if (nx <= x) continue;
lbajardsilogic@0 757
lbajardsilogic@0 758 if (illuminateFrame != p.frame &&
lbajardsilogic@0 759 (nx < x + 5 || x >= v->width() - 1)) {
lbajardsilogic@0 760 paint.setPen(Qt::NoPen);
lbajardsilogic@0 761 }
lbajardsilogic@0 762
lbajardsilogic@0 763 paint.drawRect(x, -1, nx - x, v->height() + 1);
lbajardsilogic@0 764 }
lbajardsilogic@0 765
lbajardsilogic@0 766 if (p.label != "") {
lbajardsilogic@0 767 if (!haveNext || nx > x + 6 + paint.fontMetrics().width(p.label)) {
lbajardsilogic@0 768 paint.drawText(x + 5, textY, p.label);
lbajardsilogic@0 769 }
lbajardsilogic@0 770 }
lbajardsilogic@0 771 }
lbajardsilogic@0 772
lbajardsilogic@0 773 if (m_plotStyle == PlotCurve && !path.isEmpty()) {
lbajardsilogic@0 774 paint.setRenderHint(QPainter::Antialiasing, pointCount <= v->width());
lbajardsilogic@0 775 paint.drawPath(path);
lbajardsilogic@0 776 }
lbajardsilogic@0 777
lbajardsilogic@0 778 paint.restore();
lbajardsilogic@0 779
lbajardsilogic@0 780 // looks like save/restore doesn't deal with this:
lbajardsilogic@0 781 paint.setRenderHint(QPainter::Antialiasing, false);
lbajardsilogic@0 782 }
lbajardsilogic@0 783
lbajardsilogic@0 784 int
lbajardsilogic@0 785 TimeValueLayer::getVerticalScaleWidth(View *, QPainter &paint) const
lbajardsilogic@0 786 {
lbajardsilogic@0 787 int w = paint.fontMetrics().width("-000.000");
lbajardsilogic@0 788 if (m_plotStyle == PlotSegmentation) return w + 20;
lbajardsilogic@0 789 else return w + 10;
lbajardsilogic@0 790 }
lbajardsilogic@0 791
lbajardsilogic@0 792 void
lbajardsilogic@0 793 TimeValueLayer::paintVerticalScale(View *v, QPainter &paint, QRect) const
lbajardsilogic@0 794 {
lbajardsilogic@0 795 if (!m_model) return;
lbajardsilogic@0 796
lbajardsilogic@0 797 int h = v->height();
lbajardsilogic@0 798
lbajardsilogic@0 799 int n = 10;
lbajardsilogic@0 800
lbajardsilogic@0 801 float max = m_model->getValueMaximum();
lbajardsilogic@0 802 float min = m_model->getValueMinimum();
lbajardsilogic@0 803 float val = min;
lbajardsilogic@0 804 float inc = (max - val) / n;
lbajardsilogic@0 805
lbajardsilogic@0 806 char buffer[40];
lbajardsilogic@0 807
lbajardsilogic@0 808 int w = getVerticalScaleWidth(v, paint);
lbajardsilogic@0 809
lbajardsilogic@0 810 int tx = 5;
lbajardsilogic@0 811
lbajardsilogic@0 812 int boxx = 5, boxy = 5;
lbajardsilogic@0 813 if (m_model->getScaleUnits() != "") {
lbajardsilogic@0 814 boxy += paint.fontMetrics().height();
lbajardsilogic@0 815 }
lbajardsilogic@0 816 int boxw = 10, boxh = h - boxy - 5;
lbajardsilogic@0 817
lbajardsilogic@0 818 if (m_plotStyle == PlotSegmentation) {
lbajardsilogic@0 819 tx += boxx + boxw;
lbajardsilogic@0 820 paint.drawRect(boxx, boxy, boxw, boxh);
lbajardsilogic@0 821 }
lbajardsilogic@0 822
lbajardsilogic@0 823 if (m_plotStyle == PlotSegmentation) {
lbajardsilogic@0 824 paint.save();
lbajardsilogic@0 825 for (int y = 0; y < boxh; ++y) {
lbajardsilogic@0 826 float val = ((boxh - y) * (max - min)) / boxh + min;
lbajardsilogic@0 827 paint.setPen(getColourForValue(v, val));
lbajardsilogic@0 828 paint.drawLine(boxx + 1, y + boxy + 1, boxx + boxw, y + boxy + 1);
lbajardsilogic@0 829 }
lbajardsilogic@0 830 paint.restore();
lbajardsilogic@0 831 }
lbajardsilogic@0 832
lbajardsilogic@0 833 for (int i = 0; i < n; ++i) {
lbajardsilogic@0 834
lbajardsilogic@0 835 int y, ty;
lbajardsilogic@0 836 bool drawText = true;
lbajardsilogic@0 837
lbajardsilogic@0 838 if (m_plotStyle == PlotSegmentation) {
lbajardsilogic@0 839 y = boxy + int(boxh - ((val - min) * boxh) / (max - min));
lbajardsilogic@0 840 ty = y;
lbajardsilogic@0 841 } else {
lbajardsilogic@0 842 if (i == n-1) {
lbajardsilogic@0 843 if (m_model->getScaleUnits() != "") drawText = false;
lbajardsilogic@0 844 }
lbajardsilogic@0 845 y = getYForValue(v, val);
lbajardsilogic@0 846 ty = y - paint.fontMetrics().height() +
lbajardsilogic@0 847 paint.fontMetrics().ascent();
lbajardsilogic@0 848 }
lbajardsilogic@0 849
lbajardsilogic@0 850 sprintf(buffer, "%.3f", val);
lbajardsilogic@0 851 QString label = QString(buffer);
lbajardsilogic@0 852
lbajardsilogic@0 853 if (m_plotStyle != PlotSegmentation) {
lbajardsilogic@0 854 paint.drawLine(w - 5, y, w, y);
lbajardsilogic@0 855 } else {
lbajardsilogic@0 856 paint.drawLine(boxx + boxw - boxw/3, y, boxx + boxw, y);
lbajardsilogic@0 857 }
lbajardsilogic@0 858
lbajardsilogic@0 859 if (drawText) paint.drawText(tx, ty, label);
lbajardsilogic@0 860 val += inc;
lbajardsilogic@0 861 }
lbajardsilogic@0 862
lbajardsilogic@0 863 if (m_model->getScaleUnits() != "") {
lbajardsilogic@0 864 paint.drawText(5, 5 + paint.fontMetrics().ascent(),
lbajardsilogic@0 865 m_model->getScaleUnits());
lbajardsilogic@0 866 }
lbajardsilogic@0 867 }
lbajardsilogic@0 868
lbajardsilogic@0 869 void
lbajardsilogic@0 870 TimeValueLayer::drawStart(View *v, QMouseEvent *e)
lbajardsilogic@0 871 {
lbajardsilogic@0 872 // std::cerr << "TimeValueLayer::drawStart(" << e->x() << "," << e->y() << ")" << std::endl;
lbajardsilogic@0 873
lbajardsilogic@0 874 if (!m_model) return;
lbajardsilogic@0 875
lbajardsilogic@0 876 long frame = v->getFrameForX(e->x());
lbajardsilogic@0 877 long resolution = m_model->getResolution();
lbajardsilogic@0 878 if (frame < 0) frame = 0;
lbajardsilogic@0 879 frame = (frame / resolution) * resolution;
lbajardsilogic@0 880
lbajardsilogic@0 881 float value = getValueForY(v, e->y());
lbajardsilogic@0 882
lbajardsilogic@0 883 bool havePoint = false;
lbajardsilogic@0 884
lbajardsilogic@0 885 SparseTimeValueModel::PointList points = getLocalPoints(v, e->x());
lbajardsilogic@0 886 if (!points.empty()) {
lbajardsilogic@0 887 for (SparseTimeValueModel::PointList::iterator i = points.begin();
lbajardsilogic@0 888 i != points.end(); ++i) {
lbajardsilogic@0 889 if (((i->frame / resolution) * resolution) != frame) {
lbajardsilogic@0 890 // std::cerr << "ignoring out-of-range frame at " << i->frame << std::endl;
lbajardsilogic@0 891 continue;
lbajardsilogic@0 892 }
lbajardsilogic@0 893 m_editingPoint = *i;
lbajardsilogic@0 894 havePoint = true;
lbajardsilogic@0 895 }
lbajardsilogic@0 896 }
lbajardsilogic@0 897
lbajardsilogic@0 898 if (!havePoint) {
lbajardsilogic@0 899 m_editingPoint = SparseTimeValueModel::Point
lbajardsilogic@0 900 (frame, value, tr("New Point"));
lbajardsilogic@0 901 }
lbajardsilogic@0 902
lbajardsilogic@0 903 m_originalPoint = m_editingPoint;
lbajardsilogic@0 904
lbajardsilogic@0 905 if (m_editingCommand) m_editingCommand->finish();
lbajardsilogic@0 906 m_editingCommand = new SparseTimeValueModel::EditCommand(m_model,
lbajardsilogic@0 907 tr("Draw Point"));
lbajardsilogic@0 908 if (!havePoint) {
lbajardsilogic@0 909 m_editingCommand->addPoint(m_editingPoint);
lbajardsilogic@0 910 }
lbajardsilogic@0 911
lbajardsilogic@0 912 m_editing = true;
lbajardsilogic@0 913 }
lbajardsilogic@0 914
lbajardsilogic@0 915 void
lbajardsilogic@0 916 TimeValueLayer::drawDrag(View *v, QMouseEvent *e)
lbajardsilogic@0 917 {
lbajardsilogic@0 918 // std::cerr << "TimeValueLayer::drawDrag(" << e->x() << "," << e->y() << ")" << std::endl;
lbajardsilogic@0 919
lbajardsilogic@0 920 if (!m_model || !m_editing) return;
lbajardsilogic@0 921
lbajardsilogic@0 922 long frame = v->getFrameForX(e->x());
lbajardsilogic@0 923 long resolution = m_model->getResolution();
lbajardsilogic@0 924 if (frame < 0) frame = 0;
lbajardsilogic@0 925 frame = (frame / resolution) * resolution;
lbajardsilogic@0 926
lbajardsilogic@0 927 float value = getValueForY(v, e->y());
lbajardsilogic@0 928
lbajardsilogic@0 929 SparseTimeValueModel::PointList points = getLocalPoints(v, e->x());
lbajardsilogic@0 930
lbajardsilogic@0 931 // std::cerr << points.size() << " points" << std::endl;
lbajardsilogic@0 932
lbajardsilogic@0 933 bool havePoint = false;
lbajardsilogic@0 934
lbajardsilogic@0 935 if (!points.empty()) {
lbajardsilogic@0 936 for (SparseTimeValueModel::PointList::iterator i = points.begin();
lbajardsilogic@0 937 i != points.end(); ++i) {
lbajardsilogic@0 938 if (i->frame == m_editingPoint.frame &&
lbajardsilogic@0 939 i->value == m_editingPoint.value) {
lbajardsilogic@0 940 // std::cerr << "ignoring current editing point at " << i->frame << ", " << i->value << std::endl;
lbajardsilogic@0 941 continue;
lbajardsilogic@0 942 }
lbajardsilogic@0 943 if (((i->frame / resolution) * resolution) != frame) {
lbajardsilogic@0 944 // std::cerr << "ignoring out-of-range frame at " << i->frame << std::endl;
lbajardsilogic@0 945 continue;
lbajardsilogic@0 946 }
lbajardsilogic@0 947 // std::cerr << "adjusting to new point at " << i->frame << ", " << i->value << std::endl;
lbajardsilogic@0 948 m_editingPoint = *i;
lbajardsilogic@0 949 m_originalPoint = m_editingPoint;
lbajardsilogic@0 950 m_editingCommand->deletePoint(m_editingPoint);
lbajardsilogic@0 951 havePoint = true;
lbajardsilogic@0 952 }
lbajardsilogic@0 953 }
lbajardsilogic@0 954
lbajardsilogic@0 955 if (!havePoint) {
lbajardsilogic@0 956 if (frame == m_editingPoint.frame) {
lbajardsilogic@0 957 m_editingCommand->deletePoint(m_editingPoint);
lbajardsilogic@0 958 }
lbajardsilogic@0 959 }
lbajardsilogic@0 960
lbajardsilogic@0 961 // m_editingCommand->deletePoint(m_editingPoint);
lbajardsilogic@0 962 m_editingPoint.frame = frame;
lbajardsilogic@0 963 m_editingPoint.value = value;
lbajardsilogic@0 964 m_editingCommand->addPoint(m_editingPoint);
lbajardsilogic@0 965 }
lbajardsilogic@0 966
lbajardsilogic@0 967 void
lbajardsilogic@0 968 TimeValueLayer::drawEnd(View *, QMouseEvent *)
lbajardsilogic@0 969 {
lbajardsilogic@0 970 // std::cerr << "TimeValueLayer::drawEnd(" << e->x() << "," << e->y() << ")" << std::endl;
lbajardsilogic@0 971 if (!m_model || !m_editing) return;
lbajardsilogic@0 972 m_editingCommand->finish();
lbajardsilogic@0 973 m_editingCommand = 0;
lbajardsilogic@0 974 m_editing = false;
lbajardsilogic@0 975 }
lbajardsilogic@0 976
lbajardsilogic@0 977 void
lbajardsilogic@0 978 TimeValueLayer::editStart(View *v, QMouseEvent *e)
lbajardsilogic@0 979 {
lbajardsilogic@0 980 // std::cerr << "TimeValueLayer::editStart(" << e->x() << "," << e->y() << ")" << std::endl;
lbajardsilogic@0 981
lbajardsilogic@0 982 if (!m_model) return;
lbajardsilogic@0 983
lbajardsilogic@0 984 SparseTimeValueModel::PointList points = getLocalPoints(v, e->x());
lbajardsilogic@0 985 if (points.empty()) return;
lbajardsilogic@0 986
lbajardsilogic@0 987 m_editingPoint = *points.begin();
lbajardsilogic@0 988 m_originalPoint = m_editingPoint;
lbajardsilogic@0 989
lbajardsilogic@0 990 if (m_editingCommand) {
lbajardsilogic@0 991 m_editingCommand->finish();
lbajardsilogic@0 992 m_editingCommand = 0;
lbajardsilogic@0 993 }
lbajardsilogic@0 994
lbajardsilogic@0 995 m_editing = true;
lbajardsilogic@0 996 }
lbajardsilogic@0 997
lbajardsilogic@0 998 void
lbajardsilogic@0 999 TimeValueLayer::editDrag(View *v, QMouseEvent *e)
lbajardsilogic@0 1000 {
lbajardsilogic@0 1001 // std::cerr << "TimeValueLayer::editDrag(" << e->x() << "," << e->y() << ")" << std::endl;
lbajardsilogic@0 1002
lbajardsilogic@0 1003 if (!m_model || !m_editing) return;
lbajardsilogic@0 1004
lbajardsilogic@0 1005 long frame = v->getFrameForX(e->x());
lbajardsilogic@0 1006 if (frame < 0) frame = 0;
lbajardsilogic@0 1007 frame = frame / m_model->getResolution() * m_model->getResolution();
lbajardsilogic@0 1008
lbajardsilogic@0 1009 float value = getValueForY(v, e->y());
lbajardsilogic@0 1010
lbajardsilogic@0 1011 if (!m_editingCommand) {
lbajardsilogic@0 1012 m_editingCommand = new SparseTimeValueModel::EditCommand(m_model,
lbajardsilogic@0 1013 tr("Drag Point"));
lbajardsilogic@0 1014 }
lbajardsilogic@0 1015
lbajardsilogic@0 1016 m_editingCommand->deletePoint(m_editingPoint);
lbajardsilogic@0 1017 m_editingPoint.frame = frame;
lbajardsilogic@0 1018 m_editingPoint.value = value;
lbajardsilogic@0 1019 m_editingCommand->addPoint(m_editingPoint);
lbajardsilogic@0 1020 }
lbajardsilogic@0 1021
lbajardsilogic@0 1022 void
lbajardsilogic@0 1023 TimeValueLayer::editEnd(View *, QMouseEvent *)
lbajardsilogic@0 1024 {
lbajardsilogic@0 1025 // std::cerr << "TimeValueLayer::editEnd(" << e->x() << "," << e->y() << ")" << std::endl;
lbajardsilogic@0 1026 if (!m_model || !m_editing) return;
lbajardsilogic@0 1027
lbajardsilogic@0 1028 if (m_editingCommand) {
lbajardsilogic@0 1029
lbajardsilogic@0 1030 QString newName = m_editingCommand->getName();
lbajardsilogic@0 1031
lbajardsilogic@0 1032 if (m_editingPoint.frame != m_originalPoint.frame) {
lbajardsilogic@0 1033 if (m_editingPoint.value != m_originalPoint.value) {
lbajardsilogic@0 1034 newName = tr("Edit Point");
lbajardsilogic@0 1035 } else {
lbajardsilogic@0 1036 newName = tr("Relocate Point");
lbajardsilogic@0 1037 }
lbajardsilogic@0 1038 } else {
lbajardsilogic@0 1039 newName = tr("Change Point Value");
lbajardsilogic@0 1040 }
lbajardsilogic@0 1041
lbajardsilogic@0 1042 m_editingCommand->setName(newName);
lbajardsilogic@0 1043 m_editingCommand->finish();
lbajardsilogic@0 1044 }
lbajardsilogic@0 1045
lbajardsilogic@0 1046 m_editingCommand = 0;
lbajardsilogic@0 1047 m_editing = false;
lbajardsilogic@0 1048 }
lbajardsilogic@0 1049
lbajardsilogic@0 1050 void
lbajardsilogic@0 1051 TimeValueLayer::editOpen(View *v, QMouseEvent *e)
lbajardsilogic@0 1052 {
lbajardsilogic@0 1053 if (!m_model) return;
lbajardsilogic@0 1054
lbajardsilogic@0 1055 SparseTimeValueModel::PointList points = getLocalPoints(v, e->x());
lbajardsilogic@0 1056 if (points.empty()) return;
lbajardsilogic@0 1057
lbajardsilogic@0 1058 SparseTimeValueModel::Point point = *points.begin();
lbajardsilogic@0 1059
lbajardsilogic@0 1060 ItemEditDialog *dialog = new ItemEditDialog
lbajardsilogic@0 1061 (m_model->getSampleRate(),
lbajardsilogic@0 1062 ItemEditDialog::ShowTime |
lbajardsilogic@0 1063 ItemEditDialog::ShowValue |
lbajardsilogic@0 1064 ItemEditDialog::ShowText,
lbajardsilogic@0 1065 m_model->getScaleUnits());
lbajardsilogic@0 1066
lbajardsilogic@0 1067 dialog->setFrameTime(point.frame);
lbajardsilogic@0 1068 dialog->setValue(point.value);
lbajardsilogic@0 1069 dialog->setText(point.label);
lbajardsilogic@0 1070
lbajardsilogic@0 1071 if (dialog->exec() == QDialog::Accepted) {
lbajardsilogic@0 1072
lbajardsilogic@0 1073 SparseTimeValueModel::Point newPoint = point;
lbajardsilogic@0 1074 newPoint.frame = dialog->getFrameTime();
lbajardsilogic@0 1075 newPoint.value = dialog->getValue();
lbajardsilogic@0 1076 newPoint.label = dialog->getText();
lbajardsilogic@0 1077
lbajardsilogic@0 1078 SparseTimeValueModel::EditCommand *command =
lbajardsilogic@0 1079 new SparseTimeValueModel::EditCommand(m_model, tr("Edit Point"));
lbajardsilogic@0 1080 command->deletePoint(point);
lbajardsilogic@0 1081 command->addPoint(newPoint);
lbajardsilogic@0 1082 command->finish();
lbajardsilogic@0 1083 }
lbajardsilogic@0 1084
lbajardsilogic@0 1085 delete dialog;
lbajardsilogic@0 1086 }
lbajardsilogic@0 1087
lbajardsilogic@0 1088 void
lbajardsilogic@0 1089 TimeValueLayer::moveSelection(Selection s, size_t newStartFrame)
lbajardsilogic@0 1090 {
lbajardsilogic@0 1091 if (!m_model) return;
lbajardsilogic@0 1092
lbajardsilogic@0 1093 SparseTimeValueModel::EditCommand *command =
lbajardsilogic@0 1094 new SparseTimeValueModel::EditCommand(m_model,
lbajardsilogic@0 1095 tr("Drag Selection"));
lbajardsilogic@0 1096
lbajardsilogic@0 1097 SparseTimeValueModel::PointList points =
lbajardsilogic@0 1098 m_model->getPoints(s.getStartFrame(), s.getEndFrame());
lbajardsilogic@0 1099
lbajardsilogic@0 1100 for (SparseTimeValueModel::PointList::iterator i = points.begin();
lbajardsilogic@0 1101 i != points.end(); ++i) {
lbajardsilogic@0 1102
lbajardsilogic@0 1103 if (s.contains(i->frame)) {
lbajardsilogic@0 1104 SparseTimeValueModel::Point newPoint(*i);
lbajardsilogic@0 1105 newPoint.frame = i->frame + newStartFrame - s.getStartFrame();
lbajardsilogic@0 1106 command->deletePoint(*i);
lbajardsilogic@0 1107 command->addPoint(newPoint);
lbajardsilogic@0 1108 }
lbajardsilogic@0 1109 }
lbajardsilogic@0 1110
lbajardsilogic@0 1111 command->finish();
lbajardsilogic@0 1112 }
lbajardsilogic@0 1113
lbajardsilogic@0 1114 void
lbajardsilogic@0 1115 TimeValueLayer::resizeSelection(Selection s, Selection newSize)
lbajardsilogic@0 1116 {
lbajardsilogic@0 1117 if (!m_model) return;
lbajardsilogic@0 1118
lbajardsilogic@0 1119 SparseTimeValueModel::EditCommand *command =
lbajardsilogic@0 1120 new SparseTimeValueModel::EditCommand(m_model,
lbajardsilogic@0 1121 tr("Resize Selection"));
lbajardsilogic@0 1122
lbajardsilogic@0 1123 SparseTimeValueModel::PointList points =
lbajardsilogic@0 1124 m_model->getPoints(s.getStartFrame(), s.getEndFrame());
lbajardsilogic@0 1125
lbajardsilogic@0 1126 double ratio =
lbajardsilogic@0 1127 double(newSize.getEndFrame() - newSize.getStartFrame()) /
lbajardsilogic@0 1128 double(s.getEndFrame() - s.getStartFrame());
lbajardsilogic@0 1129
lbajardsilogic@0 1130 for (SparseTimeValueModel::PointList::iterator i = points.begin();
lbajardsilogic@0 1131 i != points.end(); ++i) {
lbajardsilogic@0 1132
lbajardsilogic@0 1133 if (s.contains(i->frame)) {
lbajardsilogic@0 1134
lbajardsilogic@0 1135 double target = i->frame;
lbajardsilogic@0 1136 target = newSize.getStartFrame() +
lbajardsilogic@0 1137 double(target - s.getStartFrame()) * ratio;
lbajardsilogic@0 1138
lbajardsilogic@0 1139 SparseTimeValueModel::Point newPoint(*i);
lbajardsilogic@0 1140 newPoint.frame = lrint(target);
lbajardsilogic@0 1141 command->deletePoint(*i);
lbajardsilogic@0 1142 command->addPoint(newPoint);
lbajardsilogic@0 1143 }
lbajardsilogic@0 1144 }
lbajardsilogic@0 1145
lbajardsilogic@0 1146 command->finish();
lbajardsilogic@0 1147 }
lbajardsilogic@0 1148
lbajardsilogic@0 1149 void
lbajardsilogic@0 1150 TimeValueLayer::deleteSelection(Selection s)
lbajardsilogic@0 1151 {
lbajardsilogic@0 1152 if (!m_model) return;
lbajardsilogic@0 1153
lbajardsilogic@0 1154 SparseTimeValueModel::EditCommand *command =
lbajardsilogic@0 1155 new SparseTimeValueModel::EditCommand(m_model,
lbajardsilogic@0 1156 tr("Delete Selected Points"));
lbajardsilogic@0 1157
lbajardsilogic@0 1158 SparseTimeValueModel::PointList points =
lbajardsilogic@0 1159 m_model->getPoints(s.getStartFrame(), s.getEndFrame());
lbajardsilogic@0 1160
lbajardsilogic@0 1161 for (SparseTimeValueModel::PointList::iterator i = points.begin();
lbajardsilogic@0 1162 i != points.end(); ++i) {
lbajardsilogic@0 1163
lbajardsilogic@0 1164 if (s.contains(i->frame)) {
lbajardsilogic@0 1165 command->deletePoint(*i);
lbajardsilogic@0 1166 }
lbajardsilogic@0 1167 }
lbajardsilogic@0 1168
lbajardsilogic@0 1169 command->finish();
lbajardsilogic@0 1170 }
lbajardsilogic@0 1171
lbajardsilogic@0 1172 void
lbajardsilogic@0 1173 TimeValueLayer::copy(Selection s, Clipboard &to)
lbajardsilogic@0 1174 {
lbajardsilogic@0 1175 if (!m_model) return;
lbajardsilogic@0 1176
lbajardsilogic@0 1177 SparseTimeValueModel::PointList points =
lbajardsilogic@0 1178 m_model->getPoints(s.getStartFrame(), s.getEndFrame());
lbajardsilogic@0 1179
lbajardsilogic@0 1180 for (SparseTimeValueModel::PointList::iterator i = points.begin();
lbajardsilogic@0 1181 i != points.end(); ++i) {
lbajardsilogic@0 1182 if (s.contains(i->frame)) {
lbajardsilogic@0 1183 Clipboard::Point point(i->frame, i->value, i->label);
lbajardsilogic@0 1184 to.addPoint(point);
lbajardsilogic@0 1185 }
lbajardsilogic@0 1186 }
lbajardsilogic@0 1187 }
lbajardsilogic@0 1188
lbajardsilogic@0 1189 bool
lbajardsilogic@0 1190 TimeValueLayer::paste(const Clipboard &from, int frameOffset,
lbajardsilogic@0 1191 bool interactive)
lbajardsilogic@0 1192 {
lbajardsilogic@0 1193 if (!m_model) return false;
lbajardsilogic@0 1194
lbajardsilogic@0 1195 const Clipboard::PointList &points = from.getPoints();
lbajardsilogic@0 1196
lbajardsilogic@0 1197 SparseTimeValueModel::EditCommand *command =
lbajardsilogic@0 1198 new SparseTimeValueModel::EditCommand(m_model, tr("Paste"));
lbajardsilogic@0 1199
lbajardsilogic@0 1200 enum ValueAvailability {
lbajardsilogic@0 1201 UnknownAvailability,
lbajardsilogic@0 1202 NoValues,
lbajardsilogic@0 1203 SomeValues,
lbajardsilogic@0 1204 AllValues
lbajardsilogic@0 1205 };
lbajardsilogic@0 1206 enum ValueGeneration {
lbajardsilogic@0 1207 GenerateNone,
lbajardsilogic@0 1208 GenerateFromCounter,
lbajardsilogic@0 1209 GenerateFromFrameNumber,
lbajardsilogic@0 1210 GenerateFromRealTime,
lbajardsilogic@0 1211 GenerateFromRealTimeDifference,
lbajardsilogic@0 1212 GenerateFromTempo,
lbajardsilogic@0 1213 GenerateFromExistingNeighbour,
lbajardsilogic@0 1214 GenerateFromLabels
lbajardsilogic@0 1215 };
lbajardsilogic@0 1216
lbajardsilogic@0 1217 ValueGeneration generation = GenerateNone;
lbajardsilogic@0 1218
lbajardsilogic@0 1219 bool haveUsableLabels = false;
lbajardsilogic@0 1220 bool haveExistingItems = !(m_model->isEmpty());
lbajardsilogic@0 1221
lbajardsilogic@0 1222 if (interactive) {
lbajardsilogic@0 1223
lbajardsilogic@0 1224 ValueAvailability availability = UnknownAvailability;
lbajardsilogic@0 1225
lbajardsilogic@0 1226 for (Clipboard::PointList::const_iterator i = points.begin();
lbajardsilogic@0 1227 i != points.end(); ++i) {
lbajardsilogic@0 1228
lbajardsilogic@0 1229 if (!i->haveFrame()) continue;
lbajardsilogic@0 1230
lbajardsilogic@0 1231 if (availability == UnknownAvailability) {
lbajardsilogic@0 1232 if (i->haveValue()) availability = AllValues;
lbajardsilogic@0 1233 else availability = NoValues;
lbajardsilogic@0 1234 continue;
lbajardsilogic@0 1235 }
lbajardsilogic@0 1236
lbajardsilogic@0 1237 if (i->haveValue()) {
lbajardsilogic@0 1238 if (availability == NoValues) {
lbajardsilogic@0 1239 availability = SomeValues;
lbajardsilogic@0 1240 }
lbajardsilogic@0 1241 } else {
lbajardsilogic@0 1242 if (availability == AllValues) {
lbajardsilogic@0 1243 availability = SomeValues;
lbajardsilogic@0 1244 }
lbajardsilogic@0 1245 }
lbajardsilogic@0 1246
lbajardsilogic@0 1247 if (!haveUsableLabels) {
lbajardsilogic@0 1248 if (i->haveLabel()) {
lbajardsilogic@0 1249 if (i->getLabel().contains(QRegExp("[0-9]"))) {
lbajardsilogic@0 1250 haveUsableLabels = true;
lbajardsilogic@0 1251 }
lbajardsilogic@0 1252 }
lbajardsilogic@0 1253 }
lbajardsilogic@0 1254
lbajardsilogic@0 1255 if (availability == SomeValues && haveUsableLabels) break;
lbajardsilogic@0 1256 }
lbajardsilogic@0 1257
lbajardsilogic@0 1258 if (availability == NoValues || availability == SomeValues) {
lbajardsilogic@0 1259
lbajardsilogic@0 1260 QString text;
lbajardsilogic@0 1261 if (availability == NoValues) {
lbajardsilogic@0 1262 text = tr("The items you are pasting do not have values.\nWhat values do you want to use for these items?");
lbajardsilogic@0 1263 } else {
lbajardsilogic@0 1264 text = tr("Some of the items you are pasting do not have values.\nWhat values do you want to use for these items?");
lbajardsilogic@0 1265 }
lbajardsilogic@0 1266
lbajardsilogic@0 1267 QStringList options;
lbajardsilogic@0 1268 std::vector<int> genopts;
lbajardsilogic@0 1269
lbajardsilogic@0 1270 options << tr("Zero for all items");
lbajardsilogic@0 1271 genopts.push_back(int(GenerateNone));
lbajardsilogic@0 1272
lbajardsilogic@0 1273 options << tr("Whole numbers counting from 1");
lbajardsilogic@0 1274 genopts.push_back(int(GenerateFromCounter));
lbajardsilogic@0 1275
lbajardsilogic@0 1276 options << tr("Item's audio sample frame number");
lbajardsilogic@0 1277 genopts.push_back(int(GenerateFromFrameNumber));
lbajardsilogic@0 1278
lbajardsilogic@0 1279 options << tr("Item's time in seconds");
lbajardsilogic@0 1280 genopts.push_back(int(GenerateFromRealTime));
lbajardsilogic@0 1281
lbajardsilogic@0 1282 options << tr("Duration from the item to the following item");
lbajardsilogic@0 1283 genopts.push_back(int(GenerateFromRealTimeDifference));
lbajardsilogic@0 1284
lbajardsilogic@0 1285 options << tr("Tempo in bpm derived from the duration");
lbajardsilogic@0 1286 genopts.push_back(int(GenerateFromTempo));
lbajardsilogic@0 1287
lbajardsilogic@0 1288 if (haveExistingItems) {
lbajardsilogic@0 1289 options << tr("Value of the nearest existing item");
lbajardsilogic@0 1290 genopts.push_back(int(GenerateFromExistingNeighbour));
lbajardsilogic@0 1291 }
lbajardsilogic@0 1292
lbajardsilogic@0 1293 if (haveUsableLabels) {
lbajardsilogic@0 1294 options << tr("Value extracted from the item's label (where possible)");
lbajardsilogic@0 1295 genopts.push_back(int(GenerateFromLabels));
lbajardsilogic@0 1296 }
lbajardsilogic@0 1297
lbajardsilogic@0 1298
lbajardsilogic@0 1299 static int prevSelection = 0;
lbajardsilogic@0 1300
lbajardsilogic@0 1301 bool ok = false;
lbajardsilogic@0 1302 QString selected = ListInputDialog::getItem
lbajardsilogic@0 1303 (0, tr("Choose value calculation"),
lbajardsilogic@0 1304 text, options, prevSelection, &ok);
lbajardsilogic@0 1305
lbajardsilogic@0 1306 if (!ok) return false;
lbajardsilogic@0 1307 int selection = 0;
lbajardsilogic@0 1308 generation = GenerateNone;
lbajardsilogic@0 1309
lbajardsilogic@0 1310 for (QStringList::const_iterator i = options.begin();
lbajardsilogic@0 1311 i != options.end(); ++i) {
lbajardsilogic@0 1312 if (selected == *i) {
lbajardsilogic@0 1313 generation = ValueGeneration(genopts[selection]);
lbajardsilogic@0 1314 break;
lbajardsilogic@0 1315 }
lbajardsilogic@0 1316 ++selection;
lbajardsilogic@0 1317 }
lbajardsilogic@0 1318
lbajardsilogic@0 1319 prevSelection = selection;
lbajardsilogic@0 1320 }
lbajardsilogic@0 1321 }
lbajardsilogic@0 1322
lbajardsilogic@0 1323 int counter = 1;
lbajardsilogic@0 1324 float prevBpm = 120.f;
lbajardsilogic@0 1325
lbajardsilogic@0 1326 for (Clipboard::PointList::const_iterator i = points.begin();
lbajardsilogic@0 1327 i != points.end(); ++i) {
lbajardsilogic@0 1328
lbajardsilogic@0 1329 if (!i->haveFrame()) continue;
lbajardsilogic@0 1330 size_t frame = 0;
lbajardsilogic@0 1331 if (frameOffset > 0 || -frameOffset < i->getFrame()) {
lbajardsilogic@0 1332 frame = i->getFrame() + frameOffset;
lbajardsilogic@0 1333 }
lbajardsilogic@0 1334 SparseTimeValueModel::Point newPoint(frame);
lbajardsilogic@0 1335
lbajardsilogic@0 1336 if (i->haveLabel()) {
lbajardsilogic@0 1337 newPoint.label = i->getLabel();
lbajardsilogic@0 1338 } else if (i->haveValue()) {
lbajardsilogic@0 1339 newPoint.label = QString("%1").arg(i->getValue());
lbajardsilogic@0 1340 }
lbajardsilogic@0 1341
lbajardsilogic@0 1342 if (i->haveValue()) {
lbajardsilogic@0 1343 newPoint.value = i->getValue();
lbajardsilogic@0 1344 } else {
lbajardsilogic@0 1345
lbajardsilogic@0 1346 switch (generation) {
lbajardsilogic@0 1347
lbajardsilogic@0 1348 case GenerateNone:
lbajardsilogic@0 1349 newPoint.value = 0;
lbajardsilogic@0 1350 break;
lbajardsilogic@0 1351
lbajardsilogic@0 1352 case GenerateFromCounter:
lbajardsilogic@0 1353 newPoint.value = counter;
lbajardsilogic@0 1354 break;
lbajardsilogic@0 1355
lbajardsilogic@0 1356 case GenerateFromFrameNumber:
lbajardsilogic@0 1357 newPoint.value = frame;
lbajardsilogic@0 1358 break;
lbajardsilogic@0 1359
lbajardsilogic@0 1360 case GenerateFromRealTime:
lbajardsilogic@0 1361 newPoint.value = float(frame) / float(m_model->getSampleRate());
lbajardsilogic@0 1362 break;
lbajardsilogic@0 1363
lbajardsilogic@0 1364 case GenerateFromRealTimeDifference:
lbajardsilogic@0 1365 case GenerateFromTempo:
lbajardsilogic@0 1366 {
lbajardsilogic@0 1367 size_t nextFrame = frame;
lbajardsilogic@0 1368 Clipboard::PointList::const_iterator j = i;
lbajardsilogic@0 1369 for (; j != points.end(); ++j) {
lbajardsilogic@0 1370 if (!j->haveFrame()) continue;
lbajardsilogic@0 1371 if (j != i) break;
lbajardsilogic@0 1372 }
lbajardsilogic@0 1373 if (j != points.end()) {
lbajardsilogic@0 1374 nextFrame = j->getFrame();
lbajardsilogic@0 1375 }
lbajardsilogic@0 1376 if (generation == GenerateFromRealTimeDifference) {
lbajardsilogic@0 1377 newPoint.value = float(nextFrame - frame) /
lbajardsilogic@0 1378 float(m_model->getSampleRate());
lbajardsilogic@0 1379 } else {
lbajardsilogic@0 1380 float bpm = prevBpm;
lbajardsilogic@0 1381 if (nextFrame > frame) {
lbajardsilogic@0 1382 bpm = (60.f * m_model->getSampleRate()) /
lbajardsilogic@0 1383 (nextFrame - frame);
lbajardsilogic@0 1384 }
lbajardsilogic@0 1385 newPoint.value = bpm;
lbajardsilogic@0 1386 prevBpm = bpm;
lbajardsilogic@0 1387 }
lbajardsilogic@0 1388 break;
lbajardsilogic@0 1389 }
lbajardsilogic@0 1390
lbajardsilogic@0 1391 case GenerateFromExistingNeighbour:
lbajardsilogic@0 1392 {
lbajardsilogic@0 1393 SparseTimeValueModel::PointList points =
lbajardsilogic@0 1394 m_model->getPoints(frame);
lbajardsilogic@0 1395 if (points.empty()) points = m_model->getPreviousPoints(frame);
lbajardsilogic@0 1396 if (points.empty()) points = m_model->getNextPoints(frame);
lbajardsilogic@0 1397 if (points.empty()) {
lbajardsilogic@0 1398 newPoint.value = 0.f;
lbajardsilogic@0 1399 } else {
lbajardsilogic@0 1400 newPoint.value = points.begin()->value;
lbajardsilogic@0 1401 }
lbajardsilogic@0 1402 }
lbajardsilogic@0 1403
lbajardsilogic@0 1404 case GenerateFromLabels:
lbajardsilogic@0 1405 if (i->haveLabel()) {
lbajardsilogic@0 1406 // more forgiving than QString::toFloat()
lbajardsilogic@0 1407 newPoint.value = atof(i->getLabel().toLocal8Bit());
lbajardsilogic@0 1408 } else {
lbajardsilogic@0 1409 newPoint.value = 0.f;
lbajardsilogic@0 1410 }
lbajardsilogic@0 1411 }
lbajardsilogic@0 1412 }
lbajardsilogic@0 1413
lbajardsilogic@0 1414 command->addPoint(newPoint);
lbajardsilogic@0 1415
lbajardsilogic@0 1416 ++counter;
lbajardsilogic@0 1417 }
lbajardsilogic@0 1418
lbajardsilogic@0 1419 command->finish();
lbajardsilogic@0 1420 return true;
lbajardsilogic@0 1421 }
lbajardsilogic@0 1422
lbajardsilogic@0 1423 QString
lbajardsilogic@0 1424 TimeValueLayer::toXmlString(QString indent, QString extraAttributes) const
lbajardsilogic@0 1425 {
lbajardsilogic@0 1426 return Layer::toXmlString(indent, extraAttributes +
lbajardsilogic@0 1427 QString(" colour=\"%1\" plotStyle=\"%2\"")
lbajardsilogic@0 1428 .arg(encodeColour(m_colour)).arg(m_plotStyle));
lbajardsilogic@0 1429 }
lbajardsilogic@0 1430
lbajardsilogic@18 1431 QString
lbajardsilogic@18 1432 TimeValueLayer::toEasaierXmlString(QString indent, QString extraAttributes) const
lbajardsilogic@18 1433 {
lbajardsilogic@18 1434 return Layer::toEasaierXmlString(indent, extraAttributes +
lbajardsilogic@18 1435 QString(" colour=\"%1\" plotStyle=\"%2\"")
lbajardsilogic@18 1436 .arg(encodeColour(m_colour)).arg(m_plotStyle));
lbajardsilogic@18 1437 }
lbajardsilogic@18 1438
lbajardsilogic@0 1439 void
lbajardsilogic@0 1440 TimeValueLayer::setProperties(const QXmlAttributes &attributes)
lbajardsilogic@0 1441 {
lbajardsilogic@0 1442 QString colourSpec = attributes.value("colour");
lbajardsilogic@0 1443 if (colourSpec != "") {
lbajardsilogic@0 1444 QColor colour(colourSpec);
lbajardsilogic@0 1445 if (colour.isValid()) {
lbajardsilogic@0 1446 setBaseColour(QColor(colourSpec));
lbajardsilogic@0 1447 }
lbajardsilogic@0 1448 }
lbajardsilogic@0 1449
lbajardsilogic@0 1450 bool ok;
lbajardsilogic@0 1451 PlotStyle style = (PlotStyle)
lbajardsilogic@0 1452 attributes.value("plotStyle").toInt(&ok);
lbajardsilogic@0 1453 if (ok) setPlotStyle(style);
lbajardsilogic@0 1454 }
lbajardsilogic@0 1455