annotate layer/IntervalLayer.cpp @ 282:d9319859a4cf tip

(none)
author benoitrigolleau
date Fri, 31 Oct 2008 11:00:24 +0000
parents 66af7c1b10d9
children
rev   line source
lbajardsilogic@18 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
lbajardsilogic@18 2
lbajardsilogic@18 3 /*
lbajardsilogic@18 4 Sound Access
lbajardsilogic@18 5 EASAIER client application.
lbajardsilogic@18 6 Silogic 2007. Luc Barthélémy.
lbajardsilogic@18 7
lbajardsilogic@18 8 This program is free software; you can redistribute it and/or
lbajardsilogic@18 9 modify it under the terms of the GNU General Public License as
lbajardsilogic@18 10 published by the Free Software Foundation; either version 2 of the
lbajardsilogic@18 11 License, or (at your option) any later version. See the file
lbajardsilogic@18 12 COPYING included with this distribution for more information.
lbajardsilogic@18 13 */
lbajardsilogic@18 14
lbajardsilogic@18 15 #include <QObject>
lbajardsilogic@18 16 #include <QColor>
lbajardsilogic@18 17 #include <QPainter>
lbajardsilogic@18 18 #include <QMouseEvent>
lbajardsilogic@18 19 #include <QInputDialog>
lbajardsilogic@18 20
lbajardsilogic@18 21 #include "layer/IntervalLayer.h"
lbajardsilogic@18 22 #include "view/View.h"
lbajardsilogic@18 23 #include "system/System.h"
lbajardsilogic@18 24 #include "widgets/ItemEditDialog.h"
lbajardsilogic@18 25
lbajardsilogic@18 26
lbajardsilogic@18 27 const int gIntervalHeight = 30;
lbajardsilogic@18 28
lbajardsilogic@18 29 //****************************************************************
lbajardsilogic@18 30 //* Function: Constructor
lbajardsilogic@18 31 //* Description: declaration and initialisation of all private parameters
lbajardsilogic@18 32 //****************************************************************
lbajardsilogic@18 33 IntervalLayer::IntervalLayer():
lbajardsilogic@18 34 Layer(),
lbajardsilogic@18 35 m_model(0),
lbajardsilogic@18 36 m_editing(false),
lbajardsilogic@18 37 m_colour(Qt::darkRed),
lbajardsilogic@18 38 m_editingCommand(0)
lbajardsilogic@18 39 {
lbajardsilogic@18 40 }
lbajardsilogic@18 41
lbajardsilogic@18 42 IntervalLayer::~IntervalLayer()
lbajardsilogic@18 43 {}
lbajardsilogic@18 44
lbajardsilogic@18 45 void IntervalLayer::setModel(IntervalModel* model)
lbajardsilogic@18 46 {
lbajardsilogic@18 47 if (m_model == model) return;
lbajardsilogic@18 48 m_model = model;
lbajardsilogic@18 49
lbajardsilogic@18 50 connect(m_model, SIGNAL(modelChanged()), this, SIGNAL(modelChanged()));
lbajardsilogic@18 51 connect(m_model, SIGNAL(modelChanged(size_t, size_t)),
lbajardsilogic@18 52 this, SIGNAL(modelChanged(size_t, size_t)));
lbajardsilogic@18 53
lbajardsilogic@18 54 connect(m_model, SIGNAL(completionChanged()),
lbajardsilogic@18 55 this, SIGNAL(modelCompletionChanged()));
lbajardsilogic@18 56
lbajardsilogic@18 57 emit modelReplaced();
lbajardsilogic@18 58 }
lbajardsilogic@18 59
lbajardsilogic@18 60 Layer::PropertyList
lbajardsilogic@18 61 IntervalLayer::getProperties() const
lbajardsilogic@18 62 {
lbajardsilogic@18 63 PropertyList list;
lbajardsilogic@18 64 list.push_back("Colour");
lbajardsilogic@18 65 return list;
lbajardsilogic@18 66 }
lbajardsilogic@18 67
lbajardsilogic@18 68 Layer::PropertyType
lbajardsilogic@18 69 IntervalLayer::getPropertyType(const PropertyName &name) const
lbajardsilogic@18 70 {
lbajardsilogic@18 71 return ValueProperty;
lbajardsilogic@18 72 }
lbajardsilogic@18 73
lbajardsilogic@18 74 int
lbajardsilogic@18 75 IntervalLayer::getPropertyRangeAndValue(const PropertyName &name,
lbajardsilogic@18 76 int *min, int *max, int *deflt) const
lbajardsilogic@18 77 {
lbajardsilogic@18 78 //!!! factor this colour handling stuff out into a colour manager class
lbajardsilogic@18 79 int val = 0;
lbajardsilogic@18 80
lbajardsilogic@18 81 if (name == "Colour") {
lbajardsilogic@18 82
lbajardsilogic@18 83 if (min) *min = 0;
lbajardsilogic@18 84 if (max) *max = 5;
lbajardsilogic@18 85 if (deflt) *deflt = 0;
lbajardsilogic@18 86
lbajardsilogic@18 87 if (m_colour == Qt::black) val = 0;
lbajardsilogic@18 88 else if (m_colour == Qt::darkRed) val = 1;
lbajardsilogic@18 89 else if (m_colour == Qt::darkBlue) val = 2;
lbajardsilogic@18 90 else if (m_colour == Qt::darkGreen) val = 3;
lbajardsilogic@18 91 else if (m_colour == QColor(200, 50, 255)) val = 4;
lbajardsilogic@18 92 else if (m_colour == QColor(255, 150, 50)) val = 5;
lbajardsilogic@18 93 }
lbajardsilogic@18 94
lbajardsilogic@18 95 return val;
lbajardsilogic@18 96 }
lbajardsilogic@18 97
lbajardsilogic@18 98 QString
lbajardsilogic@18 99 IntervalLayer::getPropertyValueLabel(const PropertyName &name,
lbajardsilogic@18 100 int value) const
lbajardsilogic@18 101 {
lbajardsilogic@18 102 if (name == "Colour") {
lbajardsilogic@18 103 switch (value) {
lbajardsilogic@18 104 default:
lbajardsilogic@18 105 case 0: return tr("Black");
lbajardsilogic@18 106 case 1: return tr("Red");
lbajardsilogic@18 107 case 2: return tr("Blue");
lbajardsilogic@18 108 case 3: return tr("Green");
lbajardsilogic@18 109 case 4: return tr("Purple");
lbajardsilogic@18 110 case 5: return tr("Orange");
lbajardsilogic@18 111 }
lbajardsilogic@18 112 }
lbajardsilogic@18 113 return tr("<unknown>");
lbajardsilogic@18 114 }
lbajardsilogic@18 115
lbajardsilogic@18 116
lbajardsilogic@18 117 void IntervalLayer::setProperties(const QXmlAttributes &attributes)
lbajardsilogic@18 118 {
lbajardsilogic@18 119 QString colourSpec = attributes.value("colour");
lbajardsilogic@18 120 if (colourSpec != "") {
lbajardsilogic@18 121 QColor colour(colourSpec);
lbajardsilogic@18 122 if (colour.isValid()) {
lbajardsilogic@18 123 setBaseColour(QColor(colourSpec));
lbajardsilogic@18 124 }
lbajardsilogic@18 125 }
lbajardsilogic@18 126
lbajardsilogic@18 127 }
lbajardsilogic@18 128
lbajardsilogic@18 129 void
lbajardsilogic@18 130 IntervalLayer::setProperty(const PropertyName &name, int value)
lbajardsilogic@18 131 {
lbajardsilogic@18 132 if (name == "Colour") {
lbajardsilogic@18 133 switch (value) {
lbajardsilogic@18 134 default:
lbajardsilogic@18 135 case 0: setBaseColour(Qt::black); break;
lbajardsilogic@18 136 case 1: setBaseColour(Qt::darkRed); break;
lbajardsilogic@18 137 case 2: setBaseColour(Qt::darkBlue); break;
lbajardsilogic@18 138 case 3: setBaseColour(Qt::darkGreen); break;
lbajardsilogic@18 139 case 4: setBaseColour(QColor(200, 50, 255)); break;
lbajardsilogic@18 140 case 5: setBaseColour(QColor(255, 150, 50)); break;
lbajardsilogic@18 141 }
lbajardsilogic@18 142 }
lbajardsilogic@18 143 }
lbajardsilogic@18 144
lbajardsilogic@18 145 void
lbajardsilogic@18 146 IntervalLayer::setBaseColour(QColor colour)
lbajardsilogic@18 147 {
lbajardsilogic@18 148 if (m_colour == colour) return;
lbajardsilogic@18 149 m_colour = colour;
lbajardsilogic@18 150 emit layerParametersChanged();
lbajardsilogic@18 151 }
lbajardsilogic@18 152
lbajardsilogic@18 153 QString
lbajardsilogic@18 154 IntervalLayer::toXmlString(QString indent, QString extraAttributes) const
lbajardsilogic@18 155 {
lbajardsilogic@18 156 return Layer::toXmlString(indent, extraAttributes +
lbajardsilogic@18 157 QString(" colour=\"%1\"")
lbajardsilogic@18 158 .arg(encodeColour(m_colour)));
lbajardsilogic@18 159 }
lbajardsilogic@18 160
lbajardsilogic@18 161 QString
lbajardsilogic@18 162 IntervalLayer::toEasaierXmlString(QString indent, QString extraAttributes) const
lbajardsilogic@18 163 {
lbajardsilogic@18 164 return Layer::toEasaierXmlString(indent, extraAttributes +
lbajardsilogic@18 165 QString(" colour=\"%1\"")
lbajardsilogic@18 166 .arg(encodeColour(m_colour)));
lbajardsilogic@18 167 }
lbajardsilogic@18 168
lbajardsilogic@18 169 QString
lbajardsilogic@18 170 IntervalLayer::getPropertyLabel(const PropertyName &name) const
lbajardsilogic@18 171 {
lbajardsilogic@18 172 if (name == "Colour") return tr("Colour");
lbajardsilogic@18 173 return "";
lbajardsilogic@18 174 }
lbajardsilogic@18 175
lbajardsilogic@18 176 int
lbajardsilogic@18 177 IntervalLayer::getYForHeight(View *v, float height) const
lbajardsilogic@18 178 {
lbajardsilogic@18 179 int h = v->height();
lbajardsilogic@18 180 return h - int(height * h);
lbajardsilogic@18 181 }
lbajardsilogic@18 182
lbajardsilogic@18 183 float
lbajardsilogic@18 184 IntervalLayer::getHeightForY(View *v, int y) const
lbajardsilogic@18 185 {
lbajardsilogic@18 186 int h = v->height();
lbajardsilogic@18 187 return float(h - y) / h;
lbajardsilogic@18 188 }
lbajardsilogic@18 189
lbajardsilogic@18 190
lbajardsilogic@18 191 void
lbajardsilogic@18 192 IntervalLayer::paint(View *v, QPainter &paint, QRect rect) const
lbajardsilogic@18 193 {
lbajardsilogic@18 194 if (!m_model || !m_model->isOK()) return;
lbajardsilogic@18 195
lbajardsilogic@18 196 int sampleRate = m_model->getSampleRate();
lbajardsilogic@18 197 if (!sampleRate) return;
lbajardsilogic@18 198
lbajardsilogic@18 199 int x0 = rect.left(), x1 = rect.right();
lbajardsilogic@18 200 long frame0 = v->getFrameForX(x0);
lbajardsilogic@18 201 long frame1 = v->getFrameForX(x1);
lbajardsilogic@18 202
lbajardsilogic@18 203 paint.save();
lbajardsilogic@18 204
lbajardsilogic@18 205 QColor brushColour(m_colour);
lbajardsilogic@18 206 brushColour.setAlpha(100);
lbajardsilogic@18 207 QColor penColour = Qt::black;
lbajardsilogic@18 208
lbajardsilogic@18 209 paint.setPen(m_colour);
lbajardsilogic@18 210
lbajardsilogic@18 211 IntervalList& intervals = m_model->intervals();
lbajardsilogic@18 212
lbajardsilogic@18 213 int xS,xE,y;
lbajardsilogic@18 214 bool draw, drawText, drawStart, drawEnd;
lbajardsilogic@18 215
lbajardsilogic@18 216 QPoint localPos;
lbajardsilogic@18 217 long illuminateX = -1;
lbajardsilogic@18 218
lbajardsilogic@18 219 if (v->shouldIlluminateLocalFeatures(this, localPos)) {
lbajardsilogic@18 220 // should highlight one endpoint ?
lbajardsilogic@18 221 illuminateX = localPos.x();
lbajardsilogic@18 222 }
lbajardsilogic@18 223
lbajardsilogic@18 224 for (IntervalListConstIterator i = intervals.begin(); i != intervals.end(); ++i)
lbajardsilogic@18 225 {
lbajardsilogic@18 226 draw = drawText = drawStart = drawEnd = false;
lbajardsilogic@18 227
lbajardsilogic@18 228 TimeIntervalPtr ti = (*i);
lbajardsilogic@18 229
lbajardsilogic@18 230 if (ti->start() >= frame0 && ti->start() < frame1)
lbajardsilogic@18 231 {
lbajardsilogic@18 232 xS = v->getXForFrame(ti->start());
lbajardsilogic@18 233 xE = v->getXForFrame(ti->end());
lbajardsilogic@18 234 if (xE <= x1)
lbajardsilogic@18 235 drawEnd = true;
lbajardsilogic@18 236 else
lbajardsilogic@18 237 xE = x1;
lbajardsilogic@18 238 draw = drawText = drawStart = true;
lbajardsilogic@18 239 }
ivand_qmul@125 240 else if (ti->end() > frame0 && ti->end() <= frame1)
lbajardsilogic@18 241 {
lbajardsilogic@18 242 xS = v->getXForFrame(ti->start());
lbajardsilogic@18 243 if (xS < x0)
lbajardsilogic@18 244 xS = x0;
lbajardsilogic@18 245 xE = v->getXForFrame(ti->end());
lbajardsilogic@18 246 draw = drawEnd = true;
lbajardsilogic@18 247 }
ivand_qmul@125 248 else if (ti->start() <= frame0 && ti->end() >= frame1)
lbajardsilogic@18 249 {
lbajardsilogic@18 250 xS = x0;
lbajardsilogic@18 251 xE = x1;
lbajardsilogic@18 252 draw = true;
lbajardsilogic@18 253 }
lbajardsilogic@18 254 if (draw)
lbajardsilogic@18 255 {
lbajardsilogic@18 256 y = getYForHeight(v, ti->value());
lbajardsilogic@18 257 paint.setBrush(brushColour);
lbajardsilogic@18 258 paint.fillRect(xS, y-gIntervalHeight/2, (xE-xS+1), gIntervalHeight, brushColour);
lbajardsilogic@18 259 }
lbajardsilogic@18 260 if (drawStart)
lbajardsilogic@18 261 {
lbajardsilogic@18 262 if (abs(illuminateX - xS) < 3)
lbajardsilogic@18 263 paint.setPen(Qt::black);
lbajardsilogic@18 264 else
lbajardsilogic@18 265 paint.setPen(brushColour);
lbajardsilogic@18 266 paint.drawLine(xS, 0, xS, v->height() - 1);
lbajardsilogic@18 267 }
lbajardsilogic@18 268 if (drawEnd)
lbajardsilogic@18 269 {
lbajardsilogic@18 270 if (abs (illuminateX - xE) < 3)
lbajardsilogic@18 271 paint.setPen(Qt::black);
lbajardsilogic@18 272 else
lbajardsilogic@18 273 paint.setPen(brushColour);
lbajardsilogic@18 274 paint.drawLine(xE, 0, xE, v->height() - 1);
lbajardsilogic@18 275 }
lbajardsilogic@18 276 if (drawText)
lbajardsilogic@18 277 {
lbajardsilogic@18 278 paint.setPen(penColour);
lbajardsilogic@18 279 paint.drawText(xS+10, y, ti->label());
lbajardsilogic@18 280 }
lbajardsilogic@18 281 }
lbajardsilogic@18 282
lbajardsilogic@18 283 paint.restore();
lbajardsilogic@18 284 }
lbajardsilogic@18 285
lbajardsilogic@18 286
lbajardsilogic@18 287 bool
lbajardsilogic@18 288 IntervalLayer::getValueExtents(float &min, float &max,
lbajardsilogic@18 289 bool &logarithmic, QString &unit) const
lbajardsilogic@18 290 {
lbajardsilogic@18 291 return false;
lbajardsilogic@18 292 }
lbajardsilogic@18 293
lbajardsilogic@18 294 IntervalList
lbajardsilogic@18 295 IntervalLayer::getIntervalAt(View *v, int x, int y) // y < 0 means you don't make any test on it
lbajardsilogic@18 296 {
lbajardsilogic@18 297 IntervalList result;
lbajardsilogic@18 298 IntervalList& intervals = m_model->intervals();
lbajardsilogic@18 299
lbajardsilogic@18 300 for (IntervalListIterator i = intervals.begin(); i != intervals.end(); ++i)
lbajardsilogic@18 301 {
lbajardsilogic@18 302 TimeIntervalPtr ti = (*i);
lbajardsilogic@18 303
lbajardsilogic@18 304 int yT = getYForHeight(v, ti->value());
lbajardsilogic@18 305 int xS = v->getXForFrame(ti->start());
lbajardsilogic@18 306 int xE = v->getXForFrame(ti->end());
lbajardsilogic@18 307 if ((x >= xS) && (x <= xE))
lbajardsilogic@18 308 {
lbajardsilogic@18 309 if ((y < 0) || (abs(y - yT) <= gIntervalHeight/2))
lbajardsilogic@18 310 result.push_back(ti);
lbajardsilogic@18 311 }
lbajardsilogic@18 312 }
lbajardsilogic@18 313
lbajardsilogic@18 314 return result;
lbajardsilogic@18 315 }
lbajardsilogic@18 316
lbajardsilogic@18 317 IntervalList
lbajardsilogic@18 318 IntervalLayer::getInterval(long start, long end)
lbajardsilogic@18 319 {
lbajardsilogic@18 320 IntervalList result;
lbajardsilogic@18 321 IntervalList& intervals = m_model->intervals();
lbajardsilogic@18 322
lbajardsilogic@18 323 for (IntervalListIterator i = intervals.begin(); i != intervals.end(); ++i)
lbajardsilogic@18 324 {
lbajardsilogic@18 325 TimeIntervalPtr ti = (*i);
lbajardsilogic@18 326
lbajardsilogic@18 327 if ( (start <= ti->start()) && (ti->start() <= end) &&
lbajardsilogic@18 328 (start <= ti->end()) && (ti->end() <= end) )
lbajardsilogic@18 329 {
lbajardsilogic@18 330 result.push_back(ti);
lbajardsilogic@18 331 }
lbajardsilogic@18 332 }
lbajardsilogic@18 333
lbajardsilogic@18 334 return result;
lbajardsilogic@18 335 }
lbajardsilogic@18 336
lbajardsilogic@18 337 QString
lbajardsilogic@18 338 IntervalLayer::getFeatureDescription(View *v, QPoint& pos) const
lbajardsilogic@18 339 {
lbajardsilogic@18 340 if (!m_model || !m_model->getSampleRate()) return "";
lbajardsilogic@18 341
lbajardsilogic@18 342 QString description;
lbajardsilogic@18 343
lbajardsilogic@18 344 int x = pos.x();
lbajardsilogic@18 345 int y = pos.y();
lbajardsilogic@18 346
lbajardsilogic@18 347 long frame = v->getFrameForX(x);
lbajardsilogic@18 348
lbajardsilogic@18 349 IntervalList& intervals = m_model->intervals();
lbajardsilogic@18 350 for (IntervalListConstIterator i = intervals.begin(); i != intervals.end(); ++i)
lbajardsilogic@18 351 {
lbajardsilogic@18 352 TimeIntervalPtr ti = (*i);
lbajardsilogic@18 353
lbajardsilogic@18 354 if (ti->start() <= frame && ti->end() >= frame)
lbajardsilogic@18 355 {
lbajardsilogic@18 356 int y = getYForHeight(v, ti->value());
lbajardsilogic@18 357
lbajardsilogic@18 358 if (abs(y - pos.y()) <= gIntervalHeight/2)
lbajardsilogic@18 359 {
lbajardsilogic@18 360 RealTime rtStart = RealTime::frame2RealTime(ti->start(), m_model->getSampleRate());
lbajardsilogic@18 361 RealTime rtEnd = RealTime::frame2RealTime(ti->end(), m_model->getSampleRate());
lbajardsilogic@18 362 RealTime rtDuration = rtEnd - rtStart;
lbajardsilogic@18 363
lbajardsilogic@18 364 description = QString(tr("Interval:\t%1\nStart:\t%2 End:\t%3\tDuration:\t%4"))
lbajardsilogic@18 365 .arg(ti->label())
lbajardsilogic@18 366 .arg(rtStart.toText(true).c_str())
lbajardsilogic@18 367 .arg(rtEnd.toText(true).c_str())
lbajardsilogic@18 368 .arg(rtDuration.toText(true).c_str());
lbajardsilogic@18 369 break;
lbajardsilogic@18 370 }
lbajardsilogic@18 371 }
lbajardsilogic@18 372 }
lbajardsilogic@18 373
lbajardsilogic@18 374 return description;
lbajardsilogic@18 375 }
lbajardsilogic@18 376
lbajardsilogic@18 377
lbajardsilogic@18 378 void
lbajardsilogic@18 379 IntervalLayer::drawStart(View *v, QMouseEvent *e)
lbajardsilogic@18 380 {
lbajardsilogic@18 381 if (!m_model) {
lbajardsilogic@18 382 std::cerr << "IntervalLayer::drawStart: no model" << std::endl;
lbajardsilogic@18 383 return;
lbajardsilogic@18 384 }
lbajardsilogic@18 385
lbajardsilogic@18 386 long frame = v->getFrameForX(e->x());
lbajardsilogic@18 387
lbajardsilogic@18 388 if (frame < 0)
lbajardsilogic@18 389 frame = 0;
lbajardsilogic@18 390
lbajardsilogic@18 391 frame = frame / m_model->getResolution() * m_model->getResolution();
lbajardsilogic@18 392
lbajardsilogic@18 393 int height = (int) (getHeightForY(v, e->y())*100+0.5);
lbajardsilogic@18 394 float value = ((float) height)/100;
lbajardsilogic@18 395
lbajardsilogic@18 396 m_editingInterval = new TimeInterval(frame, frame, "", value);
lbajardsilogic@18 397
lbajardsilogic@18 398 m_model->addInterval(m_editingInterval);
lbajardsilogic@18 399
lbajardsilogic@18 400 if (m_editingCommand)
lbajardsilogic@18 401 {
lbajardsilogic@18 402 CommandHistory::getInstance()->addCommand(m_editingCommand, false);
lbajardsilogic@18 403 m_editingCommand = 0;
lbajardsilogic@18 404 }
lbajardsilogic@18 405
lbajardsilogic@18 406 m_editingCommand = new IntervalModel::IntervalCommand(m_model, m_editingInterval,
lbajardsilogic@18 407 IntervalModel::IntervalCommand::Creation ,
lbajardsilogic@18 408 frame, frame, value, "");
lbajardsilogic@18 409
lbajardsilogic@18 410 m_editing = 1;
lbajardsilogic@18 411 }
lbajardsilogic@18 412
lbajardsilogic@18 413 void
lbajardsilogic@18 414 IntervalLayer::drawDrag(View *v, QMouseEvent *e)
lbajardsilogic@18 415 {
lbajardsilogic@18 416 if (!m_model || !m_editing) return;
lbajardsilogic@18 417
lbajardsilogic@18 418 long frame = v->getFrameForX(e->x());
lbajardsilogic@18 419
lbajardsilogic@18 420 if (frame < 0)
lbajardsilogic@18 421 frame = 0;
lbajardsilogic@18 422
lbajardsilogic@18 423 frame = frame / m_model->getResolution() * m_model->getResolution();
lbajardsilogic@18 424
lbajardsilogic@18 425 long start = m_editingInterval->start();
lbajardsilogic@18 426 long end = frame;
lbajardsilogic@18 427
lbajardsilogic@18 428 if (start < end)
lbajardsilogic@18 429 {
lbajardsilogic@18 430 m_editing = 2;
lbajardsilogic@18 431 m_editingInterval->end(frame);
lbajardsilogic@18 432 m_editingCommand->newEnd(frame);
lbajardsilogic@18 433 } else {
lbajardsilogic@18 434 m_editing = 1;
lbajardsilogic@18 435 m_editingInterval->start(frame);
lbajardsilogic@18 436 m_editingCommand->newStart(frame);
lbajardsilogic@18 437 }
lbajardsilogic@18 438 }
lbajardsilogic@18 439
lbajardsilogic@18 440 void
lbajardsilogic@18 441 IntervalLayer::drawEnd(View *v, QMouseEvent *e)
lbajardsilogic@18 442 {
lbajardsilogic@18 443 if (!m_model || !m_editing)
lbajardsilogic@18 444 return;
lbajardsilogic@18 445
lbajardsilogic@18 446 bool ok = false;
lbajardsilogic@18 447 QString label = QInputDialog::getText(v, tr("Enter label"),
lbajardsilogic@18 448 tr("Please enter a new label:"),
lbajardsilogic@18 449 QLineEdit::Normal, "", &ok);
lbajardsilogic@18 450
lbajardsilogic@18 451 if (ok) {
lbajardsilogic@18 452 m_editingInterval->label(label);
lbajardsilogic@18 453 m_editingCommand->newLabel(label);
lbajardsilogic@18 454 }
lbajardsilogic@18 455
lbajardsilogic@18 456 if (m_editingCommand)
lbajardsilogic@18 457 {
lbajardsilogic@18 458 CommandHistory::getInstance()->addCommand(m_editingCommand, false);
lbajardsilogic@18 459 m_editingCommand = 0;
lbajardsilogic@18 460 }
lbajardsilogic@18 461
lbajardsilogic@18 462 m_editing = false;
lbajardsilogic@18 463 }
lbajardsilogic@18 464
lbajardsilogic@18 465 void
lbajardsilogic@18 466 IntervalLayer::editStart(View *view, QMouseEvent *evt)
lbajardsilogic@18 467 {
lbajardsilogic@18 468 if (!m_model)
lbajardsilogic@18 469 return;
lbajardsilogic@18 470
lbajardsilogic@18 471 IntervalList intervals = getIntervalAt(view, evt->x(), evt->y());
lbajardsilogic@18 472
lbajardsilogic@18 473 for (IntervalListConstIterator i = intervals.begin(); i != intervals.end(); ++i)
lbajardsilogic@18 474 {
lbajardsilogic@18 475 TimeIntervalPtr ti = (*i);
lbajardsilogic@18 476
lbajardsilogic@18 477 int xS = view->getXForFrame(ti->start());
lbajardsilogic@18 478 int xE = view->getXForFrame(ti->end());
lbajardsilogic@18 479
lbajardsilogic@18 480 if (abs(xS - evt->x()) < 5)
lbajardsilogic@18 481 {
lbajardsilogic@18 482 m_editing = 1; // editing start
lbajardsilogic@18 483 m_editingInterval = ti;
lbajardsilogic@18 484 break;
lbajardsilogic@18 485 }
lbajardsilogic@18 486 else if (abs(xE - evt->x()) < 5)
lbajardsilogic@18 487 {
lbajardsilogic@18 488 m_editing = 2; // editing end
lbajardsilogic@18 489 m_editingInterval = ti;
lbajardsilogic@18 490 break;
lbajardsilogic@18 491 }
lbajardsilogic@18 492 else
lbajardsilogic@18 493 {
lbajardsilogic@18 494 m_editing = 0;
lbajardsilogic@18 495 }
lbajardsilogic@18 496 }
lbajardsilogic@18 497
lbajardsilogic@18 498 if (m_editing)
lbajardsilogic@18 499 view->setCursor(Qt::SizeHorCursor);
lbajardsilogic@18 500
lbajardsilogic@18 501 if (m_editingCommand)
lbajardsilogic@18 502 {
lbajardsilogic@18 503 CommandHistory::getInstance()->addCommand(m_editingCommand, false);
lbajardsilogic@18 504 m_editingCommand = 0;
lbajardsilogic@18 505 }
lbajardsilogic@18 506
lbajardsilogic@18 507 }
lbajardsilogic@18 508
lbajardsilogic@18 509 void
lbajardsilogic@18 510 IntervalLayer::editDrag(View *view, QMouseEvent *evt)
lbajardsilogic@18 511 {
lbajardsilogic@18 512 if (!m_model || !m_editing)
lbajardsilogic@18 513 return;
lbajardsilogic@18 514
lbajardsilogic@18 515 long frame = view->getFrameForX(evt->x());
lbajardsilogic@18 516
lbajardsilogic@18 517 if (!m_editingCommand)
lbajardsilogic@18 518 {
lbajardsilogic@18 519 m_editingCommand = new IntervalModel::IntervalCommand(m_model, m_editingInterval, IntervalModel::IntervalCommand::Edition,
lbajardsilogic@18 520 m_editingInterval->start(),
lbajardsilogic@18 521 m_editingInterval->end(),
lbajardsilogic@18 522 m_editingInterval->value(),
lbajardsilogic@18 523 m_editingInterval->label());
lbajardsilogic@18 524 }
lbajardsilogic@18 525
lbajardsilogic@18 526 if (m_editing == 1) // start
lbajardsilogic@18 527 {
lbajardsilogic@18 528 if (frame < m_editingInterval->end())
lbajardsilogic@18 529 m_editingCommand->newStart(frame);
lbajardsilogic@18 530 }
lbajardsilogic@18 531 else if (m_editing == 2) // end
lbajardsilogic@18 532 {
lbajardsilogic@18 533 if (frame > m_editingInterval->start())
lbajardsilogic@18 534 m_editingCommand->newEnd(frame);
lbajardsilogic@18 535 }
lbajardsilogic@18 536 }
lbajardsilogic@18 537
lbajardsilogic@18 538 void
lbajardsilogic@18 539 IntervalLayer::editEnd(View *view, QMouseEvent *evt)
lbajardsilogic@18 540 {
lbajardsilogic@18 541 if (!m_model || !m_editing)
lbajardsilogic@18 542 return;
lbajardsilogic@18 543
lbajardsilogic@18 544 view->setCursor(Qt::UpArrowCursor);
lbajardsilogic@18 545
lbajardsilogic@18 546 if (m_editingCommand)
lbajardsilogic@18 547 {
lbajardsilogic@18 548 CommandHistory::getInstance()->addCommand(m_editingCommand, false);
lbajardsilogic@18 549 m_editingCommand = 0;
lbajardsilogic@18 550 }
lbajardsilogic@18 551
lbajardsilogic@18 552
lbajardsilogic@18 553 m_editing = false;
lbajardsilogic@18 554 }
lbajardsilogic@18 555
lbajardsilogic@18 556 void
lbajardsilogic@18 557 IntervalLayer::editOpen(View *view, QMouseEvent *evt) // on double-click
lbajardsilogic@18 558 {
lbajardsilogic@18 559 if (!m_model) return;
lbajardsilogic@18 560
lbajardsilogic@18 561 IntervalList intervals = getIntervalAt(view, evt->x(), evt->y());
lbajardsilogic@18 562 if (! intervals.empty())
lbajardsilogic@18 563 {
lbajardsilogic@18 564 TimeIntervalPtr ti = intervals.front();
lbajardsilogic@18 565
lbajardsilogic@18 566 bool ok = false;
lbajardsilogic@18 567 ItemEditDialog *dialog = new ItemEditDialog
lbajardsilogic@18 568 (m_model->getSampleRate(),
lbajardsilogic@18 569 ItemEditDialog::ShowTime |
lbajardsilogic@18 570 ItemEditDialog::ShowDuration |
lbajardsilogic@18 571 ItemEditDialog::ShowText |
lbajardsilogic@18 572 ItemEditDialog::ShowValue);
lbajardsilogic@18 573
lbajardsilogic@18 574 dialog->setFrameTime(ti->start());
lbajardsilogic@18 575 dialog->setFrameDuration(ti->end() - ti->start());
lbajardsilogic@18 576 dialog->setText(ti->label());
lbajardsilogic@18 577 dialog->setValue((int)(ti->value()*100+0.5));
lbajardsilogic@18 578
lbajardsilogic@18 579 if (dialog->exec() == QDialog::Accepted)
lbajardsilogic@18 580 {
lbajardsilogic@18 581
lbajardsilogic@18 582 IntervalModel::IntervalCommand *command =
lbajardsilogic@18 583 new IntervalModel::IntervalCommand(m_model, ti, IntervalModel::IntervalCommand::Edition,
lbajardsilogic@18 584 dialog->getFrameTime(),
lbajardsilogic@18 585 dialog->getFrameTime() + dialog->getFrameDuration(),
lbajardsilogic@18 586 dialog->getValue()/100,
lbajardsilogic@18 587 dialog->getText());
lbajardsilogic@18 588
lbajardsilogic@18 589 CommandHistory::getInstance()->addCommand(command);
lbajardsilogic@18 590
lbajardsilogic@18 591 }
lbajardsilogic@18 592 }
lbajardsilogic@18 593 }
lbajardsilogic@18 594
lbajardsilogic@18 595 void
lbajardsilogic@18 596 IntervalLayer::moveSelection(Selection s, size_t newStartFrame)
lbajardsilogic@18 597 {
lbajardsilogic@18 598 if (!m_model) return;
lbajardsilogic@18 599
lbajardsilogic@18 600 IntervalList intervals = getInterval(s.getStartFrame(), s.getEndFrame());
lbajardsilogic@18 601
lbajardsilogic@18 602 MacroCommand * command = new MacroCommand("Drag Selection");
lbajardsilogic@18 603
lbajardsilogic@18 604 long newStart = 0;
lbajardsilogic@18 605 long newEnd = 0;
lbajardsilogic@18 606
lbajardsilogic@18 607 for (IntervalListConstIterator i = intervals.begin(); i != intervals.end(); ++i)
lbajardsilogic@18 608 {
lbajardsilogic@18 609 TimeIntervalPtr ti = (*i);
lbajardsilogic@18 610
lbajardsilogic@18 611 newStart = ti->start() + ((long) (newStartFrame - s.getStartFrame()));
lbajardsilogic@18 612 newEnd = ti->end() + ((long) (newStartFrame - s.getStartFrame()));
lbajardsilogic@18 613
lbajardsilogic@18 614 IntervalModel::IntervalCommand *intervalCommand =
lbajardsilogic@18 615 new IntervalModel::IntervalCommand(m_model, ti, IntervalModel::IntervalCommand::Edition,
lbajardsilogic@18 616 newStart,
lbajardsilogic@18 617 newEnd,
lbajardsilogic@18 618 ti->value(),
lbajardsilogic@18 619 ti->label());
lbajardsilogic@18 620
lbajardsilogic@18 621 m_model->changeInterval(ti, newStart, newEnd, ti->value(), ti->label() );
lbajardsilogic@18 622
lbajardsilogic@18 623 command->addCommand(intervalCommand);
lbajardsilogic@18 624 }
lbajardsilogic@18 625
lbajardsilogic@18 626 CommandHistory::getInstance()->addCommand(command, false);
lbajardsilogic@18 627 }
lbajardsilogic@18 628
lbajardsilogic@18 629 void
lbajardsilogic@18 630 IntervalLayer::resizeSelection(Selection s, Selection newSize)
lbajardsilogic@18 631 {
lbajardsilogic@18 632 if (!m_model) return;
lbajardsilogic@18 633
lbajardsilogic@18 634 IntervalList intervals = getInterval(s.getStartFrame(), s.getEndFrame());
lbajardsilogic@18 635
lbajardsilogic@18 636 MacroCommand * command = new MacroCommand("Resize Selection");
lbajardsilogic@18 637
lbajardsilogic@18 638 long newStart = 0;
lbajardsilogic@18 639 long newEnd = 0;
lbajardsilogic@18 640
lbajardsilogic@18 641 double ratio = ((double) (newSize.getEndFrame() - newSize.getStartFrame())) /
lbajardsilogic@18 642 ((double) (s.getEndFrame() - s.getStartFrame()));
lbajardsilogic@18 643
lbajardsilogic@18 644 for (IntervalListConstIterator i = intervals.begin(); i != intervals.end(); ++i)
lbajardsilogic@18 645 {
lbajardsilogic@18 646 TimeIntervalPtr ti = (*i);
lbajardsilogic@18 647
lbajardsilogic@18 648 newStart = (long) newSize.getStartFrame() + (long) ( ((double) ti->start() - (double) s.getStartFrame()) * ratio );
lbajardsilogic@18 649 newEnd = (long) newSize.getStartFrame() + (long) ( ((double) ti->end() - (double) s.getStartFrame()) * ratio );
lbajardsilogic@18 650
lbajardsilogic@18 651 IntervalModel::IntervalCommand *intervalCommand =
lbajardsilogic@18 652 new IntervalModel::IntervalCommand(m_model, ti, IntervalModel::IntervalCommand::Edition,
lbajardsilogic@18 653 newStart,
lbajardsilogic@18 654 newEnd,
lbajardsilogic@18 655 ti->value(),
lbajardsilogic@18 656 ti->label());
lbajardsilogic@18 657
lbajardsilogic@18 658 m_model->changeInterval(ti, newStart, newEnd, ti->value(), ti->label() );
lbajardsilogic@18 659
lbajardsilogic@18 660 command->addCommand(intervalCommand);
lbajardsilogic@18 661 }
lbajardsilogic@18 662
lbajardsilogic@18 663 CommandHistory::getInstance()->addCommand(command, false);
lbajardsilogic@18 664 }
lbajardsilogic@18 665
lbajardsilogic@18 666 void
lbajardsilogic@18 667 IntervalLayer::deleteSelection(Selection s)
lbajardsilogic@18 668 {
lbajardsilogic@18 669 if (!m_model) return;
lbajardsilogic@18 670
lbajardsilogic@18 671 IntervalList intervals = getInterval(s.getStartFrame(), s.getEndFrame());
lbajardsilogic@18 672
lbajardsilogic@18 673 MacroCommand * command = new MacroCommand("Delete Selected Intervals");
lbajardsilogic@18 674
lbajardsilogic@18 675 for (IntervalListConstIterator i = intervals.begin(); i != intervals.end(); ++i)
lbajardsilogic@18 676 {
lbajardsilogic@18 677 TimeIntervalPtr ti = (*i);
lbajardsilogic@18 678
lbajardsilogic@18 679 m_model->removeInterval(ti);
lbajardsilogic@18 680
lbajardsilogic@18 681 IntervalModel::IntervalCommand *intervalCommand =
lbajardsilogic@18 682 new IntervalModel::IntervalCommand(m_model, ti, IntervalModel::IntervalCommand::Deletion,
lbajardsilogic@18 683 ti->start(),
lbajardsilogic@18 684 ti->end(),
lbajardsilogic@18 685 ti->value(),
lbajardsilogic@18 686 ti->label());
lbajardsilogic@18 687
lbajardsilogic@18 688 command->addCommand(intervalCommand);
lbajardsilogic@18 689 }
lbajardsilogic@18 690
lbajardsilogic@18 691 CommandHistory::getInstance()->addCommand(command, false);
lbajardsilogic@18 692 }
lbajardsilogic@18 693
lbajardsilogic@18 694 void
lbajardsilogic@18 695 IntervalLayer::paste(const Clipboard &from, int frameOffset)
lbajardsilogic@18 696 {
lbajardsilogic@18 697 if (!m_model) return;
lbajardsilogic@18 698
lbajardsilogic@18 699 const Clipboard::PointList &points = from.getPoints();
lbajardsilogic@18 700
lbajardsilogic@18 701 MacroCommand * command = new MacroCommand("Paste");
lbajardsilogic@18 702
lbajardsilogic@18 703 for (Clipboard::PointList::const_iterator i = points.begin(); i != points.end(); ++i)
lbajardsilogic@18 704 {
lbajardsilogic@18 705 if (!i->haveFrame())
lbajardsilogic@18 706 continue;
lbajardsilogic@18 707
lbajardsilogic@18 708 size_t frame = 0;
lbajardsilogic@18 709
lbajardsilogic@18 710 if (frameOffset > 0 || -frameOffset < i->getFrame()) {
lbajardsilogic@18 711 frame = i->getFrame() + frameOffset;
lbajardsilogic@18 712 }
lbajardsilogic@18 713
lbajardsilogic@18 714 TimeIntervalPtr ti = new TimeInterval((long) frame, (long) (frame+i->getDuration()), i->getLabel(), i->getValue());
lbajardsilogic@18 715
lbajardsilogic@18 716 m_model->addInterval(ti);
lbajardsilogic@18 717
lbajardsilogic@18 718 IntervalModel::IntervalCommand *intervalCommand =
lbajardsilogic@18 719 new IntervalModel::IntervalCommand(m_model, ti, IntervalModel::IntervalCommand::Creation,
lbajardsilogic@18 720 ti->start(),
lbajardsilogic@18 721 ti->end(),
lbajardsilogic@18 722 ti->value(),
lbajardsilogic@18 723 ti->label());
lbajardsilogic@18 724
lbajardsilogic@18 725 command->addCommand(intervalCommand);
lbajardsilogic@18 726
lbajardsilogic@18 727 }
lbajardsilogic@18 728
lbajardsilogic@18 729 CommandHistory::getInstance()->addCommand(command, false);
lbajardsilogic@18 730 }
lbajardsilogic@18 731
lbajardsilogic@18 732 void
lbajardsilogic@18 733 IntervalLayer::copy(Selection s, Clipboard &to)
lbajardsilogic@18 734 {
lbajardsilogic@18 735 if (!m_model) return;
lbajardsilogic@18 736
lbajardsilogic@18 737 IntervalList intervals = getInterval(s.getStartFrame(), s.getEndFrame());
lbajardsilogic@18 738
lbajardsilogic@18 739 for (IntervalListConstIterator i = intervals.begin(); i != intervals.end(); ++i)
lbajardsilogic@18 740 {
lbajardsilogic@18 741 TimeIntervalPtr ti = (*i);
lbajardsilogic@18 742
lbajardsilogic@18 743 Clipboard::Point point(ti->start(), ti->value(), ti->end()-ti->start(), ti->label());
lbajardsilogic@18 744 to.addPoint(point);
lbajardsilogic@18 745 }
lbajardsilogic@18 746 }
lbajardsilogic@18 747
lbajardsilogic@18 748 bool
lbajardsilogic@18 749 IntervalLayer::snapToFeatureFrame(View *v, int &frame,
lbajardsilogic@18 750 size_t &resolution,
lbajardsilogic@18 751 SnapType snap) const
lbajardsilogic@18 752 {
lbajardsilogic@18 753 if (!m_model)
lbajardsilogic@18 754 return Layer::snapToFeatureFrame(v, frame, resolution, snap);
lbajardsilogic@18 755
lbajardsilogic@18 756 resolution = m_model->getResolution();
lbajardsilogic@18 757
lbajardsilogic@18 758 IntervalList& intervals = m_model->intervals();
lbajardsilogic@18 759
lbajardsilogic@18 760 int snapped, best = frame;
lbajardsilogic@18 761 bool found = false;
lbajardsilogic@18 762
lbajardsilogic@18 763 unsigned int dist, distMin;
lbajardsilogic@18 764
lbajardsilogic@18 765 dist = distMin = m_model->getEndFrame();
lbajardsilogic@18 766
lbajardsilogic@18 767 for (IntervalListConstIterator i = intervals.begin(); i != intervals.end(); ++i)
lbajardsilogic@18 768 {
lbajardsilogic@18 769 TimeIntervalPtr ti = (*i);
lbajardsilogic@18 770 switch (snap)
lbajardsilogic@18 771 {
lbajardsilogic@18 772 case SnapRight:
lbajardsilogic@18 773 if (ti->start() >= frame)
lbajardsilogic@18 774 {
lbajardsilogic@18 775 dist = ti->start() - frame;
lbajardsilogic@18 776 snapped = ti->start();
lbajardsilogic@18 777 }
lbajardsilogic@18 778 else if (ti->end() >= frame)
lbajardsilogic@18 779 {
lbajardsilogic@18 780 dist = ti->end() - frame;
lbajardsilogic@18 781 snapped = ti->end();
lbajardsilogic@18 782 }
lbajardsilogic@18 783 break;
lbajardsilogic@18 784
lbajardsilogic@18 785 case SnapLeft:
lbajardsilogic@18 786 if (ti->end() <= frame)
lbajardsilogic@18 787 {
lbajardsilogic@18 788 dist = frame - ti->end();
lbajardsilogic@18 789 snapped = ti->end();
lbajardsilogic@18 790 }
lbajardsilogic@18 791 else if (ti->start() <= frame)
lbajardsilogic@18 792 {
lbajardsilogic@18 793 dist = frame - ti->start();
lbajardsilogic@18 794 snapped = ti->start();
lbajardsilogic@18 795 }
lbajardsilogic@18 796 break;
lbajardsilogic@18 797
lbajardsilogic@18 798 case SnapNearest:
lbajardsilogic@18 799 {
lbajardsilogic@18 800 int distS = abs(ti->start() - frame);
lbajardsilogic@18 801 int distE = abs(ti->end() - frame);
lbajardsilogic@18 802 if (distS < distE)
lbajardsilogic@18 803 {
lbajardsilogic@18 804 dist = distS;
lbajardsilogic@18 805 snapped = ti->start();
lbajardsilogic@18 806 } else
lbajardsilogic@18 807 {
lbajardsilogic@18 808 dist = distE;
lbajardsilogic@18 809 snapped = ti->end();
lbajardsilogic@18 810 }
lbajardsilogic@18 811 }
lbajardsilogic@18 812 break;
lbajardsilogic@18 813
lbajardsilogic@18 814 case SnapNeighbouring:
lbajardsilogic@18 815 {
lbajardsilogic@18 816 int distS = abs(ti->start() - frame);
lbajardsilogic@18 817 int distE = abs(ti->end() - frame);
lbajardsilogic@18 818 if (distS < 5)
lbajardsilogic@18 819 {
lbajardsilogic@18 820 dist = distS;
lbajardsilogic@18 821 snapped = ti->start();
lbajardsilogic@18 822 } else if (distE < 5)
lbajardsilogic@18 823 {
lbajardsilogic@18 824 dist = distE;
lbajardsilogic@18 825 snapped = ti->end();
lbajardsilogic@18 826 }
lbajardsilogic@18 827 }
lbajardsilogic@18 828 break;
lbajardsilogic@18 829 }
lbajardsilogic@18 830
lbajardsilogic@18 831 if (dist < distMin)
lbajardsilogic@18 832 {
lbajardsilogic@18 833 found = true;
lbajardsilogic@18 834 distMin = dist;
lbajardsilogic@18 835 best = snapped;
lbajardsilogic@18 836 }
lbajardsilogic@18 837
lbajardsilogic@18 838 }
lbajardsilogic@18 839
lbajardsilogic@18 840
lbajardsilogic@18 841 if (found)
lbajardsilogic@18 842 {
lbajardsilogic@18 843 frame = best;
lbajardsilogic@18 844 }
lbajardsilogic@18 845
lbajardsilogic@18 846 return found;
lbajardsilogic@18 847 }