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