annotate layer/Layer.cpp @ 317:e251c3599ea8

* Make RemoteFile far more pervasive, and use it for local files as well so that we can handle both transparently. Make it shallow copy with reference counting, so it can be used by value without having to worry about the cache file lifetime. Use RemoteFile for MainWindow file-open functions, etc
author Chris Cannam
date Thu, 18 Oct 2007 15:31:20 +0000
parents c0b9eec70639
children 984c1975f1ff
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@268 19 #include "base/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@131 27 #include "LayerFactory.h"
Chris@128 28 #include "base/PlayParameterRepository.h"
Chris@127 29
Chris@272 30 #include <cmath>
Chris@272 31
Chris@267 32 Layer::Layer() :
Chris@283 33 m_haveDraggingRect(false),
Chris@283 34 m_haveCurrentMeasureRect(false)
Chris@127 35 {
Chris@127 36 }
Chris@127 37
Chris@127 38 Layer::~Layer()
Chris@127 39 {
Chris@127 40 // std::cerr << "Layer::~Layer(" << this << ")" << std::endl;
Chris@127 41 }
Chris@127 42
Chris@127 43 QString
Chris@127 44 Layer::getPropertyContainerIconName() const
Chris@127 45 {
Chris@127 46 return LayerFactory::getInstance()->getLayerIconName
Chris@127 47 (LayerFactory::getInstance()->getLayerType(this));
Chris@127 48 }
Chris@127 49
Chris@127 50 QString
Chris@127 51 Layer::getLayerPresentationName() const
Chris@127 52 {
Chris@203 53 // QString layerName = objectName();
Chris@203 54
Chris@203 55 LayerFactory *factory = LayerFactory::getInstance();
Chris@203 56 QString layerName = factory->getLayerPresentationName
Chris@203 57 (factory->getLayerType(this));
Chris@203 58
Chris@127 59 QString modelName;
Chris@127 60 if (getModel()) modelName = getModel()->objectName();
Chris@127 61
Chris@127 62 QString text;
Chris@127 63 if (modelName != "") {
Chris@127 64 text = QString("%1: %2").arg(modelName).arg(layerName);
Chris@127 65 } else {
Chris@127 66 text = layerName;
Chris@127 67 }
Chris@127 68
Chris@127 69 return text;
Chris@127 70 }
Chris@127 71
Chris@127 72 void
Chris@127 73 Layer::setObjectName(const QString &name)
Chris@127 74 {
Chris@127 75 QObject::setObjectName(name);
Chris@127 76 emit layerNameChanged();
Chris@127 77 }
Chris@127 78
Chris@127 79 PlayParameters *
Chris@127 80 Layer::getPlayParameters()
Chris@127 81 {
Chris@127 82 // std::cerr << "Layer (" << this << ", " << objectName().toStdString() << ")::getPlayParameters: model is "<< getModel() << std::endl;
Chris@127 83 const Model *model = getModel();
Chris@127 84 if (model) {
Chris@127 85 return PlayParameterRepository::getInstance()->getPlayParameters(model);
Chris@127 86 }
Chris@127 87 return 0;
Chris@127 88 }
Chris@127 89
Chris@127 90 void
Chris@131 91 Layer::setLayerDormant(const View *v, bool dormant)
Chris@131 92 {
Chris@131 93 const void *vv = (const void *)v;
Chris@131 94 QMutexLocker locker(&m_dormancyMutex);
Chris@131 95 m_dormancy[vv] = dormant;
Chris@131 96 }
Chris@131 97
Chris@131 98 bool
Chris@131 99 Layer::isLayerDormant(const View *v) const
Chris@131 100 {
Chris@131 101 const void *vv = (const void *)v;
Chris@131 102 QMutexLocker locker(&m_dormancyMutex);
Chris@131 103 if (m_dormancy.find(vv) == m_dormancy.end()) return false;
Chris@131 104 return m_dormancy.find(vv)->second;
Chris@131 105 }
Chris@131 106
Chris@131 107 void
Chris@127 108 Layer::showLayer(View *view, bool show)
Chris@127 109 {
Chris@127 110 setLayerDormant(view, !show);
Chris@127 111 emit layerParametersChanged();
Chris@127 112 }
Chris@127 113
Chris@260 114 bool
Chris@267 115 Layer::getXScaleValue(const View *v, int x, float &value, QString &unit) const
Chris@260 116 {
Chris@260 117 if (!hasTimeXAxis()) return false;
Chris@260 118
Chris@260 119 const Model *m = getModel();
Chris@260 120 if (!m) return false;
Chris@260 121
Chris@260 122 value = float(v->getFrameForX(x)) / m->getSampleRate();
Chris@260 123 unit = "s";
Chris@260 124 return true;
Chris@260 125 }
Chris@260 126
Chris@268 127 bool
Chris@274 128 Layer::getYScaleDifference(const View *v, int y0, int y1,
Chris@274 129 float &diff, QString &unit) const
Chris@274 130 {
Chris@274 131 float v0, v1;
Chris@274 132 if (!getYScaleValue(v, y0, v0, unit) ||
Chris@274 133 !getYScaleValue(v, y1, v1, unit)) {
Chris@274 134 diff = 0.f;
Chris@274 135 return false;
Chris@274 136 }
Chris@274 137 diff = fabsf(v1 - v0);
Chris@274 138 return true;
Chris@274 139 }
Chris@274 140
Chris@274 141 bool
Chris@268 142 Layer::MeasureRect::operator<(const MeasureRect &mr) const
Chris@268 143 {
Chris@268 144 if (haveFrames) {
Chris@268 145 if (startFrame == mr.startFrame) {
Chris@268 146 if (endFrame != mr.endFrame) {
Chris@268 147 return endFrame < mr.endFrame;
Chris@268 148 }
Chris@268 149 } else {
Chris@268 150 return startFrame < mr.startFrame;
Chris@268 151 }
Chris@268 152 } else {
Chris@268 153 if (pixrect.x() == mr.pixrect.x()) {
Chris@268 154 if (pixrect.width() != mr.pixrect.width()) {
Chris@268 155 return pixrect.width() < mr.pixrect.width();
Chris@268 156 }
Chris@268 157 } else {
Chris@268 158 return pixrect.x() < mr.pixrect.x();
Chris@268 159 }
Chris@268 160 }
Chris@268 161
Chris@268 162 // the two rects are equal in x and width
Chris@268 163
Chris@268 164 if (pixrect.y() == mr.pixrect.y()) {
Chris@268 165 return pixrect.height() < mr.pixrect.height();
Chris@268 166 } else {
Chris@268 167 return pixrect.y() < mr.pixrect.y();
Chris@268 168 }
Chris@268 169 }
Chris@268 170
Chris@316 171 void
Chris@316 172 Layer::MeasureRect::toXml(QTextStream &stream, QString indent) const
Chris@269 173 {
Chris@316 174 stream << indent;
Chris@316 175 stream << QString("<measurement ");
Chris@269 176
Chris@269 177 if (haveFrames) {
Chris@316 178 stream << QString("startFrame=\"%1\" endFrame=\"%2\" ")
Chris@269 179 .arg(startFrame).arg(endFrame);
Chris@269 180 } else {
Chris@316 181 stream << QString("startX=\"%1\" endX=\"%2\" ")
Chris@316 182 .arg(pixrect.x()).arg(pixrect.x() << pixrect.width());
Chris@269 183 }
Chris@269 184
Chris@316 185 stream << QString("startY=\"%1\" endY=\"%2\"/>\n")
Chris@273 186 .arg(startY).arg(endY);
Chris@269 187 }
Chris@269 188
Chris@269 189 void
Chris@269 190 Layer::addMeasurementRect(const QXmlAttributes &attributes)
Chris@269 191 {
Chris@269 192 MeasureRect rect;
Chris@269 193 QString fs = attributes.value("startFrame");
Chris@273 194 int x0 = 0, x1 = 0;
Chris@269 195 if (fs != "") {
Chris@269 196 rect.startFrame = fs.toLong();
Chris@269 197 rect.endFrame = attributes.value("endFrame").toLong();
Chris@269 198 rect.haveFrames = true;
Chris@269 199 } else {
Chris@269 200 x0 = attributes.value("startX").toInt();
Chris@269 201 x1 = attributes.value("endX").toInt();
Chris@269 202 rect.haveFrames = false;
Chris@269 203 }
Chris@273 204 rect.startY = attributes.value("startY").toDouble();
Chris@273 205 rect.endY = attributes.value("endY").toDouble();
Chris@273 206 rect.pixrect = QRect(x0, 0, x1 - x0, 0);
Chris@269 207 addMeasureRectToSet(rect);
Chris@269 208 }
Chris@269 209
Chris@269 210 QString
Chris@268 211 Layer::AddMeasurementRectCommand::getName() const
Chris@268 212 {
Chris@268 213 return tr("Make Measurement");
Chris@268 214 }
Chris@268 215
Chris@268 216 void
Chris@268 217 Layer::AddMeasurementRectCommand::execute()
Chris@268 218 {
Chris@269 219 m_layer->addMeasureRectToSet(m_rect);
Chris@268 220 }
Chris@268 221
Chris@268 222 void
Chris@268 223 Layer::AddMeasurementRectCommand::unexecute()
Chris@268 224 {
Chris@269 225 m_layer->deleteMeasureRectFromSet(m_rect);
Chris@268 226 }
Chris@268 227
Chris@283 228 QString
Chris@283 229 Layer::DeleteMeasurementRectCommand::getName() const
Chris@283 230 {
Chris@283 231 return tr("Delete Measurement");
Chris@283 232 }
Chris@283 233
Chris@283 234 void
Chris@283 235 Layer::DeleteMeasurementRectCommand::execute()
Chris@283 236 {
Chris@283 237 m_layer->deleteMeasureRectFromSet(m_rect);
Chris@283 238 }
Chris@283 239
Chris@283 240 void
Chris@283 241 Layer::DeleteMeasurementRectCommand::unexecute()
Chris@283 242 {
Chris@283 243 m_layer->addMeasureRectToSet(m_rect);
Chris@283 244 }
Chris@283 245
Chris@267 246 void
Chris@267 247 Layer::measureStart(View *v, QMouseEvent *e)
Chris@267 248 {
Chris@283 249 setMeasureRectFromPixrect(v, m_draggingRect,
Chris@283 250 QRect(e->x(), e->y(), 0, 0));
Chris@267 251 m_haveDraggingRect = true;
Chris@267 252 }
Chris@267 253
Chris@267 254 void
Chris@267 255 Layer::measureDrag(View *v, QMouseEvent *e)
Chris@267 256 {
Chris@267 257 if (!m_haveDraggingRect) return;
Chris@268 258
Chris@283 259 setMeasureRectFromPixrect(v, m_draggingRect,
Chris@283 260 QRect(m_draggingRect.pixrect.x(),
Chris@283 261 m_draggingRect.pixrect.y(),
Chris@283 262 e->x() - m_draggingRect.pixrect.x(),
Chris@283 263 e->y() - m_draggingRect.pixrect.y()));
Chris@267 264 }
Chris@267 265
Chris@267 266 void
Chris@267 267 Layer::measureEnd(View *v, QMouseEvent *e)
Chris@267 268 {
Chris@267 269 if (!m_haveDraggingRect) return;
Chris@267 270 measureDrag(v, e);
Chris@283 271
Chris@283 272 if (!m_draggingRect.pixrect.isNull()) {
Chris@283 273 CommandHistory::getInstance()->addCommand
Chris@283 274 (new AddMeasurementRectCommand(this, m_draggingRect));
Chris@283 275 }
Chris@268 276
Chris@267 277 m_haveDraggingRect = false;
Chris@267 278 }
Chris@267 279
Chris@267 280 void
Chris@280 281 Layer::measureDoubleClick(View *v, QMouseEvent *e)
Chris@280 282 {
Chris@283 283 // nothing, in the base class
Chris@283 284 }
Chris@283 285
Chris@283 286 void
Chris@283 287 Layer::deleteCurrentMeasureRect()
Chris@283 288 {
Chris@283 289 if (!m_haveCurrentMeasureRect) return;
Chris@283 290
Chris@283 291 MeasureRectSet::const_iterator focusRectItr =
Chris@283 292 findFocusedMeasureRect(m_currentMeasureRectPoint);
Chris@283 293
Chris@283 294 if (focusRectItr == m_measureRects.end()) return;
Chris@283 295
Chris@283 296 CommandHistory::getInstance()->addCommand
Chris@283 297 (new DeleteMeasurementRectCommand(this, *focusRectItr));
Chris@280 298 }
Chris@280 299
Chris@280 300 void
Chris@272 301 Layer::paintMeasurementRects(View *v, QPainter &paint,
Chris@272 302 bool showFocus, QPoint focusPoint) const
Chris@267 303 {
Chris@273 304 updateMeasurePixrects(v);
Chris@272 305
Chris@272 306 MeasureRectSet::const_iterator focusRectItr = m_measureRects.end();
Chris@272 307
Chris@267 308 if (m_haveDraggingRect) {
Chris@272 309
Chris@270 310 paintMeasurementRect(v, paint, m_draggingRect, true);
Chris@272 311
Chris@272 312 } else if (showFocus) {
Chris@272 313
Chris@272 314 focusRectItr = findFocusedMeasureRect(focusPoint);
Chris@267 315 }
Chris@267 316
Chris@283 317 m_haveCurrentMeasureRect = false;
Chris@283 318
Chris@268 319 for (MeasureRectSet::const_iterator i = m_measureRects.begin();
Chris@268 320 i != m_measureRects.end(); ++i) {
Chris@283 321
Chris@283 322 bool focused = (i == focusRectItr);
Chris@283 323 paintMeasurementRect(v, paint, *i, focused);
Chris@283 324
Chris@283 325 if (focused) {
Chris@283 326 m_haveCurrentMeasureRect = true;
Chris@283 327 m_currentMeasureRectPoint = focusPoint;
Chris@283 328 }
Chris@267 329 }
Chris@267 330 }
Chris@267 331
Chris@272 332 bool
Chris@272 333 Layer::nearestMeasurementRectChanged(View *v, QPoint prev, QPoint now) const
Chris@272 334 {
Chris@273 335 updateMeasurePixrects(v);
Chris@272 336
Chris@272 337 MeasureRectSet::const_iterator i0 = findFocusedMeasureRect(prev);
Chris@272 338 MeasureRectSet::const_iterator i1 = findFocusedMeasureRect(now);
Chris@272 339
Chris@272 340 return (i0 != i1);
Chris@272 341 }
Chris@272 342
Chris@272 343 void
Chris@273 344 Layer::updateMeasurePixrects(View *v) const
Chris@272 345 {
Chris@272 346 long sf = v->getStartFrame();
Chris@272 347 long ef = v->getEndFrame();
Chris@272 348
Chris@272 349 for (MeasureRectSet::const_iterator i = m_measureRects.begin();
Chris@272 350 i != m_measureRects.end(); ++i) {
Chris@272 351
Chris@273 352 // This logic depends on the fact that if one measure rect in
Chris@273 353 // a layer has frame values, they all will. That is in fact
Chris@273 354 // the case, because haveFrames is based on whether the layer
Chris@273 355 // hasTimeXAxis() or not. Measure rect ordering in the rect
Chris@273 356 // set wouldn't work correctly either, if haveFrames could
Chris@273 357 // vary.
Chris@272 358
Chris@273 359 if (i->haveFrames) {
Chris@273 360 if (i->startFrame >= ef) break;
Chris@273 361 if (i->endFrame <= sf) continue;
Chris@273 362 }
Chris@272 363
Chris@273 364 int x0 = i->pixrect.x();
Chris@273 365 int x1 = x0 + i->pixrect.width();
Chris@273 366
Chris@273 367 if (i->haveFrames) {
Chris@273 368 if (i->startFrame >= v->getStartFrame()) {
Chris@273 369 x0 = v->getXForFrame(i->startFrame);
Chris@273 370 }
Chris@273 371 if (i->endFrame <= long(v->getEndFrame())) {
Chris@273 372 x1 = v->getXForFrame(i->endFrame);
Chris@273 373 }
Chris@272 374 }
Chris@272 375
Chris@273 376 i->pixrect = QRect(x0, i->pixrect.y(), x1 - x0, i->pixrect.height());
Chris@273 377
Chris@273 378 updateMeasureRectYCoords(v, *i);
Chris@273 379 }
Chris@273 380 }
Chris@273 381
Chris@273 382 void
Chris@273 383 Layer::updateMeasureRectYCoords(View *v, const MeasureRect &r) const
Chris@273 384 {
Chris@273 385 int y0 = lrint(r.startY * v->height());
Chris@273 386 int y1 = lrint(r.endY * v->height());
Chris@273 387 r.pixrect = QRect(r.pixrect.x(), y0, r.pixrect.width(), y1 - y0);
Chris@273 388 }
Chris@273 389
Chris@273 390 void
Chris@273 391 Layer::setMeasureRectYCoord(View *v, MeasureRect &r, bool start, int y) const
Chris@273 392 {
Chris@273 393 if (start) {
Chris@273 394 r.startY = double(y) / double(v->height());
Chris@273 395 r.endY = r.startY;
Chris@273 396 } else {
Chris@273 397 r.endY = double(y) / double(v->height());
Chris@272 398 }
Chris@272 399 }
Chris@272 400
Chris@283 401 void
Chris@283 402 Layer::setMeasureRectFromPixrect(View *v, MeasureRect &r, QRect pixrect) const
Chris@283 403 {
Chris@283 404 r.pixrect = pixrect;
Chris@283 405 r.haveFrames = hasTimeXAxis();
Chris@283 406 if (r.haveFrames) {
Chris@283 407 r.startFrame = v->getFrameForX(pixrect.x());
Chris@283 408 r.endFrame = v->getFrameForX(pixrect.x() + pixrect.width());
Chris@283 409 }
Chris@283 410 setMeasureRectYCoord(v, r, true, pixrect.y());
Chris@283 411 setMeasureRectYCoord(v, r, false, pixrect.y() + pixrect.height());
Chris@283 412 }
Chris@283 413
Chris@272 414 Layer::MeasureRectSet::const_iterator
Chris@272 415 Layer::findFocusedMeasureRect(QPoint focusPoint) const
Chris@272 416 {
Chris@272 417 float frDist = 0;
Chris@272 418 MeasureRectSet::const_iterator focusRectItr = m_measureRects.end();
Chris@272 419
Chris@272 420 for (MeasureRectSet::const_iterator i = m_measureRects.begin();
Chris@272 421 i != m_measureRects.end(); ++i) {
Chris@272 422
Chris@272 423 if (!i->pixrect.adjusted(-2, -2, 2, 2).contains(focusPoint)) continue;
Chris@272 424
Chris@272 425 int cx = i->pixrect.x() + i->pixrect.width()/2;
Chris@272 426 int cy = i->pixrect.y() + i->pixrect.height()/2;
Chris@272 427 int xd = focusPoint.x() - cx;
Chris@272 428 int yd = focusPoint.y() - cy;
Chris@272 429
Chris@272 430 float d = sqrt(xd * xd + yd * yd);
Chris@272 431
Chris@272 432 if (focusRectItr == m_measureRects.end() || d < frDist) {
Chris@272 433 focusRectItr = i;
Chris@272 434 frDist = d;
Chris@272 435 }
Chris@272 436 }
Chris@272 437
Chris@272 438 return focusRectItr;
Chris@272 439 }
Chris@272 440
Chris@268 441 void
Chris@270 442 Layer::paintMeasurementRect(View *v, QPainter &paint,
Chris@270 443 const MeasureRect &r, bool focus) const
Chris@268 444 {
Chris@268 445 if (r.haveFrames) {
Chris@268 446
Chris@268 447 int x0 = -1;
Chris@268 448 int x1 = v->width() + 1;
Chris@268 449
Chris@268 450 if (r.startFrame >= v->getStartFrame()) {
Chris@268 451 x0 = v->getXForFrame(r.startFrame);
Chris@268 452 }
Chris@272 453 if (r.endFrame <= long(v->getEndFrame())) {
Chris@268 454 x1 = v->getXForFrame(r.endFrame);
Chris@268 455 }
Chris@268 456
Chris@272 457 QRect pr = QRect(x0, r.pixrect.y(), x1 - x0, r.pixrect.height());
Chris@268 458 r.pixrect = pr;
Chris@268 459 }
Chris@274 460
Chris@274 461 v->drawMeasurementRect(paint, this, r.pixrect.normalized(), focus);
Chris@268 462 }
Chris@268 463
Chris@316 464 void
Chris@316 465 Layer::toXml(QTextStream &stream,
Chris@316 466 QString indent, QString extraAttributes) const
Chris@268 467 {
Chris@316 468 stream << indent;
Chris@268 469
Chris@316 470 stream << QString("<layer id=\"%2\" type=\"%1\" name=\"%3\" model=\"%4\" %5")
Chris@268 471 .arg(encodeEntities(LayerFactory::getInstance()->getLayerTypeName
Chris@268 472 (LayerFactory::getInstance()->getLayerType(this))))
Chris@268 473 .arg(getObjectExportId(this))
Chris@268 474 .arg(encodeEntities(objectName()))
Chris@268 475 .arg(getObjectExportId(getModel()))
Chris@268 476 .arg(extraAttributes);
Chris@268 477
Chris@269 478 if (m_measureRects.empty()) {
Chris@316 479 stream << QString("/>\n");
Chris@316 480 return;
Chris@269 481 }
Chris@269 482
Chris@316 483 stream << QString(">\n");
Chris@269 484
Chris@269 485 for (MeasureRectSet::const_iterator i = m_measureRects.begin();
Chris@269 486 i != m_measureRects.end(); ++i) {
Chris@316 487 i->toXml(stream, indent + " ");
Chris@269 488 }
Chris@269 489
Chris@316 490 stream << QString("</layer>\n");
Chris@268 491 }
Chris@269 492
Chris@316 493 void
Chris@316 494 Layer::toBriefXml(QTextStream &stream,
Chris@316 495 QString indent, QString extraAttributes) const
Chris@269 496 {
Chris@316 497 stream << indent;
Chris@269 498
Chris@316 499 stream << QString("<layer id=\"%2\" type=\"%1\" name=\"%3\" model=\"%4\" %5/>\n")
Chris@269 500 .arg(encodeEntities(LayerFactory::getInstance()->getLayerTypeName
Chris@269 501 (LayerFactory::getInstance()->getLayerType(this))))
Chris@269 502 .arg(getObjectExportId(this))
Chris@269 503 .arg(encodeEntities(objectName()))
Chris@269 504 .arg(getObjectExportId(getModel()))
Chris@269 505 .arg(extraAttributes);
Chris@269 506 }
Chris@269 507