Mercurial > hg > svgui
comparison layer/TimeInstantLayer.cpp @ 1433:9abddbd57667 single-point
Updates for SparseOneDimensionalModel in new API
author | Chris Cannam |
---|---|
date | Thu, 21 Mar 2019 13:34:08 +0000 |
parents | 62e908518c71 |
children | e561f0a8d75b |
comparison
equal
deleted
inserted
replaced
1432:5b9692768beb | 1433:9abddbd57667 |
---|---|
153 { | 153 { |
154 QPoint discard; | 154 QPoint discard; |
155 return !v->shouldIlluminateLocalFeatures(this, discard); | 155 return !v->shouldIlluminateLocalFeatures(this, discard); |
156 } | 156 } |
157 | 157 |
158 SparseOneDimensionalModel::PointList | 158 EventVector |
159 TimeInstantLayer::getLocalPoints(LayerGeometryProvider *v, int x) const | 159 TimeInstantLayer::getLocalPoints(LayerGeometryProvider *v, int x) const |
160 { | 160 { |
161 if (!m_model) return {}; | |
162 | |
161 // Return a set of points that all have the same frame number, the | 163 // Return a set of points that all have the same frame number, the |
162 // nearest to the given x coordinate, and that are within a | 164 // nearest to the given x coordinate, and that are within a |
163 // certain fuzz distance of that x coordinate. | 165 // certain fuzz distance of that x coordinate. |
164 | 166 |
165 if (!m_model) return SparseOneDimensionalModel::PointList(); | |
166 | |
167 sv_frame_t frame = v->getFrameForX(x); | 167 sv_frame_t frame = v->getFrameForX(x); |
168 | 168 |
169 SparseOneDimensionalModel::PointList onPoints = | 169 EventVector exact = m_model->getEventsStartingAt(frame); |
170 m_model->getPoints(frame); | 170 if (!exact.empty()) return exact; |
171 | 171 |
172 if (!onPoints.empty()) { | 172 // overspill == 1, so one event either side of the given span |
173 return onPoints; | 173 EventVector neighbouring = m_model->getEventsWithin |
174 } | 174 (frame, m_model->getResolution(), 1); |
175 | 175 |
176 SparseOneDimensionalModel::PointList prevPoints = | 176 double fuzz = v->scaleSize(2); |
177 m_model->getPreviousPoints(frame); | 177 sv_frame_t suitable = 0; |
178 SparseOneDimensionalModel::PointList nextPoints = | 178 bool have = false; |
179 m_model->getNextPoints(frame); | 179 |
180 | 180 for (Event e: neighbouring) { |
181 SparseOneDimensionalModel::PointList usePoints = prevPoints; | 181 sv_frame_t f = e.getFrame(); |
182 | 182 if (f < v->getStartFrame() || f > v->getEndFrame()) { |
183 if (prevPoints.empty()) { | 183 continue; |
184 usePoints = nextPoints; | 184 } |
185 } else if (long(prevPoints.begin()->frame) < v->getStartFrame() && | 185 int px = v->getXForFrame(f); |
186 !(nextPoints.begin()->frame > v->getEndFrame())) { | 186 if ((px > x && px - x > fuzz) || (px < x && x - px > fuzz + 3)) { |
187 usePoints = nextPoints; | 187 continue; |
188 } else if (nextPoints.begin()->frame - frame < | 188 } |
189 frame - prevPoints.begin()->frame) { | 189 if (!have) { |
190 usePoints = nextPoints; | 190 suitable = f; |
191 } | 191 have = true; |
192 | 192 } else if (llabs(frame - f) < llabs(suitable - f)) { |
193 if (!usePoints.empty()) { | 193 suitable = f; |
194 int fuzz = ViewManager::scalePixelSize(2); | 194 } |
195 int px = v->getXForFrame(usePoints.begin()->frame); | 195 } |
196 if ((px > x && px - x > fuzz) || | 196 |
197 (px < x && x - px > fuzz + 1)) { | 197 if (have) { |
198 usePoints.clear(); | 198 return m_model->getEventsStartingAt(suitable); |
199 } | 199 } else { |
200 } | 200 return {}; |
201 | 201 } |
202 return usePoints; | |
203 } | 202 } |
204 | 203 |
205 QString | 204 QString |
206 TimeInstantLayer::getLabelPreceding(sv_frame_t frame) const | 205 TimeInstantLayer::getLabelPreceding(sv_frame_t frame) const |
207 { | 206 { |
208 if (!m_model) return ""; | 207 if (!m_model || !m_model->hasTextLabels()) return ""; |
209 SparseOneDimensionalModel::PointList points = m_model->getPreviousPoints(frame); | 208 |
210 for (SparseOneDimensionalModel::PointList::const_iterator i = points.begin(); | 209 Event e; |
211 i != points.end(); ++i) { | 210 if (m_model->getNearestEventMatching |
212 if (i->label != "") return i->label; | 211 (frame, |
213 } | 212 [](Event e) { return e.hasLabel() && e.getLabel() != ""; }, |
213 EventSeries::Backward, | |
214 e)) { | |
215 return e.getLabel(); | |
216 } | |
217 | |
214 return ""; | 218 return ""; |
215 } | 219 } |
216 | 220 |
217 QString | 221 QString |
218 TimeInstantLayer::getFeatureDescription(LayerGeometryProvider *v, QPoint &pos) const | 222 TimeInstantLayer::getFeatureDescription(LayerGeometryProvider *v, QPoint &pos) const |
219 { | 223 { |
220 int x = pos.x(); | 224 int x = pos.x(); |
221 | 225 |
222 if (!m_model || !m_model->getSampleRate()) return ""; | 226 if (!m_model || !m_model->getSampleRate()) return ""; |
223 | 227 |
224 SparseOneDimensionalModel::PointList points = getLocalPoints(v, x); | 228 EventVector points = getLocalPoints(v, x); |
225 | 229 |
226 if (points.empty()) { | 230 if (points.empty()) { |
227 if (!m_model->isReady()) { | 231 if (!m_model->isReady()) { |
228 return tr("In progress"); | 232 return tr("In progress"); |
229 } else { | 233 } else { |
230 return tr("No local points"); | 234 return tr("No local points"); |
231 } | 235 } |
232 } | 236 } |
233 | 237 |
234 sv_frame_t useFrame = points.begin()->frame; | 238 sv_frame_t useFrame = points.begin()->getFrame(); |
235 | 239 |
236 RealTime rt = RealTime::frame2RealTime(useFrame, m_model->getSampleRate()); | 240 RealTime rt = RealTime::frame2RealTime(useFrame, m_model->getSampleRate()); |
237 | 241 |
238 QString text; | 242 QString text; |
239 | 243 |
240 if (points.begin()->label == "") { | 244 if (points.begin()->getLabel() == "") { |
241 text = QString(tr("Time:\t%1\nNo label")) | 245 text = QString(tr("Time:\t%1\nNo label")) |
242 .arg(rt.toText(true).c_str()); | 246 .arg(rt.toText(true).c_str()); |
243 } else { | 247 } else { |
244 text = QString(tr("Time:\t%1\nLabel:\t%2")) | 248 text = QString(tr("Time:\t%1\nLabel:\t%2")) |
245 .arg(rt.toText(true).c_str()) | 249 .arg(rt.toText(true).c_str()) |
246 .arg(points.begin()->label); | 250 .arg(points.begin()->getLabel()); |
247 } | 251 } |
248 | 252 |
249 pos = QPoint(v->getXForFrame(useFrame), pos.y()); | 253 pos = QPoint(v->getXForFrame(useFrame), pos.y()); |
250 return text; | 254 return text; |
251 } | 255 } |
257 { | 261 { |
258 if (!m_model) { | 262 if (!m_model) { |
259 return Layer::snapToFeatureFrame(v, frame, resolution, snap); | 263 return Layer::snapToFeatureFrame(v, frame, resolution, snap); |
260 } | 264 } |
261 | 265 |
266 // SnapLeft / SnapRight: return frame of nearest feature in that | |
267 // direction no matter how far away | |
268 // | |
269 // SnapNeighbouring: return frame of feature that would be used in | |
270 // an editing operation, i.e. closest feature in either direction | |
271 // but only if it is "close enough" | |
272 | |
262 resolution = m_model->getResolution(); | 273 resolution = m_model->getResolution(); |
263 SparseOneDimensionalModel::PointList points; | |
264 | 274 |
265 if (snap == SnapNeighbouring) { | 275 if (snap == SnapNeighbouring) { |
266 | 276 EventVector points = getLocalPoints(v, v->getXForFrame(frame)); |
267 points = getLocalPoints(v, v->getXForFrame(frame)); | |
268 if (points.empty()) return false; | 277 if (points.empty()) return false; |
269 frame = points.begin()->frame; | 278 frame = points.begin()->getFrame(); |
270 return true; | 279 return true; |
271 } | 280 } |
272 | 281 |
273 points = m_model->getPoints(frame, frame); | 282 Event e; |
274 sv_frame_t snapped = frame; | 283 if (m_model->getNearestEventMatching |
275 bool found = false; | 284 (frame, |
276 | 285 [](Event) { return true; }, |
277 for (SparseOneDimensionalModel::PointList::const_iterator i = points.begin(); | 286 snap == SnapLeft ? EventSeries::Backward : EventSeries::Forward, |
278 i != points.end(); ++i) { | 287 e)) { |
279 | 288 frame = e.getFrame(); |
280 if (snap == SnapRight) { | 289 return true; |
281 | 290 } |
282 if (i->frame >= frame) { | 291 |
283 snapped = i->frame; | 292 return false; |
284 found = true; | |
285 break; | |
286 } | |
287 | |
288 } else if (snap == SnapLeft) { | |
289 | |
290 if (i->frame <= frame) { | |
291 snapped = i->frame; | |
292 found = true; // don't break, as the next may be better | |
293 } else { | |
294 break; | |
295 } | |
296 | |
297 } else { // nearest | |
298 | |
299 SparseOneDimensionalModel::PointList::const_iterator j = i; | |
300 ++j; | |
301 | |
302 if (j == points.end()) { | |
303 | |
304 snapped = i->frame; | |
305 found = true; | |
306 break; | |
307 | |
308 } else if (j->frame >= frame) { | |
309 | |
310 if (j->frame - frame < frame - i->frame) { | |
311 snapped = j->frame; | |
312 } else { | |
313 snapped = i->frame; | |
314 } | |
315 found = true; | |
316 break; | |
317 } | |
318 } | |
319 } | |
320 | |
321 frame = snapped; | |
322 return found; | |
323 } | 293 } |
324 | 294 |
325 void | 295 void |
326 TimeInstantLayer::paint(LayerGeometryProvider *v, QPainter &paint, QRect rect) const | 296 TimeInstantLayer::paint(LayerGeometryProvider *v, QPainter &paint, QRect rect) const |
327 { | 297 { |
332 int x0 = rect.left(), x1 = rect.right(); | 302 int x0 = rect.left(), x1 = rect.right(); |
333 | 303 |
334 sv_frame_t frame0 = v->getFrameForX(x0); | 304 sv_frame_t frame0 = v->getFrameForX(x0); |
335 sv_frame_t frame1 = v->getFrameForX(x1); | 305 sv_frame_t frame1 = v->getFrameForX(x1); |
336 | 306 |
337 SparseOneDimensionalModel::PointList points(m_model->getPoints | 307 EventVector points(m_model->getEventsWithin(frame0, frame1 - frame0)); |
338 (frame0, frame1)); | |
339 | 308 |
340 bool odd = false; | 309 bool odd = false; |
341 if (m_plotStyle == PlotSegmentation && !points.empty()) { | 310 if (m_plotStyle == PlotSegmentation && !points.empty()) { |
342 int index = m_model->getIndexOf(*points.begin()); | 311 int index = m_model->getRowForFrame(points.begin()->getFrame()); |
343 odd = ((index % 2) == 1); | 312 odd = ((index % 2) == 1); |
344 } | 313 } |
345 | 314 |
346 paint.setPen(getBaseQColor()); | 315 paint.setPen(getBaseQColor()); |
347 | 316 |
370 | 339 |
371 QPoint localPos; | 340 QPoint localPos; |
372 sv_frame_t illuminateFrame = -1; | 341 sv_frame_t illuminateFrame = -1; |
373 | 342 |
374 if (v->shouldIlluminateLocalFeatures(this, localPos)) { | 343 if (v->shouldIlluminateLocalFeatures(this, localPos)) { |
375 SparseOneDimensionalModel::PointList localPoints = | 344 EventVector localPoints = getLocalPoints(v, localPos.x()); |
376 getLocalPoints(v, localPos.x()); | 345 if (!localPoints.empty()) { |
377 if (!localPoints.empty()) illuminateFrame = localPoints.begin()->frame; | 346 illuminateFrame = localPoints.begin()->getFrame(); |
347 } | |
378 } | 348 } |
379 | 349 |
380 int prevX = -1; | 350 int prevX = -1; |
381 int textY = v->getTextLabelHeight(this, paint); | 351 int textY = v->getTextLabelHeight(this, paint); |
382 | 352 |
383 for (SparseOneDimensionalModel::PointList::const_iterator i = points.begin(); | 353 for (EventVector::const_iterator i = points.begin(); |
384 i != points.end(); ++i) { | 354 i != points.end(); ++i) { |
385 | 355 |
386 const SparseOneDimensionalModel::Point &p(*i); | 356 Event p(*i); |
387 SparseOneDimensionalModel::PointList::const_iterator j = i; | 357 EventVector::const_iterator j = i; |
388 ++j; | 358 ++j; |
389 | 359 |
390 int x = v->getXForFrame(p.frame); | 360 int x = v->getXForFrame(p.getFrame()); |
391 if (x == prevX && m_plotStyle == PlotInstants && | 361 if (x == prevX && m_plotStyle == PlotInstants && |
392 p.frame != illuminateFrame) continue; | 362 p.getFrame() != illuminateFrame) continue; |
393 | 363 |
394 int iw = v->getXForFrame(p.frame + m_model->getResolution()) - x; | 364 int iw = v->getXForFrame(p.getFrame() + m_model->getResolution()) - x; |
395 if (iw < 2) { | 365 if (iw < 2) { |
396 if (iw < 1) { | 366 if (iw < 1) { |
397 iw = 2; | 367 iw = 2; |
398 if (j != points.end()) { | 368 if (j != points.end()) { |
399 int nx = v->getXForFrame(j->frame); | 369 int nx = v->getXForFrame(j->getFrame()); |
400 if (nx < x + 3) iw = 1; | 370 if (nx < x + 3) iw = 1; |
401 } | 371 } |
402 } else { | 372 } else { |
403 iw = 2; | 373 iw = 2; |
404 } | 374 } |
405 } | 375 } |
406 | 376 |
407 if (p.frame == illuminateFrame) { | 377 if (p.getFrame() == illuminateFrame) { |
408 paint.setPen(getForegroundQColor(v->getView())); | 378 paint.setPen(getForegroundQColor(v->getView())); |
409 } else { | 379 } else { |
410 paint.setPen(brushColour); | 380 paint.setPen(brushColour); |
411 } | 381 } |
412 | 382 |
422 else paint.setBrush(brushColour); | 392 else paint.setBrush(brushColour); |
423 | 393 |
424 int nx; | 394 int nx; |
425 | 395 |
426 if (j != points.end()) { | 396 if (j != points.end()) { |
427 const SparseOneDimensionalModel::Point &q(*j); | 397 Event q(*j); |
428 nx = v->getXForFrame(q.frame); | 398 nx = v->getXForFrame(q.getFrame()); |
429 } else { | 399 } else { |
430 nx = v->getXForFrame(m_model->getEndFrame()); | 400 nx = v->getXForFrame(m_model->getEndFrame()); |
431 } | 401 } |
432 | 402 |
433 if (nx >= x) { | 403 if (nx >= x) { |
434 | 404 |
435 if (illuminateFrame != p.frame && | 405 if (illuminateFrame != p.getFrame() && |
436 (nx < x + 5 || x >= v->getPaintWidth() - 1)) { | 406 (nx < x + 5 || x >= v->getPaintWidth() - 1)) { |
437 paint.setPen(Qt::NoPen); | 407 paint.setPen(Qt::NoPen); |
438 } | 408 } |
439 | 409 |
440 paint.drawRect(x, -1, nx - x, v->getPaintHeight() + 1); | 410 paint.drawRect(x, -1, nx - x, v->getPaintHeight() + 1); |
443 odd = !odd; | 413 odd = !odd; |
444 } | 414 } |
445 | 415 |
446 paint.setPen(getBaseQColor()); | 416 paint.setPen(getBaseQColor()); |
447 | 417 |
448 if (p.label != "") { | 418 if (p.getLabel() != "") { |
449 | 419 |
450 // only draw if there's enough room from here to the next point | 420 // only draw if there's enough room from here to the next point |
451 | 421 |
452 int lw = paint.fontMetrics().width(p.label); | 422 int lw = paint.fontMetrics().width(p.getLabel()); |
453 bool good = true; | 423 bool good = true; |
454 | 424 |
455 if (j != points.end()) { | 425 if (j != points.end()) { |
456 int nx = v->getXForFrame(j->frame); | 426 int nx = v->getXForFrame(j->getFrame()); |
457 if (nx >= x && nx - x - iw - 3 <= lw) good = false; | 427 if (nx >= x && nx - x - iw - 3 <= lw) good = false; |
458 } | 428 } |
459 | 429 |
460 if (good) { | 430 if (good) { |
461 PaintAssistant::drawVisibleText(v, paint, | 431 PaintAssistant::drawVisibleText(v, paint, |
462 x + iw + 2, textY, | 432 x + iw + 2, textY, |
463 p.label, | 433 p.getLabel(), |
464 PaintAssistant::OutlinedText); | 434 PaintAssistant::OutlinedText); |
465 } | 435 } |
466 } | 436 } |
467 | 437 |
468 prevX = x; | 438 prevX = x; |
480 | 450 |
481 sv_frame_t frame = v->getFrameForX(e->x()); | 451 sv_frame_t frame = v->getFrameForX(e->x()); |
482 if (frame < 0) frame = 0; | 452 if (frame < 0) frame = 0; |
483 frame = frame / m_model->getResolution() * m_model->getResolution(); | 453 frame = frame / m_model->getResolution() * m_model->getResolution(); |
484 | 454 |
485 m_editingPoint = SparseOneDimensionalModel::Point(frame, tr("New Point")); | 455 m_editingPoint = Event(frame, tr("New Point")); |
486 | 456 |
487 if (m_editingCommand) finish(m_editingCommand); | 457 if (m_editingCommand) finish(m_editingCommand); |
488 m_editingCommand = new SparseOneDimensionalModel::EditCommand(m_model, | 458 m_editingCommand = new ChangeEventsCommand(m_model, tr("Draw Point")); |
489 tr("Draw Point")); | 459 m_editingCommand->add(m_editingPoint); |
490 m_editingCommand->addPoint(m_editingPoint); | |
491 | 460 |
492 m_editing = true; | 461 m_editing = true; |
493 } | 462 } |
494 | 463 |
495 void | 464 void |
502 if (!m_model || !m_editing) return; | 471 if (!m_model || !m_editing) return; |
503 | 472 |
504 sv_frame_t frame = v->getFrameForX(e->x()); | 473 sv_frame_t frame = v->getFrameForX(e->x()); |
505 if (frame < 0) frame = 0; | 474 if (frame < 0) frame = 0; |
506 frame = frame / m_model->getResolution() * m_model->getResolution(); | 475 frame = frame / m_model->getResolution() * m_model->getResolution(); |
507 m_editingCommand->deletePoint(m_editingPoint); | 476 m_editingCommand->remove(m_editingPoint); |
508 m_editingPoint.frame = frame; | 477 m_editingPoint = m_editingPoint.withFrame(frame); |
509 m_editingCommand->addPoint(m_editingPoint); | 478 m_editingCommand->add(m_editingPoint); |
510 } | 479 } |
511 | 480 |
512 void | 481 void |
513 TimeInstantLayer::drawEnd(LayerGeometryProvider *, QMouseEvent *) | 482 TimeInstantLayer::drawEnd(LayerGeometryProvider *, QMouseEvent *) |
514 { | 483 { |
515 #ifdef DEBUG_TIME_INSTANT_LAYER | 484 #ifdef DEBUG_TIME_INSTANT_LAYER |
516 cerr << "TimeInstantLayer::drawEnd(" << e->x() << ")" << endl; | 485 cerr << "TimeInstantLayer::drawEnd(" << e->x() << ")" << endl; |
517 #endif | 486 #endif |
518 if (!m_model || !m_editing) return; | 487 if (!m_model || !m_editing) return; |
519 QString newName = tr("Add Point at %1 s") | 488 QString newName = tr("Add Point at %1 s") |
520 .arg(RealTime::frame2RealTime(m_editingPoint.frame, | 489 .arg(RealTime::frame2RealTime(m_editingPoint.getFrame(), |
521 m_model->getSampleRate()) | 490 m_model->getSampleRate()) |
522 .toText(false).c_str()); | 491 .toText(false).c_str()); |
523 m_editingCommand->setName(newName); | 492 m_editingCommand->setName(newName); |
524 finish(m_editingCommand); | 493 finish(m_editingCommand); |
525 m_editingCommand = nullptr; | 494 m_editingCommand = nullptr; |
529 void | 498 void |
530 TimeInstantLayer::eraseStart(LayerGeometryProvider *v, QMouseEvent *e) | 499 TimeInstantLayer::eraseStart(LayerGeometryProvider *v, QMouseEvent *e) |
531 { | 500 { |
532 if (!m_model) return; | 501 if (!m_model) return; |
533 | 502 |
534 SparseOneDimensionalModel::PointList points = getLocalPoints(v, e->x()); | 503 EventVector points = getLocalPoints(v, e->x()); |
535 if (points.empty()) return; | 504 if (points.empty()) return; |
536 | 505 |
537 m_editingPoint = *points.begin(); | 506 m_editingPoint = *points.begin(); |
538 | 507 |
539 if (m_editingCommand) { | 508 if (m_editingCommand) { |
554 { | 523 { |
555 if (!m_model || !m_editing) return; | 524 if (!m_model || !m_editing) return; |
556 | 525 |
557 m_editing = false; | 526 m_editing = false; |
558 | 527 |
559 SparseOneDimensionalModel::PointList points = getLocalPoints(v, e->x()); | 528 EventVector points = getLocalPoints(v, e->x()); |
560 if (points.empty()) return; | 529 if (points.empty()) return; |
561 if (points.begin()->frame != m_editingPoint.frame) return; | 530 if (points.begin()->getFrame() != m_editingPoint.getFrame()) return; |
562 | 531 |
563 m_editingCommand = new SparseOneDimensionalModel::EditCommand | 532 m_editingCommand = new ChangeEventsCommand(m_model, tr("Erase Point")); |
564 (m_model, tr("Erase Point")); | 533 m_editingCommand->remove(m_editingPoint); |
565 | |
566 m_editingCommand->deletePoint(m_editingPoint); | |
567 | |
568 finish(m_editingCommand); | 534 finish(m_editingCommand); |
569 m_editingCommand = nullptr; | 535 m_editingCommand = nullptr; |
570 m_editing = false; | 536 m_editing = false; |
571 } | 537 } |
572 | 538 |
577 cerr << "TimeInstantLayer::editStart(" << e->x() << ")" << endl; | 543 cerr << "TimeInstantLayer::editStart(" << e->x() << ")" << endl; |
578 #endif | 544 #endif |
579 | 545 |
580 if (!m_model) return; | 546 if (!m_model) return; |
581 | 547 |
582 SparseOneDimensionalModel::PointList points = getLocalPoints(v, e->x()); | 548 EventVector points = getLocalPoints(v, e->x()); |
583 if (points.empty()) return; | 549 if (points.empty()) return; |
584 | 550 |
585 m_editingPoint = *points.begin(); | 551 m_editingPoint = *points.begin(); |
586 | 552 |
587 if (m_editingCommand) { | 553 if (m_editingCommand) { |
604 sv_frame_t frame = v->getFrameForX(e->x()); | 570 sv_frame_t frame = v->getFrameForX(e->x()); |
605 if (frame < 0) frame = 0; | 571 if (frame < 0) frame = 0; |
606 frame = frame / m_model->getResolution() * m_model->getResolution(); | 572 frame = frame / m_model->getResolution() * m_model->getResolution(); |
607 | 573 |
608 if (!m_editingCommand) { | 574 if (!m_editingCommand) { |
609 m_editingCommand = new SparseOneDimensionalModel::EditCommand(m_model, | 575 m_editingCommand = new ChangeEventsCommand(m_model, tr("Drag Point")); |
610 tr("Drag Point")); | 576 } |
611 } | 577 |
612 | 578 m_editingCommand->remove(m_editingPoint); |
613 m_editingCommand->deletePoint(m_editingPoint); | 579 m_editingPoint = m_editingPoint.withFrame(frame); |
614 m_editingPoint.frame = frame; | 580 m_editingCommand->add(m_editingPoint); |
615 m_editingCommand->addPoint(m_editingPoint); | |
616 } | 581 } |
617 | 582 |
618 void | 583 void |
619 TimeInstantLayer::editEnd(LayerGeometryProvider *, QMouseEvent *) | 584 TimeInstantLayer::editEnd(LayerGeometryProvider *, QMouseEvent *) |
620 { | 585 { |
622 cerr << "TimeInstantLayer::editEnd(" << e->x() << ")" << endl; | 587 cerr << "TimeInstantLayer::editEnd(" << e->x() << ")" << endl; |
623 #endif | 588 #endif |
624 if (!m_model || !m_editing) return; | 589 if (!m_model || !m_editing) return; |
625 if (m_editingCommand) { | 590 if (m_editingCommand) { |
626 QString newName = tr("Move Point to %1 s") | 591 QString newName = tr("Move Point to %1 s") |
627 .arg(RealTime::frame2RealTime(m_editingPoint.frame, | 592 .arg(RealTime::frame2RealTime(m_editingPoint.getFrame(), |
628 m_model->getSampleRate()) | 593 m_model->getSampleRate()) |
629 .toText(false).c_str()); | 594 .toText(false).c_str()); |
630 m_editingCommand->setName(newName); | 595 m_editingCommand->setName(newName); |
631 finish(m_editingCommand); | 596 finish(m_editingCommand); |
632 } | 597 } |
637 bool | 602 bool |
638 TimeInstantLayer::editOpen(LayerGeometryProvider *v, QMouseEvent *e) | 603 TimeInstantLayer::editOpen(LayerGeometryProvider *v, QMouseEvent *e) |
639 { | 604 { |
640 if (!m_model) return false; | 605 if (!m_model) return false; |
641 | 606 |
642 SparseOneDimensionalModel::PointList points = getLocalPoints(v, e->x()); | 607 EventVector points = getLocalPoints(v, e->x()); |
643 if (points.empty()) return false; | 608 if (points.empty()) return false; |
644 | 609 |
645 SparseOneDimensionalModel::Point point = *points.begin(); | 610 Event point = *points.begin(); |
646 | 611 |
647 ItemEditDialog *dialog = new ItemEditDialog | 612 ItemEditDialog *dialog = new ItemEditDialog |
648 (m_model->getSampleRate(), | 613 (m_model->getSampleRate(), |
649 ItemEditDialog::ShowTime | | 614 ItemEditDialog::ShowTime | |
650 ItemEditDialog::ShowText); | 615 ItemEditDialog::ShowText); |
651 | 616 |
652 dialog->setFrameTime(point.frame); | 617 dialog->setFrameTime(point.getFrame()); |
653 dialog->setText(point.label); | 618 dialog->setText(point.getLabel()); |
654 | 619 |
655 if (dialog->exec() == QDialog::Accepted) { | 620 if (dialog->exec() == QDialog::Accepted) { |
656 | 621 |
657 SparseOneDimensionalModel::Point newPoint = point; | 622 Event newPoint = point |
658 newPoint.frame = dialog->getFrameTime(); | 623 .withFrame(dialog->getFrameTime()) |
659 newPoint.label = dialog->getText(); | 624 .withLabel(dialog->getText()); |
660 | 625 |
661 SparseOneDimensionalModel::EditCommand *command = | 626 ChangeEventsCommand *command = |
662 new SparseOneDimensionalModel::EditCommand(m_model, tr("Edit Point")); | 627 new ChangeEventsCommand(m_model, tr("Edit Point")); |
663 command->deletePoint(point); | 628 command->remove(point); |
664 command->addPoint(newPoint); | 629 command->add(newPoint); |
665 finish(command); | 630 finish(command); |
666 } | 631 } |
667 | 632 |
668 delete dialog; | 633 delete dialog; |
669 return true; | 634 return true; |
672 void | 637 void |
673 TimeInstantLayer::moveSelection(Selection s, sv_frame_t newStartFrame) | 638 TimeInstantLayer::moveSelection(Selection s, sv_frame_t newStartFrame) |
674 { | 639 { |
675 if (!m_model) return; | 640 if (!m_model) return; |
676 | 641 |
677 SparseOneDimensionalModel::EditCommand *command = | 642 ChangeEventsCommand *command = |
678 new SparseOneDimensionalModel::EditCommand(m_model, | 643 new ChangeEventsCommand(m_model, tr("Drag Selection")); |
679 tr("Drag Selection")); | 644 |
680 | 645 EventVector points = |
681 SparseOneDimensionalModel::PointList points = | 646 m_model->getEventsWithin(s.getStartFrame(), s.getDuration()); |
682 m_model->getPoints(s.getStartFrame(), s.getEndFrame()); | 647 |
683 | 648 for (auto p: points) { |
684 for (SparseOneDimensionalModel::PointList::iterator i = points.begin(); | 649 Event newPoint = p |
685 i != points.end(); ++i) { | 650 .withFrame(p.getFrame() + newStartFrame - s.getStartFrame()); |
686 | 651 command->remove(p); |
687 if (s.contains(i->frame)) { | 652 command->add(newPoint); |
688 SparseOneDimensionalModel::Point newPoint(*i); | |
689 newPoint.frame = i->frame + newStartFrame - s.getStartFrame(); | |
690 command->deletePoint(*i); | |
691 command->addPoint(newPoint); | |
692 } | |
693 } | 653 } |
694 | 654 |
695 finish(command); | 655 finish(command); |
696 } | 656 } |
697 | 657 |
698 void | 658 void |
699 TimeInstantLayer::resizeSelection(Selection s, Selection newSize) | 659 TimeInstantLayer::resizeSelection(Selection s, Selection newSize) |
700 { | 660 { |
701 if (!m_model) return; | 661 if (!m_model) return; |
702 | 662 |
703 SparseOneDimensionalModel::EditCommand *command = | 663 ChangeEventsCommand *command = |
704 new SparseOneDimensionalModel::EditCommand(m_model, | 664 new ChangeEventsCommand(m_model, tr("Resize Selection")); |
705 tr("Resize Selection")); | 665 |
706 | 666 EventVector points = |
707 SparseOneDimensionalModel::PointList points = | 667 m_model->getEventsWithin(s.getStartFrame(), s.getDuration()); |
708 m_model->getPoints(s.getStartFrame(), s.getEndFrame()); | 668 |
709 | 669 double ratio = double(newSize.getDuration()) / double(s.getDuration()); |
710 double ratio = | 670 double oldStart = double(s.getStartFrame()); |
711 double(newSize.getEndFrame() - newSize.getStartFrame()) / | 671 double newStart = double(newSize.getStartFrame()); |
712 double(s.getEndFrame() - s.getStartFrame()); | 672 |
713 | 673 for (auto p: points) { |
714 for (SparseOneDimensionalModel::PointList::iterator i = points.begin(); | 674 |
715 i != points.end(); ++i) { | 675 double newFrame = (double(p.getFrame()) - oldStart) * ratio + newStart; |
716 | 676 |
717 if (s.contains(i->frame)) { | 677 Event newPoint = p |
718 | 678 .withFrame(lrint(newFrame)); |
719 double target = double(i->frame); | 679 command->remove(p); |
720 target = double(newSize.getStartFrame()) + | 680 command->add(newPoint); |
721 target - double(s.getStartFrame()) * ratio; | |
722 | |
723 SparseOneDimensionalModel::Point newPoint(*i); | |
724 newPoint.frame = lrint(target); | |
725 command->deletePoint(*i); | |
726 command->addPoint(newPoint); | |
727 } | |
728 } | 681 } |
729 | 682 |
730 finish(command); | 683 finish(command); |
731 } | 684 } |
732 | 685 |
733 void | 686 void |
734 TimeInstantLayer::deleteSelection(Selection s) | 687 TimeInstantLayer::deleteSelection(Selection s) |
735 { | 688 { |
736 if (!m_model) return; | 689 if (!m_model) return; |
737 | 690 |
738 SparseOneDimensionalModel::EditCommand *command = | 691 ChangeEventsCommand *command = |
739 new SparseOneDimensionalModel::EditCommand(m_model, | 692 new ChangeEventsCommand(m_model, tr("Delete Selection")); |
740 tr("Delete Selection")); | 693 |
741 | 694 EventVector points = |
742 SparseOneDimensionalModel::PointList points = | 695 m_model->getEventsWithin(s.getStartFrame(), s.getDuration()); |
743 m_model->getPoints(s.getStartFrame(), s.getEndFrame()); | 696 |
744 | 697 for (auto p: points) { |
745 for (SparseOneDimensionalModel::PointList::iterator i = points.begin(); | 698 command->remove(p); |
746 i != points.end(); ++i) { | |
747 if (s.contains(i->frame)) command->deletePoint(*i); | |
748 } | 699 } |
749 | 700 |
750 finish(command); | 701 finish(command); |
751 } | 702 } |
752 | 703 |
753 void | 704 void |
754 TimeInstantLayer::copy(LayerGeometryProvider *v, Selection s, Clipboard &to) | 705 TimeInstantLayer::copy(LayerGeometryProvider *v, Selection s, Clipboard &to) |
755 { | 706 { |
756 if (!m_model) return; | 707 if (!m_model) return; |
757 | 708 |
758 SparseOneDimensionalModel::PointList points = | 709 EventVector points = |
759 m_model->getPoints(s.getStartFrame(), s.getEndFrame()); | 710 m_model->getEventsWithin(s.getStartFrame(), s.getDuration()); |
760 | 711 |
761 for (SparseOneDimensionalModel::PointList::iterator i = points.begin(); | 712 for (auto p: points) { |
762 i != points.end(); ++i) { | 713 to.addPoint(p.withReferenceFrame(alignToReference(v, p.getFrame()))); |
763 if (s.contains(i->frame)) { | |
764 Event point(i->frame, i->label); | |
765 to.addPoint(point.withReferenceFrame(alignToReference(v, i->frame))); | |
766 } | |
767 } | 714 } |
768 } | 715 } |
769 | 716 |
770 bool | 717 bool |
771 TimeInstantLayer::paste(LayerGeometryProvider *v, const Clipboard &from, sv_frame_t frameOffset, bool) | 718 TimeInstantLayer::paste(LayerGeometryProvider *v, const Clipboard &from, sv_frame_t frameOffset, bool) |
772 { | 719 { |
773 if (!m_model) return false; | 720 if (!m_model) return false; |
774 | 721 |
775 const EventVector &points = from.getPoints(); | 722 EventVector points = from.getPoints(); |
776 | 723 |
777 bool realign = false; | 724 bool realign = false; |
778 | 725 |
779 if (clipboardHasDifferentAlignment(v, from)) { | 726 if (clipboardHasDifferentAlignment(v, from)) { |
780 | 727 |
791 if (button == QMessageBox::Yes) { | 738 if (button == QMessageBox::Yes) { |
792 realign = true; | 739 realign = true; |
793 } | 740 } |
794 } | 741 } |
795 | 742 |
796 SparseOneDimensionalModel::EditCommand *command = | 743 ChangeEventsCommand *command = |
797 new SparseOneDimensionalModel::EditCommand(m_model, tr("Paste")); | 744 new ChangeEventsCommand(m_model, tr("Paste")); |
798 | 745 |
799 for (EventVector::const_iterator i = points.begin(); | 746 for (EventVector::const_iterator i = points.begin(); |
800 i != points.end(); ++i) { | 747 i != points.end(); ++i) { |
801 | 748 |
802 sv_frame_t frame = 0; | 749 sv_frame_t frame = 0; |
819 else if (frameOffset < 0) { | 766 else if (frameOffset < 0) { |
820 if (frame > -frameOffset) frame += frameOffset; | 767 if (frame > -frameOffset) frame += frameOffset; |
821 else frame = 0; | 768 else frame = 0; |
822 } | 769 } |
823 | 770 |
824 SparseOneDimensionalModel::Point newPoint(frame); | 771 Event newPoint = *i; |
825 if (i->hasLabel()) { | 772 if (!i->hasLabel() && i->hasValue()) { |
826 newPoint.label = i->getLabel(); | 773 newPoint = newPoint.withLabel(QString("%1").arg(i->getValue())); |
827 } else if (i->hasValue()) { | |
828 newPoint.label = QString("%1").arg(i->getValue()); | |
829 } | 774 } |
830 | 775 |
831 command->addPoint(newPoint); | 776 command->add(newPoint); |
832 } | 777 } |
833 | 778 |
834 finish(command); | 779 finish(command); |
835 return true; | 780 return true; |
836 } | 781 } |