annotate layer/Layer.cpp @ 312:6de6f78b13a1

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