annotate layer/TimeInstantLayer.cpp @ 282:d9319859a4cf tip

(none)
author benoitrigolleau
date Fri, 31 Oct 2008 11:00:24 +0000
parents aa81e87c8089
children
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 "TimeInstantLayer.h"
lbajardsilogic@0 17
lbajardsilogic@0 18 #include "data/model/Model.h"
lbajardsilogic@0 19 #include "base/RealTime.h"
lbajardsilogic@0 20 #include "view/View.h"
lbajardsilogic@0 21 #include "base/Profiler.h"
lbajardsilogic@0 22 #include "base/Clipboard.h"
lbajardsilogic@0 23
lbajardsilogic@0 24 #include "data/model/SparseOneDimensionalModel.h"
lbajardsilogic@0 25
lbajardsilogic@0 26 #include "widgets/ItemEditDialog.h"
lbajardsilogic@0 27
lbajardsilogic@0 28 #include <QPainter>
lbajardsilogic@0 29 #include <QMouseEvent>
lbajardsilogic@0 30
lbajardsilogic@0 31 #include <iostream>
lbajardsilogic@0 32 #include <cmath>
lbajardsilogic@0 33
lbajardsilogic@0 34 TimeInstantLayer::TimeInstantLayer() :
lbajardsilogic@0 35 Layer(),
lbajardsilogic@0 36 m_model(0),
lbajardsilogic@0 37 m_editing(false),
lbajardsilogic@0 38 m_editingPoint(0, tr("New Point")),
lbajardsilogic@0 39 m_editingCommand(0),
lbajardsilogic@0 40 m_colour(QColor(200, 50, 255)),
lbajardsilogic@0 41 m_plotStyle(PlotInstants)
lbajardsilogic@0 42 {
lbajardsilogic@0 43
lbajardsilogic@0 44 }
lbajardsilogic@0 45
lbajardsilogic@0 46 void
lbajardsilogic@0 47 TimeInstantLayer::setModel(SparseOneDimensionalModel *model)
lbajardsilogic@0 48 {
lbajardsilogic@0 49 if (m_model == model) return;
lbajardsilogic@0 50 m_model = model;
lbajardsilogic@0 51
lbajardsilogic@0 52 connect(m_model, SIGNAL(modelChanged()), this, SIGNAL(modelChanged()));
lbajardsilogic@0 53 connect(m_model, SIGNAL(modelChanged(size_t, size_t)),
lbajardsilogic@0 54 this, SIGNAL(modelChanged(size_t, size_t)));
lbajardsilogic@0 55
lbajardsilogic@0 56 connect(m_model, SIGNAL(completionChanged()),
lbajardsilogic@0 57 this, SIGNAL(modelCompletionChanged()));
lbajardsilogic@0 58
lbajardsilogic@0 59 std::cerr << "TimeInstantLayer::setModel(" << model << ")" << std::endl;
lbajardsilogic@0 60
lbajardsilogic@0 61 emit modelReplaced();
lbajardsilogic@0 62 }
lbajardsilogic@0 63
lbajardsilogic@0 64 Layer::PropertyList
lbajardsilogic@0 65 TimeInstantLayer::getProperties() const
lbajardsilogic@0 66 {
lbajardsilogic@0 67 PropertyList list;
lbajardsilogic@0 68 list.push_back("Colour");
lbajardsilogic@0 69 list.push_back("Plot Type");
lbajardsilogic@0 70 return list;
lbajardsilogic@0 71 }
lbajardsilogic@0 72
lbajardsilogic@0 73 QString
lbajardsilogic@0 74 TimeInstantLayer::getPropertyLabel(const PropertyName &name) const
lbajardsilogic@0 75 {
lbajardsilogic@0 76 if (name == "Colour") return tr("Colour");
lbajardsilogic@0 77 if (name == "Plot Type") return tr("Plot Type");
lbajardsilogic@0 78 return "";
lbajardsilogic@0 79 }
lbajardsilogic@0 80
lbajardsilogic@0 81 Layer::PropertyType
lbajardsilogic@0 82 TimeInstantLayer::getPropertyType(const PropertyName &) const
lbajardsilogic@0 83 {
lbajardsilogic@0 84 return ValueProperty;
lbajardsilogic@0 85 }
lbajardsilogic@0 86
lbajardsilogic@0 87 int
lbajardsilogic@0 88 TimeInstantLayer::getPropertyRangeAndValue(const PropertyName &name,
lbajardsilogic@0 89 int *min, int *max, int *deflt) const
lbajardsilogic@0 90 {
lbajardsilogic@0 91 int val = 0;
lbajardsilogic@0 92
lbajardsilogic@0 93 if (name == "Colour") {
lbajardsilogic@0 94
lbajardsilogic@0 95 if (min) *min = 0;
lbajardsilogic@0 96 if (max) *max = 5;
lbajardsilogic@0 97 if (deflt) *deflt = 0;
lbajardsilogic@0 98
lbajardsilogic@0 99 if (m_colour == Qt::black) val = 0;
lbajardsilogic@0 100 else if (m_colour == Qt::darkRed) val = 1;
lbajardsilogic@0 101 else if (m_colour == Qt::darkBlue) val = 2;
lbajardsilogic@0 102 else if (m_colour == Qt::darkGreen) val = 3;
lbajardsilogic@0 103 else if (m_colour == QColor(200, 50, 255)) val = 4;
lbajardsilogic@0 104 else if (m_colour == QColor(255, 150, 50)) val = 5;
lbajardsilogic@0 105
lbajardsilogic@0 106 } else if (name == "Plot Type") {
lbajardsilogic@0 107
lbajardsilogic@0 108 if (min) *min = 0;
lbajardsilogic@0 109 if (max) *max = 1;
lbajardsilogic@0 110 if (deflt) *deflt = 0;
lbajardsilogic@0 111
lbajardsilogic@0 112 val = int(m_plotStyle);
lbajardsilogic@0 113
lbajardsilogic@0 114 } else {
lbajardsilogic@0 115
lbajardsilogic@0 116 val = Layer::getPropertyRangeAndValue(name, min, max, deflt);
lbajardsilogic@0 117 }
lbajardsilogic@0 118
lbajardsilogic@0 119 return val;
lbajardsilogic@0 120 }
lbajardsilogic@0 121
lbajardsilogic@0 122 QString
lbajardsilogic@0 123 TimeInstantLayer::getPropertyValueLabel(const PropertyName &name,
lbajardsilogic@0 124 int value) const
lbajardsilogic@0 125 {
lbajardsilogic@0 126 if (name == "Colour") {
lbajardsilogic@0 127 switch (value) {
lbajardsilogic@0 128 default:
lbajardsilogic@0 129 case 0: return tr("Black");
lbajardsilogic@0 130 case 1: return tr("Red");
lbajardsilogic@0 131 case 2: return tr("Blue");
lbajardsilogic@0 132 case 3: return tr("Green");
lbajardsilogic@0 133 case 4: return tr("Purple");
lbajardsilogic@0 134 case 5: return tr("Orange");
lbajardsilogic@0 135 }
lbajardsilogic@0 136 } else if (name == "Plot Type") {
lbajardsilogic@0 137 switch (value) {
lbajardsilogic@0 138 default:
lbajardsilogic@0 139 case 0: return tr("Instants");
lbajardsilogic@0 140 case 1: return tr("Segmentation");
lbajardsilogic@0 141 }
lbajardsilogic@0 142 }
lbajardsilogic@0 143 return tr("<unknown>");
lbajardsilogic@0 144 }
lbajardsilogic@0 145
lbajardsilogic@0 146 void
lbajardsilogic@0 147 TimeInstantLayer::setProperty(const PropertyName &name, int value)
lbajardsilogic@0 148 {
lbajardsilogic@0 149 if (name == "Colour") {
lbajardsilogic@0 150 switch (value) {
lbajardsilogic@0 151 default:
lbajardsilogic@0 152 case 0: setBaseColour(Qt::black); break;
lbajardsilogic@0 153 case 1: setBaseColour(Qt::darkRed); break;
lbajardsilogic@0 154 case 2: setBaseColour(Qt::darkBlue); break;
lbajardsilogic@0 155 case 3: setBaseColour(Qt::darkGreen); break;
lbajardsilogic@0 156 case 4: setBaseColour(QColor(200, 50, 255)); break;
lbajardsilogic@0 157 case 5: setBaseColour(QColor(255, 150, 50)); break;
lbajardsilogic@0 158 }
lbajardsilogic@0 159 } else if (name == "Plot Type") {
lbajardsilogic@0 160 setPlotStyle(PlotStyle(value));
lbajardsilogic@0 161 }
lbajardsilogic@0 162 }
lbajardsilogic@0 163
lbajardsilogic@0 164 void
lbajardsilogic@0 165 TimeInstantLayer::setBaseColour(QColor colour)
lbajardsilogic@0 166 {
lbajardsilogic@0 167 if (m_colour == colour) return;
lbajardsilogic@0 168 m_colour = colour;
lbajardsilogic@0 169 emit layerParametersChanged();
lbajardsilogic@0 170 }
lbajardsilogic@0 171
lbajardsilogic@0 172 void
lbajardsilogic@0 173 TimeInstantLayer::setPlotStyle(PlotStyle style)
lbajardsilogic@0 174 {
lbajardsilogic@0 175 if (m_plotStyle == style) return;
lbajardsilogic@0 176 m_plotStyle = style;
lbajardsilogic@0 177 emit layerParametersChanged();
lbajardsilogic@0 178 }
lbajardsilogic@0 179
lbajardsilogic@0 180 bool
lbajardsilogic@0 181 TimeInstantLayer::isLayerScrollable(const View *v) const
lbajardsilogic@0 182 {
lbajardsilogic@0 183 QPoint discard;
lbajardsilogic@0 184 return !v->shouldIlluminateLocalFeatures(this, discard);
lbajardsilogic@0 185 }
lbajardsilogic@0 186
lbajardsilogic@0 187 SparseOneDimensionalModel::PointList
lbajardsilogic@0 188 TimeInstantLayer::getLocalPoints(View *v, int x) const
lbajardsilogic@0 189 {
lbajardsilogic@0 190 // Return a set of points that all have the same frame number, the
lbajardsilogic@0 191 // nearest to the given x coordinate, and that are within a
lbajardsilogic@0 192 // certain fuzz distance of that x coordinate.
lbajardsilogic@0 193
lbajardsilogic@0 194 if (!m_model) return SparseOneDimensionalModel::PointList();
lbajardsilogic@0 195
lbajardsilogic@0 196 long frame = v->getFrameForX(x);
lbajardsilogic@0 197
lbajardsilogic@0 198 SparseOneDimensionalModel::PointList onPoints =
lbajardsilogic@0 199 m_model->getPoints(frame);
lbajardsilogic@0 200
lbajardsilogic@0 201 if (!onPoints.empty()) {
lbajardsilogic@0 202 return onPoints;
lbajardsilogic@0 203 }
lbajardsilogic@0 204
lbajardsilogic@0 205 SparseOneDimensionalModel::PointList prevPoints =
lbajardsilogic@0 206 m_model->getPreviousPoints(frame);
lbajardsilogic@0 207 SparseOneDimensionalModel::PointList nextPoints =
lbajardsilogic@0 208 m_model->getNextPoints(frame);
lbajardsilogic@0 209
lbajardsilogic@0 210 SparseOneDimensionalModel::PointList usePoints = prevPoints;
lbajardsilogic@0 211
lbajardsilogic@34 212 if (! nextPoints.empty())
lbajardsilogic@34 213 {
lbajardsilogic@34 214 if (prevPoints.empty()) {
lbajardsilogic@34 215 usePoints = nextPoints;
lbajardsilogic@34 216 } else if (long(prevPoints.begin()->frame) < v->getStartFrame() &&
lbajardsilogic@34 217 !(nextPoints.begin()->frame > v->getEndFrame())) {
lbajardsilogic@34 218 usePoints = nextPoints;
lbajardsilogic@34 219 } else if (nextPoints.begin()->frame - frame <
lbajardsilogic@34 220 frame - prevPoints.begin()->frame) {
lbajardsilogic@34 221 usePoints = nextPoints;
lbajardsilogic@34 222 }
lbajardsilogic@34 223 }
lbajardsilogic@0 224
lbajardsilogic@0 225 if (!usePoints.empty()) {
lbajardsilogic@0 226 int fuzz = 2;
lbajardsilogic@0 227 int px = v->getXForFrame(usePoints.begin()->frame);
lbajardsilogic@0 228 if ((px > x && px - x > fuzz) ||
lbajardsilogic@0 229 (px < x && x - px > fuzz + 1)) {
lbajardsilogic@0 230 usePoints.clear();
lbajardsilogic@0 231 }
lbajardsilogic@0 232 }
lbajardsilogic@0 233
lbajardsilogic@0 234 return usePoints;
lbajardsilogic@0 235 }
lbajardsilogic@0 236
lbajardsilogic@0 237 QString
lbajardsilogic@0 238 TimeInstantLayer::getFeatureDescription(View *v, QPoint &pos) const
lbajardsilogic@0 239 {
lbajardsilogic@0 240 int x = pos.x();
lbajardsilogic@0 241
lbajardsilogic@0 242 if (!m_model || !m_model->getSampleRate()) return "";
lbajardsilogic@0 243
lbajardsilogic@0 244 SparseOneDimensionalModel::PointList points = getLocalPoints(v, x);
lbajardsilogic@0 245
lbajardsilogic@0 246 if (points.empty()) {
lbajardsilogic@0 247 if (!m_model->isReady()) {
lbajardsilogic@0 248 return tr("In progress");
lbajardsilogic@0 249 } else {
lbajardsilogic@0 250 return tr("No local points");
lbajardsilogic@0 251 }
lbajardsilogic@0 252 }
lbajardsilogic@0 253
lbajardsilogic@0 254 long useFrame = points.begin()->frame;
lbajardsilogic@0 255
lbajardsilogic@0 256 RealTime rt = RealTime::frame2RealTime(useFrame, m_model->getSampleRate());
lbajardsilogic@0 257
lbajardsilogic@0 258 QString text;
lbajardsilogic@0 259
lbajardsilogic@0 260 if (points.begin()->label == "") {
lbajardsilogic@0 261 text = QString(tr("Time:\t%1\nNo label"))
lbajardsilogic@0 262 .arg(rt.toText(true).c_str());
lbajardsilogic@0 263 } else {
lbajardsilogic@0 264 text = QString(tr("Time:\t%1\nLabel:\t%2"))
lbajardsilogic@0 265 .arg(rt.toText(true).c_str())
lbajardsilogic@0 266 .arg(points.begin()->label);
lbajardsilogic@0 267 }
lbajardsilogic@0 268
lbajardsilogic@0 269 pos = QPoint(v->getXForFrame(useFrame), pos.y());
lbajardsilogic@0 270 return text;
lbajardsilogic@0 271 }
lbajardsilogic@0 272
lbajardsilogic@0 273 bool
lbajardsilogic@0 274 TimeInstantLayer::snapToFeatureFrame(View *v, int &frame,
lbajardsilogic@0 275 size_t &resolution,
lbajardsilogic@0 276 SnapType snap) const
lbajardsilogic@0 277 {
lbajardsilogic@0 278 if (!m_model) {
lbajardsilogic@0 279 return Layer::snapToFeatureFrame(v, frame, resolution, snap);
lbajardsilogic@0 280 }
lbajardsilogic@0 281
lbajardsilogic@0 282 resolution = m_model->getResolution();
lbajardsilogic@0 283 SparseOneDimensionalModel::PointList points;
lbajardsilogic@0 284
lbajardsilogic@0 285 if (snap == SnapNeighbouring) {
lbajardsilogic@0 286
lbajardsilogic@0 287 points = getLocalPoints(v, v->getXForFrame(frame));
lbajardsilogic@0 288 if (points.empty()) return false;
lbajardsilogic@0 289 frame = points.begin()->frame;
lbajardsilogic@0 290 return true;
lbajardsilogic@0 291 }
lbajardsilogic@0 292
lbajardsilogic@0 293 points = m_model->getPoints(frame, frame);
lbajardsilogic@0 294 int snapped = frame;
lbajardsilogic@0 295 bool found = false;
lbajardsilogic@0 296
lbajardsilogic@0 297 for (SparseOneDimensionalModel::PointList::const_iterator i = points.begin();
lbajardsilogic@0 298 i != points.end(); ++i) {
lbajardsilogic@0 299
lbajardsilogic@0 300 if (snap == SnapRight) {
lbajardsilogic@0 301
lbajardsilogic@0 302 if (i->frame >= frame) {
lbajardsilogic@0 303 snapped = i->frame;
lbajardsilogic@0 304 found = true;
lbajardsilogic@0 305 break;
lbajardsilogic@0 306 }
lbajardsilogic@0 307
lbajardsilogic@0 308 } else if (snap == SnapLeft) {
lbajardsilogic@0 309
lbajardsilogic@0 310 if (i->frame <= frame) {
lbajardsilogic@0 311 snapped = i->frame;
lbajardsilogic@0 312 found = true; // don't break, as the next may be better
lbajardsilogic@0 313 } else {
lbajardsilogic@0 314 break;
lbajardsilogic@0 315 }
lbajardsilogic@0 316
lbajardsilogic@0 317 } else { // nearest
lbajardsilogic@0 318
lbajardsilogic@0 319 SparseOneDimensionalModel::PointList::const_iterator j = i;
lbajardsilogic@0 320 ++j;
lbajardsilogic@0 321
lbajardsilogic@0 322 if (j == points.end()) {
lbajardsilogic@0 323
lbajardsilogic@0 324 snapped = i->frame;
lbajardsilogic@0 325 found = true;
lbajardsilogic@0 326 break;
lbajardsilogic@0 327
lbajardsilogic@0 328 } else if (j->frame >= frame) {
lbajardsilogic@0 329
lbajardsilogic@0 330 if (j->frame - frame < frame - i->frame) {
lbajardsilogic@0 331 snapped = j->frame;
lbajardsilogic@0 332 } else {
lbajardsilogic@0 333 snapped = i->frame;
lbajardsilogic@0 334 }
lbajardsilogic@0 335 found = true;
lbajardsilogic@0 336 break;
lbajardsilogic@0 337 }
lbajardsilogic@0 338 }
lbajardsilogic@0 339 }
lbajardsilogic@0 340
lbajardsilogic@0 341 frame = snapped;
lbajardsilogic@0 342 return found;
lbajardsilogic@0 343 }
lbajardsilogic@0 344
lbajardsilogic@0 345 void
lbajardsilogic@0 346 TimeInstantLayer::paint(View *v, QPainter &paint, QRect rect) const
lbajardsilogic@0 347 {
lbajardsilogic@0 348 if (!m_model || !m_model->isOK()) return;
lbajardsilogic@0 349
lbajardsilogic@0 350 // Profiler profiler("TimeInstantLayer::paint", true);
lbajardsilogic@0 351
lbajardsilogic@0 352 int x0 = rect.left(), x1 = rect.right();
lbajardsilogic@0 353
lbajardsilogic@0 354 long frame0 = v->getFrameForX(x0);
lbajardsilogic@0 355 long frame1 = v->getFrameForX(x1);
lbajardsilogic@0 356
lbajardsilogic@0 357 SparseOneDimensionalModel::PointList points(m_model->getPoints
lbajardsilogic@0 358 (frame0, frame1));
lbajardsilogic@0 359
lbajardsilogic@0 360 bool odd = false;
lbajardsilogic@0 361 if (m_plotStyle == PlotSegmentation && !points.empty()) {
lbajardsilogic@0 362 int index = m_model->getIndexOf(*points.begin());
lbajardsilogic@0 363 odd = ((index % 2) == 1);
lbajardsilogic@0 364 }
lbajardsilogic@0 365
lbajardsilogic@0 366 paint.setPen(m_colour);
lbajardsilogic@0 367
lbajardsilogic@0 368 QColor brushColour(m_colour);
lbajardsilogic@0 369 brushColour.setAlpha(100);
lbajardsilogic@0 370 paint.setBrush(brushColour);
lbajardsilogic@0 371
lbajardsilogic@0 372 QColor oddBrushColour(brushColour);
lbajardsilogic@0 373 if (m_plotStyle == PlotSegmentation) {
lbajardsilogic@0 374 if (m_colour == Qt::black) {
lbajardsilogic@0 375 oddBrushColour = Qt::gray;
lbajardsilogic@0 376 } else if (m_colour == Qt::darkRed) {
lbajardsilogic@0 377 oddBrushColour = Qt::red;
lbajardsilogic@0 378 } else if (m_colour == Qt::darkBlue) {
lbajardsilogic@0 379 oddBrushColour = Qt::blue;
lbajardsilogic@0 380 } else if (m_colour == Qt::darkGreen) {
lbajardsilogic@0 381 oddBrushColour = Qt::green;
lbajardsilogic@0 382 } else {
lbajardsilogic@0 383 oddBrushColour = oddBrushColour.light(150);
lbajardsilogic@0 384 }
lbajardsilogic@0 385 oddBrushColour.setAlpha(100);
lbajardsilogic@0 386 }
lbajardsilogic@0 387
lbajardsilogic@0 388 // std::cerr << "TimeInstantLayer::paint: resolution is "
lbajardsilogic@0 389 // << m_model->getResolution() << " frames" << std::endl;
lbajardsilogic@0 390
lbajardsilogic@0 391 QPoint localPos;
lbajardsilogic@0 392 long illuminateFrame = -1;
lbajardsilogic@0 393
lbajardsilogic@0 394 if (v->shouldIlluminateLocalFeatures(this, localPos)) {
lbajardsilogic@0 395 SparseOneDimensionalModel::PointList localPoints =
lbajardsilogic@0 396 getLocalPoints(v, localPos.x());
lbajardsilogic@0 397 if (!localPoints.empty()) illuminateFrame = localPoints.begin()->frame;
lbajardsilogic@0 398 }
lbajardsilogic@0 399
lbajardsilogic@0 400 int prevX = -1;
lbajardsilogic@0 401 int textY = v->getTextLabelHeight(this, paint);
lbajardsilogic@0 402
lbajardsilogic@0 403 for (SparseOneDimensionalModel::PointList::const_iterator i = points.begin();
lbajardsilogic@0 404 i != points.end(); ++i) {
lbajardsilogic@0 405
lbajardsilogic@0 406 const SparseOneDimensionalModel::Point &p(*i);
lbajardsilogic@0 407 SparseOneDimensionalModel::PointList::const_iterator j = i;
lbajardsilogic@0 408 ++j;
lbajardsilogic@0 409
lbajardsilogic@0 410 int x = v->getXForFrame(p.frame);
lbajardsilogic@0 411 if (x == prevX && p.frame != illuminateFrame) continue;
lbajardsilogic@0 412
lbajardsilogic@0 413 int iw = v->getXForFrame(p.frame + m_model->getResolution()) - x;
lbajardsilogic@0 414 if (iw < 2) {
lbajardsilogic@0 415 if (iw < 1) {
lbajardsilogic@0 416 iw = 2;
lbajardsilogic@0 417 if (j != points.end()) {
lbajardsilogic@0 418 int nx = v->getXForFrame(j->frame);
lbajardsilogic@0 419 if (nx < x + 3) iw = 1;
lbajardsilogic@0 420 }
lbajardsilogic@0 421 } else {
lbajardsilogic@0 422 iw = 2;
lbajardsilogic@0 423 }
lbajardsilogic@0 424 }
lbajardsilogic@0 425
lbajardsilogic@0 426 if (p.frame == illuminateFrame) {
lbajardsilogic@0 427 paint.setPen(Qt::black); //!!!
lbajardsilogic@0 428 } else {
lbajardsilogic@0 429 paint.setPen(brushColour);
lbajardsilogic@0 430 }
lbajardsilogic@0 431
lbajardsilogic@0 432 if (m_plotStyle == PlotInstants) {
lbajardsilogic@0 433 if (iw > 1) {
lbajardsilogic@0 434 paint.drawRect(x, 0, iw - 1, v->height() - 1);
lbajardsilogic@0 435 } else {
lbajardsilogic@0 436 paint.drawLine(x, 0, x, v->height() - 1);
lbajardsilogic@0 437 }
lbajardsilogic@0 438 } else {
lbajardsilogic@0 439
lbajardsilogic@0 440 if (odd) paint.setBrush(oddBrushColour);
lbajardsilogic@0 441 else paint.setBrush(brushColour);
lbajardsilogic@0 442
lbajardsilogic@0 443 int nx;
lbajardsilogic@0 444
lbajardsilogic@0 445 if (j != points.end()) {
lbajardsilogic@0 446 const SparseOneDimensionalModel::Point &q(*j);
lbajardsilogic@0 447 nx = v->getXForFrame(q.frame);
lbajardsilogic@0 448 } else {
lbajardsilogic@0 449 nx = v->getXForFrame(m_model->getEndFrame());
lbajardsilogic@0 450 }
lbajardsilogic@0 451
lbajardsilogic@0 452 if (nx >= x) {
lbajardsilogic@0 453
lbajardsilogic@0 454 if (illuminateFrame != p.frame &&
lbajardsilogic@0 455 (nx < x + 5 || x >= v->width() - 1)) {
lbajardsilogic@0 456 paint.setPen(Qt::NoPen);
lbajardsilogic@0 457 }
lbajardsilogic@0 458
lbajardsilogic@0 459 paint.drawRect(x, -1, nx - x, v->height() + 1);
lbajardsilogic@0 460 }
lbajardsilogic@0 461
lbajardsilogic@0 462 odd = !odd;
lbajardsilogic@0 463 }
lbajardsilogic@0 464
lbajardsilogic@0 465 paint.setPen(m_colour);
lbajardsilogic@0 466
lbajardsilogic@0 467 if (p.label != "") {
lbajardsilogic@0 468
lbajardsilogic@0 469 // only draw if there's enough room from here to the next point
lbajardsilogic@0 470
lbajardsilogic@0 471 int lw = paint.fontMetrics().width(p.label);
lbajardsilogic@0 472 bool good = true;
lbajardsilogic@0 473
lbajardsilogic@0 474 if (j != points.end()) {
lbajardsilogic@0 475 int nx = v->getXForFrame(j->frame);
lbajardsilogic@0 476 if (nx >= x && nx - x - iw - 3 <= lw) good = false;
lbajardsilogic@0 477 }
lbajardsilogic@0 478
lbajardsilogic@0 479 if (good) {
lbajardsilogic@0 480 paint.drawText(x + iw + 2, textY, p.label);
lbajardsilogic@0 481 }
lbajardsilogic@0 482 }
lbajardsilogic@0 483
lbajardsilogic@0 484 prevX = x;
lbajardsilogic@0 485 }
lbajardsilogic@0 486 }
lbajardsilogic@0 487
lbajardsilogic@0 488 void
lbajardsilogic@0 489 TimeInstantLayer::drawStart(View *v, QMouseEvent *e)
lbajardsilogic@0 490 {
lbajardsilogic@0 491 std::cerr << "TimeInstantLayer::drawStart(" << e->x() << ")" << std::endl;
lbajardsilogic@0 492
lbajardsilogic@0 493 if (!m_model) return;
lbajardsilogic@0 494
lbajardsilogic@0 495 long frame = v->getFrameForX(e->x());
lbajardsilogic@0 496 if (frame < 0) frame = 0;
lbajardsilogic@0 497 frame = frame / m_model->getResolution() * m_model->getResolution();
lbajardsilogic@0 498
lbajardsilogic@0 499 m_editingPoint = SparseOneDimensionalModel::Point(frame, tr("New Point"));
lbajardsilogic@0 500
lbajardsilogic@0 501 if (m_editingCommand) m_editingCommand->finish();
lbajardsilogic@0 502 m_editingCommand = new SparseOneDimensionalModel::EditCommand(m_model,
lbajardsilogic@0 503 tr("Draw Point"));
lbajardsilogic@0 504 m_editingCommand->addPoint(m_editingPoint);
lbajardsilogic@0 505
lbajardsilogic@0 506 m_editing = true;
lbajardsilogic@0 507 }
lbajardsilogic@0 508
lbajardsilogic@0 509 void
lbajardsilogic@0 510 TimeInstantLayer::drawDrag(View *v, QMouseEvent *e)
lbajardsilogic@0 511 {
lbajardsilogic@0 512 std::cerr << "TimeInstantLayer::drawDrag(" << e->x() << ")" << std::endl;
lbajardsilogic@0 513
lbajardsilogic@0 514 if (!m_model || !m_editing) return;
lbajardsilogic@0 515
lbajardsilogic@0 516 long frame = v->getFrameForX(e->x());
lbajardsilogic@0 517 if (frame < 0) frame = 0;
lbajardsilogic@0 518 frame = frame / m_model->getResolution() * m_model->getResolution();
lbajardsilogic@0 519 m_editingCommand->deletePoint(m_editingPoint);
lbajardsilogic@0 520 m_editingPoint.frame = frame;
lbajardsilogic@0 521 m_editingCommand->addPoint(m_editingPoint);
lbajardsilogic@0 522 }
lbajardsilogic@0 523
lbajardsilogic@0 524 void
lbajardsilogic@0 525 TimeInstantLayer::drawEnd(View *, QMouseEvent *e)
lbajardsilogic@0 526 {
lbajardsilogic@0 527 std::cerr << "TimeInstantLayer::drawEnd(" << e->x() << ")" << std::endl;
lbajardsilogic@0 528 if (!m_model || !m_editing) return;
lbajardsilogic@0 529 QString newName = tr("Add Point at %1 s")
lbajardsilogic@0 530 .arg(RealTime::frame2RealTime(m_editingPoint.frame,
lbajardsilogic@0 531 m_model->getSampleRate())
lbajardsilogic@0 532 .toText(false).c_str());
lbajardsilogic@0 533 m_editingCommand->setName(newName);
lbajardsilogic@0 534 m_editingCommand->finish();
lbajardsilogic@0 535 m_editingCommand = 0;
lbajardsilogic@0 536 m_editing = false;
lbajardsilogic@0 537 }
lbajardsilogic@0 538
lbajardsilogic@0 539 void
lbajardsilogic@0 540 TimeInstantLayer::editStart(View *v, QMouseEvent *e)
lbajardsilogic@0 541 {
lbajardsilogic@0 542 std::cerr << "TimeInstantLayer::editStart(" << e->x() << ")" << std::endl;
lbajardsilogic@0 543
lbajardsilogic@0 544 if (!m_model) return;
lbajardsilogic@0 545
lbajardsilogic@0 546 SparseOneDimensionalModel::PointList points = getLocalPoints(v, e->x());
lbajardsilogic@0 547 if (points.empty()) return;
lbajardsilogic@0 548
lbajardsilogic@0 549 m_editingPoint = *points.begin();
lbajardsilogic@0 550
lbajardsilogic@0 551 if (m_editingCommand) {
lbajardsilogic@0 552 m_editingCommand->finish();
lbajardsilogic@0 553 m_editingCommand = 0;
lbajardsilogic@0 554 }
lbajardsilogic@0 555
lbajardsilogic@0 556 m_editing = true;
lbajardsilogic@0 557 }
lbajardsilogic@0 558
lbajardsilogic@0 559 void
lbajardsilogic@0 560 TimeInstantLayer::editDrag(View *v, QMouseEvent *e)
lbajardsilogic@0 561 {
lbajardsilogic@0 562 std::cerr << "TimeInstantLayer::editDrag(" << e->x() << ")" << std::endl;
lbajardsilogic@0 563
lbajardsilogic@0 564 if (!m_model || !m_editing) return;
lbajardsilogic@0 565
lbajardsilogic@0 566 long frame = v->getFrameForX(e->x());
lbajardsilogic@0 567 if (frame < 0) frame = 0;
lbajardsilogic@0 568 frame = frame / m_model->getResolution() * m_model->getResolution();
lbajardsilogic@0 569
lbajardsilogic@0 570 if (!m_editingCommand) {
lbajardsilogic@0 571 m_editingCommand = new SparseOneDimensionalModel::EditCommand(m_model,
lbajardsilogic@0 572 tr("Drag Point"));
lbajardsilogic@0 573 }
lbajardsilogic@0 574
lbajardsilogic@0 575 m_editingCommand->deletePoint(m_editingPoint);
lbajardsilogic@0 576 m_editingPoint.frame = frame;
lbajardsilogic@0 577 m_editingCommand->addPoint(m_editingPoint);
lbajardsilogic@0 578 }
lbajardsilogic@0 579
lbajardsilogic@0 580 void
lbajardsilogic@0 581 TimeInstantLayer::editEnd(View *, QMouseEvent *e)
lbajardsilogic@0 582 {
lbajardsilogic@0 583 std::cerr << "TimeInstantLayer::editEnd(" << e->x() << ")" << std::endl;
lbajardsilogic@0 584 if (!m_model || !m_editing) return;
lbajardsilogic@0 585 if (m_editingCommand) {
lbajardsilogic@0 586 QString newName = tr("Move Point to %1 s")
lbajardsilogic@0 587 .arg(RealTime::frame2RealTime(m_editingPoint.frame,
lbajardsilogic@0 588 m_model->getSampleRate())
lbajardsilogic@0 589 .toText(false).c_str());
lbajardsilogic@0 590 m_editingCommand->setName(newName);
lbajardsilogic@0 591 m_editingCommand->finish();
lbajardsilogic@0 592 }
lbajardsilogic@0 593 m_editingCommand = 0;
lbajardsilogic@0 594 m_editing = false;
lbajardsilogic@0 595 }
lbajardsilogic@0 596
lbajardsilogic@0 597 void
lbajardsilogic@0 598 TimeInstantLayer::editOpen(View *v, QMouseEvent *e)
lbajardsilogic@0 599 {
lbajardsilogic@0 600 if (!m_model) return;
lbajardsilogic@0 601
lbajardsilogic@0 602 SparseOneDimensionalModel::PointList points = getLocalPoints(v, e->x());
lbajardsilogic@0 603 if (points.empty()) return;
lbajardsilogic@0 604
lbajardsilogic@0 605 SparseOneDimensionalModel::Point point = *points.begin();
lbajardsilogic@0 606
lbajardsilogic@0 607 ItemEditDialog *dialog = new ItemEditDialog
lbajardsilogic@0 608 (m_model->getSampleRate(),
lbajardsilogic@0 609 ItemEditDialog::ShowTime |
lbajardsilogic@0 610 ItemEditDialog::ShowText);
lbajardsilogic@0 611
lbajardsilogic@0 612 dialog->setFrameTime(point.frame);
lbajardsilogic@0 613 dialog->setText(point.label);
lbajardsilogic@0 614
lbajardsilogic@0 615 if (dialog->exec() == QDialog::Accepted) {
lbajardsilogic@0 616
lbajardsilogic@0 617 SparseOneDimensionalModel::Point newPoint = point;
lbajardsilogic@0 618 newPoint.frame = dialog->getFrameTime();
lbajardsilogic@0 619 newPoint.label = dialog->getText();
lbajardsilogic@0 620
lbajardsilogic@0 621 SparseOneDimensionalModel::EditCommand *command =
lbajardsilogic@0 622 new SparseOneDimensionalModel::EditCommand(m_model, tr("Edit Point"));
lbajardsilogic@0 623 command->deletePoint(point);
lbajardsilogic@0 624 command->addPoint(newPoint);
lbajardsilogic@0 625 command->finish();
lbajardsilogic@0 626 }
lbajardsilogic@0 627
lbajardsilogic@0 628 delete dialog;
lbajardsilogic@0 629 }
lbajardsilogic@0 630
lbajardsilogic@0 631 void
lbajardsilogic@0 632 TimeInstantLayer::moveSelection(Selection s, size_t newStartFrame)
lbajardsilogic@0 633 {
lbajardsilogic@0 634 if (!m_model) return;
lbajardsilogic@0 635
lbajardsilogic@0 636 SparseOneDimensionalModel::EditCommand *command =
lbajardsilogic@0 637 new SparseOneDimensionalModel::EditCommand(m_model,
lbajardsilogic@0 638 tr("Drag Selection"));
lbajardsilogic@0 639
lbajardsilogic@0 640 SparseOneDimensionalModel::PointList points =
lbajardsilogic@0 641 m_model->getPoints(s.getStartFrame(), s.getEndFrame());
lbajardsilogic@0 642
lbajardsilogic@0 643 for (SparseOneDimensionalModel::PointList::iterator i = points.begin();
lbajardsilogic@0 644 i != points.end(); ++i) {
lbajardsilogic@0 645
lbajardsilogic@0 646 if (s.contains(i->frame)) {
lbajardsilogic@0 647 SparseOneDimensionalModel::Point newPoint(*i);
lbajardsilogic@0 648 newPoint.frame = i->frame + newStartFrame - s.getStartFrame();
lbajardsilogic@0 649 command->deletePoint(*i);
lbajardsilogic@0 650 command->addPoint(newPoint);
lbajardsilogic@0 651 }
lbajardsilogic@0 652 }
lbajardsilogic@0 653
lbajardsilogic@0 654 command->finish();
lbajardsilogic@0 655 }
lbajardsilogic@0 656
lbajardsilogic@0 657 void
lbajardsilogic@0 658 TimeInstantLayer::resizeSelection(Selection s, Selection newSize)
lbajardsilogic@0 659 {
lbajardsilogic@0 660 if (!m_model) return;
lbajardsilogic@0 661
lbajardsilogic@0 662 SparseOneDimensionalModel::EditCommand *command =
lbajardsilogic@0 663 new SparseOneDimensionalModel::EditCommand(m_model,
lbajardsilogic@0 664 tr("Resize Selection"));
lbajardsilogic@0 665
lbajardsilogic@0 666 SparseOneDimensionalModel::PointList points =
lbajardsilogic@0 667 m_model->getPoints(s.getStartFrame(), s.getEndFrame());
lbajardsilogic@0 668
lbajardsilogic@0 669 double ratio =
lbajardsilogic@0 670 double(newSize.getEndFrame() - newSize.getStartFrame()) /
lbajardsilogic@0 671 double(s.getEndFrame() - s.getStartFrame());
lbajardsilogic@0 672
lbajardsilogic@0 673 for (SparseOneDimensionalModel::PointList::iterator i = points.begin();
lbajardsilogic@0 674 i != points.end(); ++i) {
lbajardsilogic@0 675
lbajardsilogic@0 676 if (s.contains(i->frame)) {
lbajardsilogic@0 677
lbajardsilogic@0 678 double target = i->frame;
lbajardsilogic@0 679 target = newSize.getStartFrame() +
lbajardsilogic@0 680 double(target - s.getStartFrame()) * ratio;
lbajardsilogic@0 681
lbajardsilogic@0 682 SparseOneDimensionalModel::Point newPoint(*i);
lbajardsilogic@0 683 newPoint.frame = lrint(target);
lbajardsilogic@0 684 command->deletePoint(*i);
lbajardsilogic@0 685 command->addPoint(newPoint);
lbajardsilogic@0 686 }
lbajardsilogic@0 687 }
lbajardsilogic@0 688
lbajardsilogic@0 689 command->finish();
lbajardsilogic@0 690 }
lbajardsilogic@0 691
lbajardsilogic@0 692 void
lbajardsilogic@0 693 TimeInstantLayer::deleteSelection(Selection s)
lbajardsilogic@0 694 {
lbajardsilogic@0 695 if (!m_model) return;
lbajardsilogic@0 696
lbajardsilogic@0 697 SparseOneDimensionalModel::EditCommand *command =
lbajardsilogic@0 698 new SparseOneDimensionalModel::EditCommand(m_model,
lbajardsilogic@0 699 tr("Delete Selection"));
lbajardsilogic@0 700
lbajardsilogic@0 701 SparseOneDimensionalModel::PointList points =
lbajardsilogic@0 702 m_model->getPoints(s.getStartFrame(), s.getEndFrame());
lbajardsilogic@0 703
lbajardsilogic@0 704 for (SparseOneDimensionalModel::PointList::iterator i = points.begin();
lbajardsilogic@0 705 i != points.end(); ++i) {
lbajardsilogic@0 706 if (s.contains(i->frame)) command->deletePoint(*i);
lbajardsilogic@0 707 }
lbajardsilogic@0 708
lbajardsilogic@0 709 command->finish();
lbajardsilogic@0 710 }
lbajardsilogic@0 711
lbajardsilogic@0 712 void
lbajardsilogic@0 713 TimeInstantLayer::copy(Selection s, Clipboard &to)
lbajardsilogic@0 714 {
lbajardsilogic@0 715 if (!m_model) return;
lbajardsilogic@0 716
lbajardsilogic@0 717 SparseOneDimensionalModel::PointList points =
lbajardsilogic@0 718 m_model->getPoints(s.getStartFrame(), s.getEndFrame());
lbajardsilogic@0 719
lbajardsilogic@0 720 for (SparseOneDimensionalModel::PointList::iterator i = points.begin();
lbajardsilogic@0 721 i != points.end(); ++i) {
lbajardsilogic@0 722 if (s.contains(i->frame)) {
lbajardsilogic@0 723 Clipboard::Point point(i->frame, i->label);
lbajardsilogic@0 724 to.addPoint(point);
lbajardsilogic@0 725 }
lbajardsilogic@0 726 }
lbajardsilogic@0 727 }
lbajardsilogic@0 728
lbajardsilogic@0 729 bool
lbajardsilogic@0 730 TimeInstantLayer::paste(const Clipboard &from, int frameOffset, bool)
lbajardsilogic@0 731 {
lbajardsilogic@0 732 if (!m_model) return false;
lbajardsilogic@0 733
lbajardsilogic@0 734 const Clipboard::PointList &points = from.getPoints();
lbajardsilogic@0 735
lbajardsilogic@0 736 SparseOneDimensionalModel::EditCommand *command =
lbajardsilogic@0 737 new SparseOneDimensionalModel::EditCommand(m_model, tr("Paste"));
lbajardsilogic@0 738
lbajardsilogic@0 739 for (Clipboard::PointList::const_iterator i = points.begin();
lbajardsilogic@0 740 i != points.end(); ++i) {
lbajardsilogic@0 741
lbajardsilogic@0 742 if (!i->haveFrame()) continue;
lbajardsilogic@0 743 size_t frame = 0;
lbajardsilogic@0 744 if (frameOffset > 0 || -frameOffset < i->getFrame()) {
lbajardsilogic@0 745 frame = i->getFrame() + frameOffset;
lbajardsilogic@0 746 }
lbajardsilogic@0 747 SparseOneDimensionalModel::Point newPoint(frame);
lbajardsilogic@0 748 if (i->haveLabel()) {
lbajardsilogic@0 749 newPoint.label = i->getLabel();
lbajardsilogic@0 750 } else if (i->haveValue()) {
lbajardsilogic@0 751 newPoint.label = QString("%1").arg(i->getValue());
lbajardsilogic@0 752 }
lbajardsilogic@0 753
lbajardsilogic@0 754 command->addPoint(newPoint);
lbajardsilogic@0 755 }
lbajardsilogic@0 756
lbajardsilogic@0 757 command->finish();
lbajardsilogic@0 758 return true;
lbajardsilogic@0 759 }
lbajardsilogic@0 760
lbajardsilogic@0 761 QString
lbajardsilogic@0 762 TimeInstantLayer::toXmlString(QString indent, QString extraAttributes) const
lbajardsilogic@0 763 {
lbajardsilogic@0 764 return Layer::toXmlString(indent, extraAttributes +
lbajardsilogic@0 765 QString(" colour=\"%1\" plotStyle=\"%2\"")
lbajardsilogic@0 766 .arg(encodeColour(m_colour)).arg(m_plotStyle));
lbajardsilogic@0 767 }
lbajardsilogic@0 768
lbajardsilogic@18 769 QString
lbajardsilogic@18 770 TimeInstantLayer::toEasaierXmlString(QString indent, QString extraAttributes) const
lbajardsilogic@18 771 {
lbajardsilogic@18 772 return Layer::toEasaierXmlString(indent, extraAttributes +
lbajardsilogic@18 773 QString(" colour=\"%1\" plotStyle=\"%2\"")
lbajardsilogic@18 774 .arg(encodeColour(m_colour)).arg(m_plotStyle));
lbajardsilogic@18 775 }
lbajardsilogic@18 776
lbajardsilogic@0 777 void
lbajardsilogic@0 778 TimeInstantLayer::setProperties(const QXmlAttributes &attributes)
lbajardsilogic@0 779 {
lbajardsilogic@0 780 QString colourSpec = attributes.value("colour");
lbajardsilogic@0 781 if (colourSpec != "") {
lbajardsilogic@0 782 QColor colour(colourSpec);
lbajardsilogic@0 783 if (colour.isValid()) {
lbajardsilogic@0 784 setBaseColour(QColor(colourSpec));
lbajardsilogic@0 785 }
lbajardsilogic@0 786 }
lbajardsilogic@0 787
lbajardsilogic@0 788 bool ok;
lbajardsilogic@0 789 PlotStyle style = (PlotStyle)
lbajardsilogic@0 790 attributes.value("plotStyle").toInt(&ok);
lbajardsilogic@0 791 if (ok) setPlotStyle(style);
lbajardsilogic@0 792 }
lbajardsilogic@0 793