annotate layer/Layer.cpp @ 829:5acfb11e8aef

Do not move playhead on click, unless in "DAW mode". In centre-frame modes it's confusing and leads to random jumps when playing aligned material
author Chris Cannam
date Fri, 25 Jul 2014 17:02:16 +0100
parents 4c8ca536b54f
children e0f08e108064
rev   line source
Chris@127 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@127 2
Chris@127 3 /*
Chris@127 4 Sonic Visualiser
Chris@127 5 An audio file viewer and annotation editor.
Chris@127 6 Centre for Digital Music, Queen Mary, University of London.
Chris@182 7 This file copyright 2006 Chris Cannam and QMUL.
Chris@127 8
Chris@127 9 This program is free software; you can redistribute it and/or
Chris@127 10 modify it under the terms of the GNU General Public License as
Chris@127 11 published by the Free Software Foundation; either version 2 of the
Chris@127 12 License, or (at your option) any later version. See the file
Chris@127 13 COPYING included with this distribution for more information.
Chris@127 14 */
Chris@127 15
Chris@127 16 #include "Layer.h"
Chris@128 17 #include "view/View.h"
Chris@128 18 #include "data/model/Model.h"
Chris@376 19 #include "widgets/CommandHistory.h"
Chris@127 20
Chris@127 21 #include <iostream>
Chris@127 22
Chris@131 23 #include <QMutexLocker>
Chris@267 24 #include <QMouseEvent>
Chris@316 25 #include <QTextStream>
Chris@131 26
Chris@326 27 #include <QDomDocument>
Chris@326 28 #include <QDomElement>
Chris@326 29 #include <QDomNamedNodeMap>
Chris@326 30 #include <QDomAttr>
Chris@326 31
Chris@131 32 #include "LayerFactory.h"
Chris@128 33 #include "base/PlayParameterRepository.h"
Chris@127 34
Chris@272 35 #include <cmath>
Chris@272 36
Chris@267 37 Layer::Layer() :
Chris@283 38 m_haveDraggingRect(false),
Chris@283 39 m_haveCurrentMeasureRect(false)
Chris@127 40 {
Chris@127 41 }
Chris@127 42
Chris@127 43 Layer::~Layer()
Chris@127 44 {
Chris@587 45 // SVDEBUG << "Layer::~Layer(" << this << ")" << endl;
Chris@127 46 }
Chris@127 47
Chris@320 48 void
Chris@320 49 Layer::connectSignals(const Model *model)
Chris@320 50 {
Chris@320 51 connect(model, SIGNAL(modelChanged()),
Chris@320 52 this, SIGNAL(modelChanged()));
Chris@320 53
Chris@806 54 connect(model, SIGNAL(modelChangedWithin(int, int)),
Chris@806 55 this, SIGNAL(modelChangedWithin(int, int)));
Chris@320 56
Chris@320 57 connect(model, SIGNAL(completionChanged()),
Chris@320 58 this, SIGNAL(modelCompletionChanged()));
Chris@320 59
Chris@320 60 connect(model, SIGNAL(alignmentCompletionChanged()),
Chris@320 61 this, SIGNAL(modelAlignmentCompletionChanged()));
Chris@320 62 }
Chris@320 63
Chris@127 64 QString
Chris@127 65 Layer::getPropertyContainerIconName() const
Chris@127 66 {
Chris@127 67 return LayerFactory::getInstance()->getLayerIconName
Chris@127 68 (LayerFactory::getInstance()->getLayerType(this));
Chris@127 69 }
Chris@127 70
Chris@363 71 void
Chris@363 72 Layer::setPresentationName(QString name)
Chris@363 73 {
Chris@363 74 m_presentationName = name;
Chris@363 75 }
Chris@363 76
Chris@127 77 QString
Chris@127 78 Layer::getLayerPresentationName() const
Chris@127 79 {
Chris@363 80 if (m_presentationName != "") return m_presentationName;
Chris@203 81
Chris@203 82 LayerFactory *factory = LayerFactory::getInstance();
Chris@203 83 QString layerName = factory->getLayerPresentationName
Chris@203 84 (factory->getLayerType(this));
Chris@203 85
Chris@127 86 QString modelName;
Chris@127 87 if (getModel()) modelName = getModel()->objectName();
Chris@127 88
Chris@127 89 QString text;
Chris@127 90 if (modelName != "") {
Chris@127 91 text = QString("%1: %2").arg(modelName).arg(layerName);
Chris@127 92 } else {
Chris@127 93 text = layerName;
Chris@127 94 }
Chris@127 95
Chris@127 96 return text;
Chris@127 97 }
Chris@127 98
Chris@127 99 void
Chris@127 100 Layer::setObjectName(const QString &name)
Chris@127 101 {
Chris@127 102 QObject::setObjectName(name);
Chris@127 103 emit layerNameChanged();
Chris@127 104 }
Chris@127 105
Chris@127 106 PlayParameters *
Chris@127 107 Layer::getPlayParameters()
Chris@127 108 {
Chris@682 109 // cerr << "Layer (" << this << ", " << objectName() << ")::getPlayParameters: model is "<< getModel() << endl;
Chris@127 110 const Model *model = getModel();
Chris@127 111 if (model) {
Chris@127 112 return PlayParameterRepository::getInstance()->getPlayParameters(model);
Chris@127 113 }
Chris@127 114 return 0;
Chris@127 115 }
Chris@127 116
Chris@127 117 void
Chris@131 118 Layer::setLayerDormant(const View *v, bool dormant)
Chris@131 119 {
Chris@131 120 const void *vv = (const void *)v;
Chris@131 121 QMutexLocker locker(&m_dormancyMutex);
Chris@131 122 m_dormancy[vv] = dormant;
Chris@131 123 }
Chris@131 124
Chris@131 125 bool
Chris@131 126 Layer::isLayerDormant(const View *v) const
Chris@131 127 {
Chris@131 128 const void *vv = (const void *)v;
Chris@131 129 QMutexLocker locker(&m_dormancyMutex);
Chris@131 130 if (m_dormancy.find(vv) == m_dormancy.end()) return false;
Chris@131 131 return m_dormancy.find(vv)->second;
Chris@131 132 }
Chris@131 133
Chris@131 134 void
Chris@127 135 Layer::showLayer(View *view, bool show)
Chris@127 136 {
Chris@127 137 setLayerDormant(view, !show);
Chris@127 138 emit layerParametersChanged();
Chris@127 139 }
Chris@127 140
Chris@260 141 bool
Chris@267 142 Layer::getXScaleValue(const View *v, int x, float &value, QString &unit) const
Chris@260 143 {
Chris@260 144 if (!hasTimeXAxis()) return false;
Chris@260 145
Chris@260 146 const Model *m = getModel();
Chris@260 147 if (!m) return false;
Chris@260 148
Chris@260 149 value = float(v->getFrameForX(x)) / m->getSampleRate();
Chris@260 150 unit = "s";
Chris@260 151 return true;
Chris@260 152 }
Chris@260 153
Chris@268 154 bool
Chris@274 155 Layer::getYScaleDifference(const View *v, int y0, int y1,
Chris@274 156 float &diff, QString &unit) const
Chris@274 157 {
Chris@274 158 float v0, v1;
Chris@274 159 if (!getYScaleValue(v, y0, v0, unit) ||
Chris@274 160 !getYScaleValue(v, y1, v1, unit)) {
Chris@274 161 diff = 0.f;
Chris@274 162 return false;
Chris@274 163 }
Chris@274 164 diff = fabsf(v1 - v0);
Chris@274 165 return true;
Chris@274 166 }
Chris@274 167
Chris@805 168 int
Chris@805 169 Layer::alignToReference(View *v, int frame) const
Chris@359 170 {
Chris@359 171 const Model *m = getModel();
Chris@587 172 SVDEBUG << "Layer::alignToReference(" << frame << "): model = " << m << ", alignment reference = " << (m ? m->getAlignmentReference() : 0) << endl;
Chris@359 173 if (m && m->getAlignmentReference()) {
Chris@359 174 return m->alignToReference(frame);
Chris@359 175 } else {
Chris@359 176 return v->alignToReference(frame);
Chris@359 177 }
Chris@359 178 }
Chris@359 179
Chris@805 180 int
Chris@805 181 Layer::alignFromReference(View *v, int frame) const
Chris@359 182 {
Chris@359 183 const Model *m = getModel();
Chris@587 184 SVDEBUG << "Layer::alignFromReference(" << frame << "): model = " << m << ", alignment reference = " << (m ? m->getAlignmentReference() : 0) << endl;
Chris@359 185 if (m && m->getAlignmentReference()) {
Chris@359 186 return m->alignFromReference(frame);
Chris@359 187 } else {
Chris@359 188 return v->alignFromReference(frame);
Chris@359 189 }
Chris@359 190 }
Chris@359 191
Chris@274 192 bool
Chris@360 193 Layer::clipboardHasDifferentAlignment(View *v, const Clipboard &clip) const
Chris@360 194 {
Chris@360 195 // Notes on pasting to an aligned layer:
Chris@360 196 //
Chris@360 197 // Each point may have a reference frame that may differ from the
Chris@360 198 // point's given frame (in its source model). If it has no
Chris@360 199 // reference frame, we have to assume the source model was not
Chris@360 200 // aligned or was the reference model: when cutting or copying
Chris@360 201 // points from a layer, we must always set their reference frame
Chris@360 202 // correctly if we are aligned.
Chris@360 203 //
Chris@360 204 // When pasting:
Chris@360 205 // - if point's reference and aligned frames differ:
Chris@360 206 // - if this layer is aligned:
Chris@360 207 // - if point's aligned frame matches this layer's aligned version
Chris@360 208 // of point's reference frame:
Chris@360 209 // - we can paste at reference frame or our frame
Chris@360 210 // - else
Chris@360 211 // - we can paste at reference frame, result of aligning reference
Chris@360 212 // frame in our model, or literal source frame
Chris@360 213 // - else
Chris@360 214 // - we can paste at reference (our) frame, or literal source frame
Chris@360 215 // - else
Chris@360 216 // - if this layer is aligned:
Chris@360 217 // - we can paste at reference (point's only available) frame,
Chris@360 218 // or result of aligning reference frame in our model
Chris@360 219 // - else
Chris@360 220 // - we can only paste at reference frame
Chris@360 221 //
Chris@360 222 // Which of these alternatives are useful?
Chris@360 223 //
Chris@360 224 // Example: we paste between two tracks that are aligned to the
Chris@360 225 // same reference, and the points are at 10s and 20s in the source
Chris@360 226 // track, corresponding to 5s and 10s in the reference but 20s and
Chris@360 227 // 30s in the target track.
Chris@360 228 //
Chris@360 229 // The obvious default is to paste at 20s and 30s; if we aren't
Chris@360 230 // doing that, would it be better to paste at 5s and 10s or at 10s
Chris@360 231 // and 20s? We probably don't ever want to do the former, do we?
Chris@360 232 // We either want to be literal all the way through, or aligned
Chris@360 233 // all the way through.
Chris@360 234
Chris@360 235 for (Clipboard::PointList::const_iterator i = clip.getPoints().begin();
Chris@360 236 i != clip.getPoints().end(); ++i) {
Chris@360 237
Chris@360 238 // In principle, we want to know whether the aligned version
Chris@360 239 // of the reference frame in our layer is the same as the
Chris@360 240 // source frame contained in the clipboard point. However,
Chris@360 241 // because of rounding during alignment, that won't
Chris@360 242 // necessarily be the case even if the clipboard point came
Chris@360 243 // from our layer! What we need to check is whether, if we
Chris@360 244 // aligned the clipboard point's frame back to the reference
Chris@360 245 // using this layer's alignment, we would obtain the same
Chris@360 246 // reference frame as that for the clipboard point.
Chris@360 247
Chris@360 248 // What if the clipboard point has no reference frame? Then
Chris@360 249 // we have to treat it as having its own frame as the
Chris@360 250 // reference (i.e. having been copied from the reference
Chris@360 251 // model).
Chris@360 252
Chris@806 253 int sourceFrame = i->getFrame();
Chris@806 254 int referenceFrame = sourceFrame;
Chris@360 255 if (i->haveReferenceFrame()) {
Chris@360 256 referenceFrame = i->getReferenceFrame();
Chris@360 257 }
Chris@806 258 int myMappedFrame = alignToReference(v, sourceFrame);
Chris@360 259
Chris@682 260 // cerr << "sourceFrame = " << sourceFrame << ", referenceFrame = " << referenceFrame << " (have = " << i->haveReferenceFrame() << "), myMappedFrame = " << myMappedFrame << endl;
Chris@360 261
Chris@360 262 if (myMappedFrame != referenceFrame) return true;
Chris@360 263 }
Chris@360 264
Chris@360 265 return false;
Chris@360 266 }
Chris@360 267
Chris@360 268 bool
Chris@268 269 Layer::MeasureRect::operator<(const MeasureRect &mr) const
Chris@268 270 {
Chris@268 271 if (haveFrames) {
Chris@268 272 if (startFrame == mr.startFrame) {
Chris@268 273 if (endFrame != mr.endFrame) {
Chris@268 274 return endFrame < mr.endFrame;
Chris@268 275 }
Chris@268 276 } else {
Chris@268 277 return startFrame < mr.startFrame;
Chris@268 278 }
Chris@268 279 } else {
Chris@268 280 if (pixrect.x() == mr.pixrect.x()) {
Chris@268 281 if (pixrect.width() != mr.pixrect.width()) {
Chris@268 282 return pixrect.width() < mr.pixrect.width();
Chris@268 283 }
Chris@268 284 } else {
Chris@268 285 return pixrect.x() < mr.pixrect.x();
Chris@268 286 }
Chris@268 287 }
Chris@268 288
Chris@268 289 // the two rects are equal in x and width
Chris@268 290
Chris@268 291 if (pixrect.y() == mr.pixrect.y()) {
Chris@268 292 return pixrect.height() < mr.pixrect.height();
Chris@268 293 } else {
Chris@268 294 return pixrect.y() < mr.pixrect.y();
Chris@268 295 }
Chris@268 296 }
Chris@268 297
Chris@316 298 void
Chris@316 299 Layer::MeasureRect::toXml(QTextStream &stream, QString indent) const
Chris@269 300 {
Chris@316 301 stream << indent;
Chris@316 302 stream << QString("<measurement ");
Chris@269 303
Chris@269 304 if (haveFrames) {
Chris@316 305 stream << QString("startFrame=\"%1\" endFrame=\"%2\" ")
Chris@269 306 .arg(startFrame).arg(endFrame);
Chris@269 307 } else {
Chris@316 308 stream << QString("startX=\"%1\" endX=\"%2\" ")
Chris@316 309 .arg(pixrect.x()).arg(pixrect.x() << pixrect.width());
Chris@269 310 }
Chris@269 311
Chris@316 312 stream << QString("startY=\"%1\" endY=\"%2\"/>\n")
Chris@273 313 .arg(startY).arg(endY);
Chris@269 314 }
Chris@269 315
Chris@269 316 void
Chris@269 317 Layer::addMeasurementRect(const QXmlAttributes &attributes)
Chris@269 318 {
Chris@269 319 MeasureRect rect;
Chris@269 320 QString fs = attributes.value("startFrame");
Chris@273 321 int x0 = 0, x1 = 0;
Chris@269 322 if (fs != "") {
Chris@806 323 rect.startFrame = fs.toInt();
Chris@806 324 rect.endFrame = attributes.value("endFrame").toInt();
Chris@269 325 rect.haveFrames = true;
Chris@269 326 } else {
Chris@269 327 x0 = attributes.value("startX").toInt();
Chris@269 328 x1 = attributes.value("endX").toInt();
Chris@269 329 rect.haveFrames = false;
Chris@269 330 }
Chris@273 331 rect.startY = attributes.value("startY").toDouble();
Chris@273 332 rect.endY = attributes.value("endY").toDouble();
Chris@273 333 rect.pixrect = QRect(x0, 0, x1 - x0, 0);
Chris@269 334 addMeasureRectToSet(rect);
Chris@269 335 }
Chris@269 336
Chris@269 337 QString
Chris@268 338 Layer::AddMeasurementRectCommand::getName() const
Chris@268 339 {
Chris@268 340 return tr("Make Measurement");
Chris@268 341 }
Chris@268 342
Chris@268 343 void
Chris@268 344 Layer::AddMeasurementRectCommand::execute()
Chris@268 345 {
Chris@269 346 m_layer->addMeasureRectToSet(m_rect);
Chris@268 347 }
Chris@268 348
Chris@268 349 void
Chris@268 350 Layer::AddMeasurementRectCommand::unexecute()
Chris@268 351 {
Chris@269 352 m_layer->deleteMeasureRectFromSet(m_rect);
Chris@268 353 }
Chris@268 354
Chris@283 355 QString
Chris@283 356 Layer::DeleteMeasurementRectCommand::getName() const
Chris@283 357 {
Chris@283 358 return tr("Delete Measurement");
Chris@283 359 }
Chris@283 360
Chris@283 361 void
Chris@283 362 Layer::DeleteMeasurementRectCommand::execute()
Chris@283 363 {
Chris@283 364 m_layer->deleteMeasureRectFromSet(m_rect);
Chris@283 365 }
Chris@283 366
Chris@283 367 void
Chris@283 368 Layer::DeleteMeasurementRectCommand::unexecute()
Chris@283 369 {
Chris@283 370 m_layer->addMeasureRectToSet(m_rect);
Chris@283 371 }
Chris@283 372
Chris@267 373 void
Chris@267 374 Layer::measureStart(View *v, QMouseEvent *e)
Chris@267 375 {
Chris@283 376 setMeasureRectFromPixrect(v, m_draggingRect,
Chris@283 377 QRect(e->x(), e->y(), 0, 0));
Chris@267 378 m_haveDraggingRect = true;
Chris@267 379 }
Chris@267 380
Chris@267 381 void
Chris@267 382 Layer::measureDrag(View *v, QMouseEvent *e)
Chris@267 383 {
Chris@267 384 if (!m_haveDraggingRect) return;
Chris@268 385
Chris@283 386 setMeasureRectFromPixrect(v, m_draggingRect,
Chris@283 387 QRect(m_draggingRect.pixrect.x(),
Chris@283 388 m_draggingRect.pixrect.y(),
Chris@283 389 e->x() - m_draggingRect.pixrect.x(),
Chris@283 390 e->y() - m_draggingRect.pixrect.y()));
Chris@267 391 }
Chris@267 392
Chris@267 393 void
Chris@267 394 Layer::measureEnd(View *v, QMouseEvent *e)
Chris@267 395 {
Chris@267 396 if (!m_haveDraggingRect) return;
Chris@267 397 measureDrag(v, e);
Chris@283 398
Chris@283 399 if (!m_draggingRect.pixrect.isNull()) {
Chris@283 400 CommandHistory::getInstance()->addCommand
Chris@283 401 (new AddMeasurementRectCommand(this, m_draggingRect));
Chris@283 402 }
Chris@268 403
Chris@267 404 m_haveDraggingRect = false;
Chris@267 405 }
Chris@267 406
Chris@267 407 void
Chris@805 408 Layer::measureDoubleClick(View *, QMouseEvent *)
Chris@280 409 {
Chris@283 410 // nothing, in the base class
Chris@283 411 }
Chris@283 412
Chris@283 413 void
Chris@283 414 Layer::deleteCurrentMeasureRect()
Chris@283 415 {
Chris@283 416 if (!m_haveCurrentMeasureRect) return;
Chris@283 417
Chris@283 418 MeasureRectSet::const_iterator focusRectItr =
Chris@283 419 findFocusedMeasureRect(m_currentMeasureRectPoint);
Chris@283 420
Chris@283 421 if (focusRectItr == m_measureRects.end()) return;
Chris@283 422
Chris@283 423 CommandHistory::getInstance()->addCommand
Chris@283 424 (new DeleteMeasurementRectCommand(this, *focusRectItr));
Chris@280 425 }
Chris@280 426
Chris@280 427 void
Chris@272 428 Layer::paintMeasurementRects(View *v, QPainter &paint,
Chris@272 429 bool showFocus, QPoint focusPoint) const
Chris@267 430 {
Chris@273 431 updateMeasurePixrects(v);
Chris@272 432
Chris@272 433 MeasureRectSet::const_iterator focusRectItr = m_measureRects.end();
Chris@272 434
Chris@267 435 if (m_haveDraggingRect) {
Chris@272 436
Chris@270 437 paintMeasurementRect(v, paint, m_draggingRect, true);
Chris@272 438
Chris@272 439 } else if (showFocus) {
Chris@272 440
Chris@272 441 focusRectItr = findFocusedMeasureRect(focusPoint);
Chris@267 442 }
Chris@267 443
Chris@283 444 m_haveCurrentMeasureRect = false;
Chris@283 445
Chris@268 446 for (MeasureRectSet::const_iterator i = m_measureRects.begin();
Chris@268 447 i != m_measureRects.end(); ++i) {
Chris@283 448
Chris@283 449 bool focused = (i == focusRectItr);
Chris@283 450 paintMeasurementRect(v, paint, *i, focused);
Chris@283 451
Chris@283 452 if (focused) {
Chris@283 453 m_haveCurrentMeasureRect = true;
Chris@283 454 m_currentMeasureRectPoint = focusPoint;
Chris@283 455 }
Chris@267 456 }
Chris@267 457 }
Chris@267 458
Chris@272 459 bool
Chris@272 460 Layer::nearestMeasurementRectChanged(View *v, QPoint prev, QPoint now) const
Chris@272 461 {
Chris@273 462 updateMeasurePixrects(v);
Chris@272 463
Chris@272 464 MeasureRectSet::const_iterator i0 = findFocusedMeasureRect(prev);
Chris@272 465 MeasureRectSet::const_iterator i1 = findFocusedMeasureRect(now);
Chris@272 466
Chris@272 467 return (i0 != i1);
Chris@272 468 }
Chris@272 469
Chris@272 470 void
Chris@273 471 Layer::updateMeasurePixrects(View *v) const
Chris@272 472 {
Chris@806 473 int sf = v->getStartFrame();
Chris@806 474 int ef = v->getEndFrame();
Chris@272 475
Chris@272 476 for (MeasureRectSet::const_iterator i = m_measureRects.begin();
Chris@272 477 i != m_measureRects.end(); ++i) {
Chris@272 478
Chris@273 479 // This logic depends on the fact that if one measure rect in
Chris@273 480 // a layer has frame values, they all will. That is in fact
Chris@273 481 // the case, because haveFrames is based on whether the layer
Chris@273 482 // hasTimeXAxis() or not. Measure rect ordering in the rect
Chris@273 483 // set wouldn't work correctly either, if haveFrames could
Chris@273 484 // vary.
Chris@272 485
Chris@273 486 if (i->haveFrames) {
Chris@273 487 if (i->startFrame >= ef) break;
Chris@273 488 if (i->endFrame <= sf) continue;
Chris@273 489 }
Chris@272 490
Chris@273 491 int x0 = i->pixrect.x();
Chris@273 492 int x1 = x0 + i->pixrect.width();
Chris@273 493
Chris@273 494 if (i->haveFrames) {
Chris@273 495 if (i->startFrame >= v->getStartFrame()) {
Chris@273 496 x0 = v->getXForFrame(i->startFrame);
Chris@273 497 }
Chris@806 498 if (i->endFrame <= int(v->getEndFrame())) {
Chris@273 499 x1 = v->getXForFrame(i->endFrame);
Chris@273 500 }
Chris@272 501 }
Chris@272 502
Chris@273 503 i->pixrect = QRect(x0, i->pixrect.y(), x1 - x0, i->pixrect.height());
Chris@273 504
Chris@273 505 updateMeasureRectYCoords(v, *i);
Chris@273 506 }
Chris@273 507 }
Chris@273 508
Chris@273 509 void
Chris@273 510 Layer::updateMeasureRectYCoords(View *v, const MeasureRect &r) const
Chris@273 511 {
Chris@273 512 int y0 = lrint(r.startY * v->height());
Chris@273 513 int y1 = lrint(r.endY * v->height());
Chris@273 514 r.pixrect = QRect(r.pixrect.x(), y0, r.pixrect.width(), y1 - y0);
Chris@273 515 }
Chris@273 516
Chris@273 517 void
Chris@273 518 Layer::setMeasureRectYCoord(View *v, MeasureRect &r, bool start, int y) const
Chris@273 519 {
Chris@273 520 if (start) {
Chris@273 521 r.startY = double(y) / double(v->height());
Chris@273 522 r.endY = r.startY;
Chris@273 523 } else {
Chris@273 524 r.endY = double(y) / double(v->height());
Chris@272 525 }
Chris@272 526 }
Chris@272 527
Chris@283 528 void
Chris@283 529 Layer::setMeasureRectFromPixrect(View *v, MeasureRect &r, QRect pixrect) const
Chris@283 530 {
Chris@283 531 r.pixrect = pixrect;
Chris@283 532 r.haveFrames = hasTimeXAxis();
Chris@283 533 if (r.haveFrames) {
Chris@283 534 r.startFrame = v->getFrameForX(pixrect.x());
Chris@283 535 r.endFrame = v->getFrameForX(pixrect.x() + pixrect.width());
Chris@283 536 }
Chris@283 537 setMeasureRectYCoord(v, r, true, pixrect.y());
Chris@283 538 setMeasureRectYCoord(v, r, false, pixrect.y() + pixrect.height());
Chris@283 539 }
Chris@283 540
Chris@272 541 Layer::MeasureRectSet::const_iterator
Chris@272 542 Layer::findFocusedMeasureRect(QPoint focusPoint) const
Chris@272 543 {
Chris@272 544 float frDist = 0;
Chris@272 545 MeasureRectSet::const_iterator focusRectItr = m_measureRects.end();
Chris@272 546
Chris@272 547 for (MeasureRectSet::const_iterator i = m_measureRects.begin();
Chris@272 548 i != m_measureRects.end(); ++i) {
Chris@272 549
Chris@272 550 if (!i->pixrect.adjusted(-2, -2, 2, 2).contains(focusPoint)) continue;
Chris@272 551
Chris@272 552 int cx = i->pixrect.x() + i->pixrect.width()/2;
Chris@272 553 int cy = i->pixrect.y() + i->pixrect.height()/2;
Chris@272 554 int xd = focusPoint.x() - cx;
Chris@272 555 int yd = focusPoint.y() - cy;
Chris@272 556
Chris@545 557 float d = sqrt(float(xd * xd + yd * yd));
Chris@272 558
Chris@272 559 if (focusRectItr == m_measureRects.end() || d < frDist) {
Chris@272 560 focusRectItr = i;
Chris@272 561 frDist = d;
Chris@272 562 }
Chris@272 563 }
Chris@272 564
Chris@272 565 return focusRectItr;
Chris@272 566 }
Chris@272 567
Chris@268 568 void
Chris@270 569 Layer::paintMeasurementRect(View *v, QPainter &paint,
Chris@270 570 const MeasureRect &r, bool focus) const
Chris@268 571 {
Chris@268 572 if (r.haveFrames) {
Chris@268 573
Chris@268 574 int x0 = -1;
Chris@268 575 int x1 = v->width() + 1;
Chris@268 576
Chris@268 577 if (r.startFrame >= v->getStartFrame()) {
Chris@268 578 x0 = v->getXForFrame(r.startFrame);
Chris@268 579 }
Chris@806 580 if (r.endFrame <= v->getEndFrame()) {
Chris@268 581 x1 = v->getXForFrame(r.endFrame);
Chris@268 582 }
Chris@268 583
Chris@272 584 QRect pr = QRect(x0, r.pixrect.y(), x1 - x0, r.pixrect.height());
Chris@268 585 r.pixrect = pr;
Chris@268 586 }
Chris@274 587
Chris@274 588 v->drawMeasurementRect(paint, this, r.pixrect.normalized(), focus);
Chris@268 589 }
Chris@268 590
Chris@316 591 void
Chris@316 592 Layer::toXml(QTextStream &stream,
Chris@316 593 QString indent, QString extraAttributes) const
Chris@268 594 {
Chris@316 595 stream << indent;
Chris@268 596
Chris@363 597 if (m_presentationName != "") {
Chris@363 598 extraAttributes = QString("%1 presentationName=\"%2\"")
Chris@363 599 .arg(extraAttributes).arg(encodeEntities(m_presentationName));
Chris@363 600 }
Chris@363 601
Chris@316 602 stream << QString("<layer id=\"%2\" type=\"%1\" name=\"%3\" model=\"%4\" %5")
Chris@268 603 .arg(encodeEntities(LayerFactory::getInstance()->getLayerTypeName
Chris@268 604 (LayerFactory::getInstance()->getLayerType(this))))
Chris@268 605 .arg(getObjectExportId(this))
Chris@268 606 .arg(encodeEntities(objectName()))
Chris@268 607 .arg(getObjectExportId(getModel()))
Chris@268 608 .arg(extraAttributes);
Chris@268 609
Chris@269 610 if (m_measureRects.empty()) {
Chris@316 611 stream << QString("/>\n");
Chris@316 612 return;
Chris@269 613 }
Chris@269 614
Chris@316 615 stream << QString(">\n");
Chris@269 616
Chris@269 617 for (MeasureRectSet::const_iterator i = m_measureRects.begin();
Chris@269 618 i != m_measureRects.end(); ++i) {
Chris@316 619 i->toXml(stream, indent + " ");
Chris@269 620 }
Chris@269 621
Chris@316 622 stream << QString("</layer>\n");
Chris@268 623 }
Chris@269 624
Chris@316 625 void
Chris@316 626 Layer::toBriefXml(QTextStream &stream,
Chris@316 627 QString indent, QString extraAttributes) const
Chris@269 628 {
Chris@316 629 stream << indent;
Chris@269 630
Chris@363 631 if (m_presentationName != "") {
Chris@363 632 extraAttributes = QString("%1 presentationName=\"%2\"")
Chris@363 633 .arg(extraAttributes).arg(encodeEntities(m_presentationName));
Chris@363 634 }
Chris@363 635
Chris@316 636 stream << QString("<layer id=\"%2\" type=\"%1\" name=\"%3\" model=\"%4\" %5/>\n")
Chris@269 637 .arg(encodeEntities(LayerFactory::getInstance()->getLayerTypeName
Chris@269 638 (LayerFactory::getInstance()->getLayerType(this))))
Chris@269 639 .arg(getObjectExportId(this))
Chris@269 640 .arg(encodeEntities(objectName()))
Chris@269 641 .arg(getObjectExportId(getModel()))
Chris@269 642 .arg(extraAttributes);
Chris@269 643 }
Chris@269 644