annotate layer/Layer.cpp @ 269:7b58c5e91f20

* save/reload measurements in session
author Chris Cannam
date Tue, 26 Jun 2007 12:27:47 +0000
parents 70537b0434c4
children 61a704654497
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@267 29 Layer::Layer() :
Chris@267 30 m_haveDraggingRect(false)
Chris@127 31 {
Chris@127 32 }
Chris@127 33
Chris@127 34 Layer::~Layer()
Chris@127 35 {
Chris@127 36 // std::cerr << "Layer::~Layer(" << this << ")" << std::endl;
Chris@127 37 }
Chris@127 38
Chris@127 39 QString
Chris@127 40 Layer::getPropertyContainerIconName() const
Chris@127 41 {
Chris@127 42 return LayerFactory::getInstance()->getLayerIconName
Chris@127 43 (LayerFactory::getInstance()->getLayerType(this));
Chris@127 44 }
Chris@127 45
Chris@127 46 QString
Chris@127 47 Layer::getLayerPresentationName() const
Chris@127 48 {
Chris@203 49 // QString layerName = objectName();
Chris@203 50
Chris@203 51 LayerFactory *factory = LayerFactory::getInstance();
Chris@203 52 QString layerName = factory->getLayerPresentationName
Chris@203 53 (factory->getLayerType(this));
Chris@203 54
Chris@127 55 QString modelName;
Chris@127 56 if (getModel()) modelName = getModel()->objectName();
Chris@127 57
Chris@127 58 QString text;
Chris@127 59 if (modelName != "") {
Chris@127 60 text = QString("%1: %2").arg(modelName).arg(layerName);
Chris@127 61 } else {
Chris@127 62 text = layerName;
Chris@127 63 }
Chris@127 64
Chris@127 65 return text;
Chris@127 66 }
Chris@127 67
Chris@127 68 void
Chris@127 69 Layer::setObjectName(const QString &name)
Chris@127 70 {
Chris@127 71 QObject::setObjectName(name);
Chris@127 72 emit layerNameChanged();
Chris@127 73 }
Chris@127 74
Chris@127 75 PlayParameters *
Chris@127 76 Layer::getPlayParameters()
Chris@127 77 {
Chris@127 78 // std::cerr << "Layer (" << this << ", " << objectName().toStdString() << ")::getPlayParameters: model is "<< getModel() << std::endl;
Chris@127 79 const Model *model = getModel();
Chris@127 80 if (model) {
Chris@127 81 return PlayParameterRepository::getInstance()->getPlayParameters(model);
Chris@127 82 }
Chris@127 83 return 0;
Chris@127 84 }
Chris@127 85
Chris@127 86 void
Chris@131 87 Layer::setLayerDormant(const View *v, bool dormant)
Chris@131 88 {
Chris@131 89 const void *vv = (const void *)v;
Chris@131 90 QMutexLocker locker(&m_dormancyMutex);
Chris@131 91 m_dormancy[vv] = dormant;
Chris@131 92 }
Chris@131 93
Chris@131 94 bool
Chris@131 95 Layer::isLayerDormant(const View *v) const
Chris@131 96 {
Chris@131 97 const void *vv = (const void *)v;
Chris@131 98 QMutexLocker locker(&m_dormancyMutex);
Chris@131 99 if (m_dormancy.find(vv) == m_dormancy.end()) return false;
Chris@131 100 return m_dormancy.find(vv)->second;
Chris@131 101 }
Chris@131 102
Chris@131 103 void
Chris@127 104 Layer::showLayer(View *view, bool show)
Chris@127 105 {
Chris@127 106 setLayerDormant(view, !show);
Chris@127 107 emit layerParametersChanged();
Chris@127 108 }
Chris@127 109
Chris@260 110 bool
Chris@267 111 Layer::getXScaleValue(const View *v, int x, float &value, QString &unit) const
Chris@260 112 {
Chris@260 113 if (!hasTimeXAxis()) return false;
Chris@260 114
Chris@260 115 const Model *m = getModel();
Chris@260 116 if (!m) return false;
Chris@260 117
Chris@260 118 value = float(v->getFrameForX(x)) / m->getSampleRate();
Chris@260 119 unit = "s";
Chris@260 120 return true;
Chris@260 121 }
Chris@260 122
Chris@268 123 bool
Chris@268 124 Layer::MeasureRect::operator<(const MeasureRect &mr) const
Chris@268 125 {
Chris@268 126 if (haveFrames) {
Chris@268 127 if (startFrame == mr.startFrame) {
Chris@268 128 if (endFrame != mr.endFrame) {
Chris@268 129 return endFrame < mr.endFrame;
Chris@268 130 }
Chris@268 131 } else {
Chris@268 132 return startFrame < mr.startFrame;
Chris@268 133 }
Chris@268 134 } else {
Chris@268 135 if (pixrect.x() == mr.pixrect.x()) {
Chris@268 136 if (pixrect.width() != mr.pixrect.width()) {
Chris@268 137 return pixrect.width() < mr.pixrect.width();
Chris@268 138 }
Chris@268 139 } else {
Chris@268 140 return pixrect.x() < mr.pixrect.x();
Chris@268 141 }
Chris@268 142 }
Chris@268 143
Chris@268 144 // the two rects are equal in x and width
Chris@268 145
Chris@268 146 if (pixrect.y() == mr.pixrect.y()) {
Chris@268 147 return pixrect.height() < mr.pixrect.height();
Chris@268 148 } else {
Chris@268 149 return pixrect.y() < mr.pixrect.y();
Chris@268 150 }
Chris@268 151 }
Chris@268 152
Chris@268 153 QString
Chris@269 154 Layer::MeasureRect::toXmlString(QString indent) const
Chris@269 155 {
Chris@269 156 QString s;
Chris@269 157
Chris@269 158 s += indent;
Chris@269 159 s += QString("<measurement ");
Chris@269 160
Chris@269 161 if (haveFrames) {
Chris@269 162 s += QString("startFrame=\"%1\" endFrame=\"%2\" ")
Chris@269 163 .arg(startFrame).arg(endFrame);
Chris@269 164 } else {
Chris@269 165 s += QString("startX=\"%1\" endX=\"%2\" ")
Chris@269 166 .arg(pixrect.x()).arg(pixrect.x() + pixrect.width());
Chris@269 167 }
Chris@269 168
Chris@269 169 s += QString("startY=\"%1\" endY=\"%2\"/>\n")
Chris@269 170 .arg(pixrect.y()).arg(pixrect.y() + pixrect.height());
Chris@269 171
Chris@269 172 return s;
Chris@269 173 }
Chris@269 174
Chris@269 175 void
Chris@269 176 Layer::addMeasurementRect(const QXmlAttributes &attributes)
Chris@269 177 {
Chris@269 178 MeasureRect rect;
Chris@269 179 QString fs = attributes.value("startFrame");
Chris@269 180 int x0 = 0, y0 = 0, x1 = 0, y1 = 0;
Chris@269 181 if (fs != "") {
Chris@269 182 rect.startFrame = fs.toLong();
Chris@269 183 rect.endFrame = attributes.value("endFrame").toLong();
Chris@269 184 rect.haveFrames = true;
Chris@269 185 } else {
Chris@269 186 x0 = attributes.value("startX").toInt();
Chris@269 187 x1 = attributes.value("endX").toInt();
Chris@269 188 rect.haveFrames = false;
Chris@269 189 }
Chris@269 190 y0 = attributes.value("startY").toInt();
Chris@269 191 y1 = attributes.value("endY").toInt();
Chris@269 192 rect.pixrect = QRect(x0, y0, x1 - x0, y1 - y0);
Chris@269 193 addMeasureRectToSet(rect);
Chris@269 194 }
Chris@269 195
Chris@269 196 QString
Chris@268 197 Layer::AddMeasurementRectCommand::getName() const
Chris@268 198 {
Chris@268 199 return tr("Make Measurement");
Chris@268 200 }
Chris@268 201
Chris@268 202 void
Chris@268 203 Layer::AddMeasurementRectCommand::execute()
Chris@268 204 {
Chris@269 205 m_layer->addMeasureRectToSet(m_rect);
Chris@268 206 }
Chris@268 207
Chris@268 208 void
Chris@268 209 Layer::AddMeasurementRectCommand::unexecute()
Chris@268 210 {
Chris@269 211 m_layer->deleteMeasureRectFromSet(m_rect);
Chris@268 212 }
Chris@268 213
Chris@267 214 void
Chris@267 215 Layer::measureStart(View *v, QMouseEvent *e)
Chris@267 216 {
Chris@267 217 m_draggingRect.pixrect = QRect(e->x(), e->y(), 0, 0);
Chris@267 218 if (hasTimeXAxis()) {
Chris@268 219 m_draggingRect.haveFrames = true;
Chris@267 220 m_draggingRect.startFrame = v->getFrameForX(e->x());
Chris@267 221 m_draggingRect.endFrame = m_draggingRect.startFrame;
Chris@268 222 } else {
Chris@268 223 m_draggingRect.haveFrames = false;
Chris@267 224 }
Chris@267 225 m_haveDraggingRect = true;
Chris@267 226 }
Chris@267 227
Chris@267 228 void
Chris@267 229 Layer::measureDrag(View *v, QMouseEvent *e)
Chris@267 230 {
Chris@267 231 if (!m_haveDraggingRect) return;
Chris@268 232
Chris@267 233 m_draggingRect.pixrect = QRect(m_draggingRect.pixrect.x(),
Chris@267 234 m_draggingRect.pixrect.y(),
Chris@267 235 e->x() - m_draggingRect.pixrect.x(),
Chris@268 236 e->y() - m_draggingRect.pixrect.y())
Chris@268 237 .normalized();
Chris@268 238
Chris@267 239 if (hasTimeXAxis()) {
Chris@267 240 m_draggingRect.endFrame = v->getFrameForX(e->x());
Chris@267 241 }
Chris@267 242 }
Chris@267 243
Chris@267 244 void
Chris@267 245 Layer::measureEnd(View *v, QMouseEvent *e)
Chris@267 246 {
Chris@267 247 if (!m_haveDraggingRect) return;
Chris@267 248 measureDrag(v, e);
Chris@268 249
Chris@268 250 CommandHistory::getInstance()->addCommand
Chris@268 251 (new AddMeasurementRectCommand(this, m_draggingRect));
Chris@268 252
Chris@267 253 m_haveDraggingRect = false;
Chris@267 254 }
Chris@267 255
Chris@267 256 void
Chris@267 257 Layer::paintMeasurementRects(View *v, QPainter &paint) const
Chris@267 258 {
Chris@267 259 if (m_haveDraggingRect) {
Chris@268 260 paintMeasurementRect(v, paint, m_draggingRect);
Chris@267 261 }
Chris@267 262
Chris@268 263 for (MeasureRectSet::const_iterator i = m_measureRects.begin();
Chris@268 264 i != m_measureRects.end(); ++i) {
Chris@268 265 paintMeasurementRect(v, paint, *i);
Chris@267 266 }
Chris@267 267 }
Chris@267 268
Chris@268 269 void
Chris@269 270 Layer::paintMeasurementRect(View *v, QPainter &paint, const MeasureRect &r) const
Chris@268 271 {
Chris@268 272 if (r.haveFrames) {
Chris@268 273
Chris@268 274 int x0 = -1;
Chris@268 275 int x1 = v->width() + 1;
Chris@268 276
Chris@268 277 if (r.startFrame >= v->getStartFrame()) {
Chris@268 278 x0 = v->getXForFrame(r.startFrame);
Chris@268 279 }
Chris@268 280 if (r.endFrame <= v->getEndFrame()) {
Chris@268 281 x1 = v->getXForFrame(r.endFrame);
Chris@268 282 }
Chris@268 283
Chris@268 284 QRect pr = QRect(x0, r.pixrect.y(),
Chris@268 285 x1 - x0, r.pixrect.height());
Chris@268 286
Chris@268 287 r.pixrect = pr;
Chris@268 288 }
Chris@268 289
Chris@268 290 v->drawMeasurementRect(paint, this, r.pixrect);
Chris@268 291 }
Chris@268 292
Chris@268 293 QString
Chris@268 294 Layer::toXmlString(QString indent, QString extraAttributes) const
Chris@268 295 {
Chris@268 296 QString s;
Chris@268 297
Chris@268 298 s += indent;
Chris@268 299
Chris@269 300 s += QString("<layer id=\"%2\" type=\"%1\" name=\"%3\" model=\"%4\" %5")
Chris@268 301 .arg(encodeEntities(LayerFactory::getInstance()->getLayerTypeName
Chris@268 302 (LayerFactory::getInstance()->getLayerType(this))))
Chris@268 303 .arg(getObjectExportId(this))
Chris@268 304 .arg(encodeEntities(objectName()))
Chris@268 305 .arg(getObjectExportId(getModel()))
Chris@268 306 .arg(extraAttributes);
Chris@268 307
Chris@269 308 if (m_measureRects.empty()) {
Chris@269 309 s += QString("/>\n");
Chris@269 310 return s;
Chris@269 311 }
Chris@269 312
Chris@269 313 s += QString(">\n");
Chris@269 314
Chris@269 315 for (MeasureRectSet::const_iterator i = m_measureRects.begin();
Chris@269 316 i != m_measureRects.end(); ++i) {
Chris@269 317 s += i->toXmlString(indent + " ");
Chris@269 318 }
Chris@269 319
Chris@269 320 s += QString("</layer>\n");
Chris@269 321
Chris@268 322 return s;
Chris@268 323 }
Chris@269 324
Chris@269 325 QString
Chris@269 326 Layer::toBriefXmlString(QString indent, QString extraAttributes) const
Chris@269 327 {
Chris@269 328 QString s;
Chris@269 329
Chris@269 330 s += indent;
Chris@269 331
Chris@269 332 s += QString("<layer id=\"%2\" type=\"%1\" name=\"%3\" model=\"%4\" %5/>\n")
Chris@269 333 .arg(encodeEntities(LayerFactory::getInstance()->getLayerTypeName
Chris@269 334 (LayerFactory::getInstance()->getLayerType(this))))
Chris@269 335 .arg(getObjectExportId(this))
Chris@269 336 .arg(encodeEntities(objectName()))
Chris@269 337 .arg(getObjectExportId(getModel()))
Chris@269 338 .arg(extraAttributes);
Chris@269 339
Chris@269 340 return s;
Chris@269 341 }
Chris@269 342