svgui  1.9
RegionLayer.cpp
Go to the documentation of this file.
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
2 
3 /*
4  Sonic Visualiser
5  An audio file viewer and annotation editor.
6  Centre for Digital Music, Queen Mary, University of London.
7  This file copyright 2006-2008 Chris Cannam and QMUL.
8 
9  This program is free software; you can redistribute it and/or
10  modify it under the terms of the GNU General Public License as
11  published by the Free Software Foundation; either version 2 of the
12  License, or (at your option) any later version. See the file
13  COPYING included with this distribution for more information.
14 */
15 
16 #include "RegionLayer.h"
17 
18 #include "data/model/Model.h"
19 #include "base/RealTime.h"
20 #include "base/Profiler.h"
21 #include "base/LogRange.h"
22 #include "ColourDatabase.h"
23 
24 #include "ColourMapper.h"
25 #include "LinearNumericalScale.h"
26 #include "LogNumericalScale.h"
27 #include "LinearColourScale.h"
28 #include "LogColourScale.h"
29 
30 #include "view/View.h"
31 
32 #include "data/model/RegionModel.h"
33 
34 #include "widgets/ItemEditDialog.h"
35 #include "widgets/TextAbbrev.h"
36 
37 #include <QPainter>
38 #include <QPainterPath>
39 #include <QMouseEvent>
40 #include <QTextStream>
41 #include <QMessageBox>
42 
43 #include <iostream>
44 #include <cmath>
45 
48  m_model(0),
49  m_editing(false),
50  m_dragPointX(0),
51  m_dragPointY(0),
52  m_dragStartX(0),
53  m_dragStartY(0),
54  m_originalPoint(0, 0.0, 0, tr("New Region")),
55  m_editingPoint(0, 0.0, 0, tr("New Region")),
56  m_editingCommand(0),
57  m_verticalScale(EqualSpaced),
58  m_colourMap(0),
59  m_plotStyle(PlotLines)
60 {
61 
62 }
63 
64 void
65 RegionLayer::setModel(RegionModel *model)
66 {
67  if (m_model == model) return;
68  m_model = model;
69 
71 
72  connect(m_model, SIGNAL(modelChanged()), this, SLOT(recalcSpacing()));
73  recalcSpacing();
74 
75 // SVDEBUG << "RegionLayer::setModel(" << model << ")" << endl;
76 
77  if (m_model && m_model->getRDFTypeURI().endsWith("Segment")) {
79  }
80  if (m_model && m_model->getRDFTypeURI().endsWith("Change")) {
82  }
83 
84  emit modelReplaced();
85 }
86 
87 Layer::PropertyList
89 {
90  PropertyList list = SingleColourLayer::getProperties();
91  list.push_back("Vertical Scale");
92  list.push_back("Scale Units");
93  list.push_back("Plot Type");
94  return list;
95 }
96 
97 QString
98 RegionLayer::getPropertyLabel(const PropertyName &name) const
99 {
100  if (name == "Vertical Scale") return tr("Vertical Scale");
101  if (name == "Scale Units") return tr("Scale Units");
102  if (name == "Plot Type") return tr("Plot Type");
104 }
105 
106 Layer::PropertyType
107 RegionLayer::getPropertyType(const PropertyName &name) const
108 {
109  if (name == "Scale Units") return UnitsProperty;
110  if (name == "Vertical Scale") return ValueProperty;
111  if (name == "Plot Type") return ValueProperty;
112  if (name == "Colour" && m_plotStyle == PlotSegmentation) return ValueProperty;
114 }
115 
116 QString
117 RegionLayer::getPropertyGroupName(const PropertyName &name) const
118 {
119  if (name == "Vertical Scale" || name == "Scale Units") {
120  return tr("Scale");
121  }
123 }
124 
125 int
126 RegionLayer::getPropertyRangeAndValue(const PropertyName &name,
127  int *min, int *max, int *deflt) const
128 {
129  int val = 0;
130 
131  if (name == "Colour" && m_plotStyle == PlotSegmentation) {
132 
133  if (min) *min = 0;
134  if (max) *max = ColourMapper::getColourMapCount() - 1;
135  if (deflt) *deflt = 0;
136 
137  val = m_colourMap;
138 
139  } else if (name == "Plot Type") {
140 
141  if (min) *min = 0;
142  if (max) *max = 1;
143  if (deflt) *deflt = 0;
144 
145  val = int(m_plotStyle);
146 
147  } else if (name == "Vertical Scale") {
148 
149  if (min) *min = 0;
150  if (max) *max = 3;
151  if (deflt) *deflt = int(EqualSpaced);
152 
153  val = int(m_verticalScale);
154 
155  } else if (name == "Scale Units") {
156 
157  if (deflt) *deflt = 0;
158  if (m_model) {
159  val = UnitDatabase::getInstance()->getUnitId
160  (getScaleUnits());
161  }
162 
163  } else {
164 
165  val = SingleColourLayer::getPropertyRangeAndValue(name, min, max, deflt);
166  }
167 
168  return val;
169 }
170 
171 QString
172 RegionLayer::getPropertyValueLabel(const PropertyName &name,
173  int value) const
174 {
175  if (name == "Colour" && m_plotStyle == PlotSegmentation) {
176  return ColourMapper::getColourMapName(value);
177  } else if (name == "Plot Type") {
178 
179  switch (value) {
180  default:
181  case 0: return tr("Bars");
182  case 1: return tr("Segmentation");
183  }
184 
185  } else if (name == "Vertical Scale") {
186  switch (value) {
187  default:
188  case 0: return tr("Auto-Align");
189  case 1: return tr("Equal Spaced");
190  case 2: return tr("Linear");
191  case 3: return tr("Log");
192  }
193  }
194  return SingleColourLayer::getPropertyValueLabel(name, value);
195 }
196 
197 void
198 RegionLayer::setProperty(const PropertyName &name, int value)
199 {
200  if (name == "Colour" && m_plotStyle == PlotSegmentation) {
201  setFillColourMap(value);
202  } else if (name == "Plot Type") {
203  setPlotStyle(PlotStyle(value));
204  } else if (name == "Vertical Scale") {
206  } else if (name == "Scale Units") {
207  if (m_model) {
208  m_model->setScaleUnits
209  (UnitDatabase::getInstance()->getUnitById(value));
210  emit modelChanged();
211  }
212  } else {
213  return SingleColourLayer::setProperty(name, value);
214  }
215 }
216 
217 void
219 {
220  if (m_colourMap == map) return;
221  m_colourMap = map;
222  emit layerParametersChanged();
223 }
224 
225 void
227 {
228  if (m_plotStyle == style) return;
229  bool colourTypeChanged = (style == PlotSegmentation ||
231  m_plotStyle = style;
232  if (colourTypeChanged) {
234  }
235  emit layerParametersChanged();
236 }
237 
238 void
240 {
241  if (m_verticalScale == scale) return;
242  m_verticalScale = scale;
243  emit layerParametersChanged();
244 }
245 
246 bool
248 {
249  QPoint discard;
250  return !v->shouldIlluminateLocalFeatures(this, discard);
251 }
252 
253 void
255 {
256  m_spacingMap.clear();
257  m_distributionMap.clear();
258  if (!m_model) return;
259 
260 // SVDEBUG << "RegionLayer::recalcSpacing" << endl;
261 
262  for (RegionModel::PointList::const_iterator i = m_model->getPoints().begin();
263  i != m_model->getPoints().end(); ++i) {
264  m_distributionMap[i->value]++;
265 // SVDEBUG << "RegionLayer::recalcSpacing: value found: " << i->value << " (now have " << m_distributionMap[i->value] << " of this value)" << endl;
266  }
267 
268  int n = 0;
269 
270  for (SpacingMap::const_iterator i = m_distributionMap.begin();
271  i != m_distributionMap.end(); ++i) {
272  m_spacingMap[i->first] = n++;
273 // SVDEBUG << "RegionLayer::recalcSpacing: " << i->first << " -> " << m_spacingMap[i->first] << endl;
274  }
275 }
276 
277 bool
278 RegionLayer::getValueExtents(float &min, float &max,
279  bool &logarithmic, QString &unit) const
280 {
281  if (!m_model) return false;
282  min = m_model->getValueMinimum();
283  max = m_model->getValueMaximum();
284  unit = getScaleUnits();
285 
286  if (m_verticalScale == LogScale) logarithmic = true;
287 
288  return true;
289 }
290 
291 bool
292 RegionLayer::getDisplayExtents(float &min, float &max) const
293 {
294  if (!m_model ||
296  m_verticalScale == EqualSpaced) return false;
297 
298  min = m_model->getValueMinimum();
299  max = m_model->getValueMaximum();
300 
301  return true;
302 }
303 
304 RegionModel::PointList
306 {
307  if (!m_model) return RegionModel::PointList();
308 
309  long frame = v->getFrameForX(x);
310 
311  RegionModel::PointList onPoints =
312  m_model->getPoints(frame);
313 
314  if (!onPoints.empty()) {
315  return onPoints;
316  }
317 
318  RegionModel::PointList prevPoints =
319  m_model->getPreviousPoints(frame);
320  RegionModel::PointList nextPoints =
321  m_model->getNextPoints(frame);
322 
323  RegionModel::PointList usePoints = prevPoints;
324 
325  if (prevPoints.empty()) {
326  usePoints = nextPoints;
327  } else if (long(prevPoints.begin()->frame) < v->getStartFrame() &&
328  !(nextPoints.begin()->frame > v->getEndFrame())) {
329  usePoints = nextPoints;
330  } else if (long(nextPoints.begin()->frame) - frame <
331  frame - long(prevPoints.begin()->frame)) {
332  usePoints = nextPoints;
333  }
334 
335  if (!usePoints.empty()) {
336  int fuzz = 2;
337  int px = v->getXForFrame(usePoints.begin()->frame);
338  if ((px > x && px - x > fuzz) ||
339  (px < x && x - px > fuzz + 1)) {
340  usePoints.clear();
341  }
342  }
343 
344  return usePoints;
345 }
346 
347 bool
348 RegionLayer::getPointToDrag(View *v, int x, int y, RegionModel::Point &p) const
349 {
350  if (!m_model) return false;
351 
352  long frame = v->getFrameForX(x);
353 
354  RegionModel::PointList onPoints = m_model->getPoints(frame);
355  if (onPoints.empty()) return false;
356 
357  int nearestDistance = -1;
358 
359  for (RegionModel::PointList::const_iterator i = onPoints.begin();
360  i != onPoints.end(); ++i) {
361 
362  int distance = getYForValue(v, (*i).value) - y;
363  if (distance < 0) distance = -distance;
364  if (nearestDistance == -1 || distance < nearestDistance) {
365  nearestDistance = distance;
366  p = *i;
367  }
368  }
369 
370  return true;
371 }
372 
373 QString
375 {
376  if (!m_model) return "";
377  RegionModel::PointList points = m_model->getPreviousPoints(frame);
378  for (RegionModel::PointList::const_iterator i = points.begin();
379  i != points.end(); ++i) {
380  if (i->label != "") return i->label;
381  }
382  return "";
383 }
384 
385 QString
387 {
388  int x = pos.x();
389 
390  if (!m_model || !m_model->getSampleRate()) return "";
391 
392  RegionModel::PointList points = getLocalPoints(v, x);
393 
394  if (points.empty()) {
395  if (!m_model->isReady()) {
396  return tr("In progress");
397  } else {
398  return tr("No local points");
399  }
400  }
401 
402  RegionRec region(0);
403  RegionModel::PointList::iterator i;
404 
407 
408  for (i = points.begin(); i != points.end(); ++i) {
409 
410  int y = getYForValue(v, i->value);
411  int h = 3;
412 
413  if (m_model->getValueQuantization() != 0.0) {
414  h = y - getYForValue(v, i->value + m_model->getValueQuantization());
415  if (h < 3) h = 3;
416  }
417 
418  if (pos.y() >= y - h && pos.y() <= y) {
419  region = *i;
420  break;
421  }
422  }
423 
424  if (i == points.end()) return tr("No local points");
425 
426  RealTime rt = RealTime::frame2RealTime(region.frame,
427  m_model->getSampleRate());
428  RealTime rd = RealTime::frame2RealTime(region.duration,
429  m_model->getSampleRate());
430 
431  QString valueText;
432 
433  valueText = tr("%1 %2").arg(region.value).arg(getScaleUnits());
434 
435  QString text;
436 
437  if (region.label == "") {
438  text = QString(tr("Time:\t%1\nValue:\t%2\nDuration:\t%3\nNo label"))
439  .arg(rt.toText(true).c_str())
440  .arg(valueText)
441  .arg(rd.toText(true).c_str());
442  } else {
443  text = QString(tr("Time:\t%1\nValue:\t%2\nDuration:\t%3\nLabel:\t%4"))
444  .arg(rt.toText(true).c_str())
445  .arg(valueText)
446  .arg(rd.toText(true).c_str())
447  .arg(region.label);
448  }
449 
450  pos = QPoint(v->getXForFrame(region.frame),
451  getYForValue(v, region.value));
452  return text;
453 }
454 
455 bool
457  int &resolution,
458  SnapType snap) const
459 {
460  if (!m_model) {
461  return Layer::snapToFeatureFrame(v, frame, resolution, snap);
462  }
463 
464  resolution = m_model->getResolution();
465  RegionModel::PointList points;
466 
467  if (snap == SnapNeighbouring) {
468 
469  points = getLocalPoints(v, v->getXForFrame(frame));
470  if (points.empty()) return false;
471  frame = points.begin()->frame;
472  return true;
473  }
474 
475  points = m_model->getPoints(frame, frame);
476  int snapped = frame;
477  bool found = false;
478 
479  for (RegionModel::PointList::const_iterator i = points.begin();
480  i != points.end(); ++i) {
481 
482  if (snap == SnapRight) {
483 
484  // The best frame to snap to is the end frame of whichever
485  // feature we would have snapped to the start frame of if
486  // we had been snapping left.
487 
488  if (i->frame <= frame) {
489  if (i->frame + i->duration > frame) {
490  snapped = i->frame + i->duration;
491  found = true; // don't break, as the next may be better
492  }
493  } else {
494  if (!found) {
495  snapped = i->frame;
496  found = true;
497  }
498  break;
499  }
500 
501  } else if (snap == SnapLeft) {
502 
503  if (i->frame <= frame) {
504  snapped = i->frame;
505  found = true; // don't break, as the next may be better
506  } else {
507  break;
508  }
509 
510  } else { // nearest
511 
512  RegionModel::PointList::const_iterator j = i;
513  ++j;
514 
515  if (j == points.end()) {
516 
517  snapped = i->frame;
518  found = true;
519  break;
520 
521  } else if (j->frame >= frame) {
522 
523  if (j->frame - frame < frame - i->frame) {
524  snapped = j->frame;
525  } else {
526  snapped = i->frame;
527  }
528  found = true;
529  break;
530  }
531  }
532  }
533 
534  frame = snapped;
535  return found;
536 }
537 
538 bool
540  int &resolution,
541  SnapType snap) const
542 {
543  if (!m_model) {
544  return Layer::snapToSimilarFeature(v, frame, resolution, snap);
545  }
546 
547  resolution = m_model->getResolution();
548 
549  const RegionModel::PointList &points = m_model->getPoints();
550  RegionModel::PointList close = m_model->getPoints(frame, frame);
551 
552  RegionModel::PointList::const_iterator i;
553 
554  int matchframe = frame;
555  float matchvalue = 0.f;
556 
557  for (i = close.begin(); i != close.end(); ++i) {
558  if (i->frame > frame) break;
559  matchvalue = i->value;
560  matchframe = i->frame;
561  }
562 
563  int snapped = frame;
564  bool found = false;
565  bool distant = false;
566  float epsilon = 0.0001;
567 
568  i = close.begin();
569 
570  // Scan through the close points first, then the more distant ones
571  // if no suitable close one is found. So the while-termination
572  // condition here can only happen once i has passed through the
573  // whole of the close container and then the whole of the separate
574  // points container. The two iterators are totally distinct, but
575  // have the same type so we cheekily use the same variable and a
576  // single loop for both.
577 
578  while (i != points.end()) {
579 
580  if (!distant) {
581  if (i == close.end()) {
582  // switch from the close container to the points container
583  i = points.begin();
584  distant = true;
585  }
586  }
587 
588  if (snap == SnapRight) {
589 
590  if (i->frame > matchframe &&
591  fabsf(i->value - matchvalue) < epsilon) {
592  snapped = i->frame;
593  found = true;
594  break;
595  }
596 
597  } else if (snap == SnapLeft) {
598 
599  if (i->frame < matchframe) {
600  if (fabsf(i->value - matchvalue) < epsilon) {
601  snapped = i->frame;
602  found = true; // don't break, as the next may be better
603  }
604  } else if (found || distant) {
605  break;
606  }
607 
608  } else {
609  // no other snap types supported
610  }
611 
612  ++i;
613  }
614 
615  frame = snapped;
616  return found;
617 }
618 
619 QString
621 {
622  if (m_model) return m_model->getScaleUnits();
623  else return "";
624 }
625 
626 void
627 RegionLayer::getScaleExtents(View *v, float &min, float &max, bool &log) const
628 {
629  min = 0.0;
630  max = 0.0;
631  log = false;
632 
633  QString queryUnits;
634  queryUnits = getScaleUnits();
635 
637 
638  if (!v->getValueExtents(queryUnits, min, max, log)) {
639 
640  min = m_model->getValueMinimum();
641  max = m_model->getValueMaximum();
642 
643 // cerr << "RegionLayer[" << this << "]::getScaleExtents: min = " << min << ", max = " << max << ", log = " << log << endl;
644 
645  } else if (log) {
646 
647  LogRange::mapRange(min, max);
648 
649 // cerr << "RegionLayer[" << this << "]::getScaleExtents: min = " << min << ", max = " << max << ", log = " << log << endl;
650 
651  }
652 
653  } else if (m_verticalScale == EqualSpaced) {
654 
655  if (!m_spacingMap.empty()) {
656  SpacingMap::const_iterator i = m_spacingMap.begin();
657  min = i->second;
658  i = m_spacingMap.end();
659  --i;
660  max = i->second;
661 // cerr << "RegionLayer[" << this << "]::getScaleExtents: equal spaced; min = " << min << ", max = " << max << ", log = " << log << endl;
662  }
663 
664  } else {
665 
666  min = m_model->getValueMinimum();
667  max = m_model->getValueMaximum();
668 
669  if (m_verticalScale == LogScale) {
670  LogRange::mapRange(min, max);
671  log = true;
672  }
673  }
674 
675  if (max == min) max = min + 1.0;
676 }
677 
678 int
680 {
681  int h = v->height();
682  int n = m_spacingMap.size();
683  // this maps from i (spacing of the value from the spacing
684  // map) and n (number of region types) to y
685  int y = h - (((h * i) / n) + (h / (2 * n)));
686  return y;
687 }
688 
689 float
691 {
692  // we return an inexact result here (float rather than int)
693  int h = v->height();
694  int n = m_spacingMap.size();
695  // from y = h - ((h * i) / n) + (h / (2 * n)) as above (vh taking place of i)
696  float vh = float(2*h*n - h - 2*n*y) / float(2*h);
697  return vh;
698 }
699 
700 int
701 RegionLayer::getYForValue(View *v, float val) const
702 {
703  float min = 0.0, max = 0.0;
704  bool logarithmic = false;
705  int h = v->height();
706 
707  if (m_verticalScale == EqualSpaced) {
708 
709  if (m_spacingMap.empty()) return h/2;
710 
711  SpacingMap::const_iterator i = m_spacingMap.lower_bound(val);
713 
714  int y = spacingIndexToY(v, i->second);
715 
716 // SVDEBUG << "RegionLayer::getYForValue: value " << val << " -> i->second " << i->second << " -> y " << y << endl;
717  return y;
718 
719 
720  } else {
721 
722  getScaleExtents(v, min, max, logarithmic);
723 
724 // cerr << "RegionLayer[" << this << "]::getYForValue(" << val << "): min = " << min << ", max = " << max << ", log = " << logarithmic << endl;
725 // cerr << "h = " << h << ", margin = " << margin << endl;
726 
727  if (logarithmic) {
728  val = LogRange::map(val);
729  }
730 
731  return int(h - ((val - min) * h) / (max - min));
732  }
733 }
734 
735 float
737 {
738  return getValueForY(v, y, -1);
739 }
740 
741 float
742 RegionLayer::getValueForY(View *v, int y, int avoid) const
743 {
744  float min = 0.0, max = 0.0;
745  bool logarithmic = false;
746  int h = v->height();
747 
748  if (m_verticalScale == EqualSpaced) {
749 
750  // if we're equal spaced, we probably want to snap to the
751  // nearest item when close to it, and give some notification
752  // that we're doing so
753 
754  if (m_spacingMap.empty()) return 1.f;
755 
756  // n is the number of distinct regions. if we are close to
757  // one of the m/n divisions in the y scale, we should snap to
758  // the value of the mth region.
759 
760  float vh = yToSpacingIndex(v, y);
761 
762  // spacings in the map are integral, so find the closest one,
763  // map it back to its y coordinate, and see how far we are
764  // from it
765 
766  int n = m_spacingMap.size();
767  int ivh = lrintf(vh);
768  if (ivh < 0) ivh = 0;
769  if (ivh > n-1) ivh = n-1;
770  int iy = spacingIndexToY(v, ivh);
771 
772  int dist = iy - y;
773  int gap = h / n; // between region lines
774 
775 // cerr << "getValueForY: y = " << y << ", vh = " << vh << ", ivh = " << ivh << " of " << n << ", iy = " << iy << ", dist = " << dist << ", gap = " << gap << endl;
776 
777  SpacingMap::const_iterator i = m_spacingMap.begin();
778  while (i != m_spacingMap.end()) {
779  if (i->second == ivh) break;
780  ++i;
781  }
782  if (i == m_spacingMap.end()) i = m_spacingMap.begin();
783 
784 // cerr << "nearest existing value = " << i->first << " at " << iy << endl;
785 
786  float val = 0;
787 
788 // cerr << "note: avoid = " << avoid << ", i->second = " << i->second << endl;
789 
790  if (dist < -gap/3 &&
791  ((avoid == -1) ||
792  (avoid != i->second && avoid != i->second - 1))) {
793  // bisect gap to prior
794  if (i == m_spacingMap.begin()) {
795  val = i->first - 1.f;
796 // cerr << "extended down to " << val << endl;
797  } else {
798  SpacingMap::const_iterator j = i;
799  --j;
800  val = (i->first + j->first) / 2;
801 // cerr << "bisected down to " << val << endl;
802  }
803  } else if (dist > gap/3 &&
804  ((avoid == -1) ||
805  (avoid != i->second && avoid != i->second + 1))) {
806  // bisect gap to following
807  SpacingMap::const_iterator j = i;
808  ++j;
809  if (j == m_spacingMap.end()) {
810  val = i->first + 1.f;
811 // cerr << "extended up to " << val << endl;
812  } else {
813  val = (i->first + j->first) / 2;
814 // cerr << "bisected up to " << val << endl;
815  }
816  } else {
817  // snap
818  val = i->first;
819 // cerr << "snapped to " << val << endl;
820  }
821 
822  return val;
823 
824  } else {
825 
826  getScaleExtents(v, min, max, logarithmic);
827 
828  float val = min + (float(h - y) * float(max - min)) / h;
829 
830  if (logarithmic) {
831  val = powf(10.f, val);
832  }
833 
834  return val;
835  }
836 }
837 
838 QColor
840 {
841  float min, max;
842  bool log;
843  getScaleExtents(v, min, max, log);
844 
845  if (min > max) std::swap(min, max);
846  if (max == min) max = min + 1;
847 
848  if (log) {
849  LogRange::mapRange(min, max);
850  val = LogRange::map(val);
851  }
852 
853 // SVDEBUG << "RegionLayer::getColourForValue: min " << min << ", max "
854 // << max << ", log " << log << ", value " << val << endl;
855 
856  QColor solid = ColourMapper(m_colourMap, min, max).map(val);
857  return QColor(solid.red(), solid.green(), solid.blue(), 120);
858 }
859 
860 int
861 RegionLayer::getDefaultColourHint(bool darkbg, bool &impose)
862 {
863  impose = false;
865  (QString(darkbg ? "Bright Blue" : "Blue"));
866 }
867 
868 void
869 RegionLayer::paint(View *v, QPainter &paint, QRect rect) const
870 {
871  if (!m_model || !m_model->isOK()) return;
872 
873  int sampleRate = m_model->getSampleRate();
874  if (!sampleRate) return;
875 
876 // Profiler profiler("RegionLayer::paint", true);
877 
878  int x0 = rect.left() - 40, x1 = rect.right();
879  long frame0 = v->getFrameForX(x0);
880  long frame1 = v->getFrameForX(x1);
881 
882  RegionModel::PointList points(m_model->getPoints(frame0, frame1));
883  if (points.empty()) return;
884 
885  paint.setPen(getBaseQColor());
886 
887  QColor brushColour(getBaseQColor());
888  brushColour.setAlpha(80);
889 
890 // SVDEBUG << "RegionLayer::paint: resolution is "
891 // << m_model->getResolution() << " frames" << endl;
892 
893  float min = m_model->getValueMinimum();
894  float max = m_model->getValueMaximum();
895  if (max == min) max = min + 1.0;
896 
897  QPoint localPos;
898  RegionModel::Point illuminatePoint(0);
899  bool shouldIlluminate = false;
900 
901  if (v->shouldIlluminateLocalFeatures(this, localPos)) {
902  shouldIlluminate = getPointToDrag(v, localPos.x(), localPos.y(),
903  illuminatePoint);
904  }
905 
906  paint.save();
907  paint.setRenderHint(QPainter::Antialiasing, false);
908 
911 
914 
915  int fontHeight = paint.fontMetrics().height();
916 
917  for (RegionModel::PointList::const_iterator i = points.begin();
918  i != points.end(); ++i) {
919 
920  const RegionModel::Point &p(*i);
921 
922  int x = v->getXForFrame(p.frame);
923  int y = getYForValue(v, p.value);
924  int w = v->getXForFrame(p.frame + p.duration) - x;
925  int h = 9;
926  int ex = x + w;
927 
928  RegionModel::PointList::const_iterator j = i;
929  ++j;
930 
931  if (j != points.end()) {
932  const RegionModel::Point &q(*j);
933  int nx = v->getXForFrame(q.frame);
934  if (nx < ex) ex = nx;
935  }
936 
937  if (m_model->getValueQuantization() != 0.0) {
938  h = y - getYForValue(v, p.value + m_model->getValueQuantization());
939  if (h < 3) h = 3;
940  }
941 
942  if (w < 1) w = 1;
943 
944  if (m_plotStyle == PlotSegmentation) {
945  paint.setPen(getForegroundQColor(v));
946  paint.setBrush(getColourForValue(v, p.value));
947  } else {
948  paint.setPen(getBaseQColor());
949  paint.setBrush(brushColour);
950  }
951 
952  if (m_plotStyle == PlotSegmentation) {
953 
954  if (ex <= x) continue;
955 
956  if (!shouldIlluminate ||
957  // "illuminatePoint != p"
958  RegionModel::Point::Comparator()(illuminatePoint, p) ||
959  RegionModel::Point::Comparator()(p, illuminatePoint)) {
960 
961  paint.setPen(QPen(getForegroundQColor(v), 1));
962  paint.drawLine(x, 0, x, v->height());
963  paint.setPen(Qt::NoPen);
964 
965  } else {
966  paint.setPen(QPen(getForegroundQColor(v), 2));
967  }
968 
969  paint.drawRect(x, -1, ex - x, v->height() + 2);
970 
971  } else {
972 
973  if (shouldIlluminate &&
974  // "illuminatePoint == p"
975  !RegionModel::Point::Comparator()(illuminatePoint, p) &&
976  !RegionModel::Point::Comparator()(p, illuminatePoint)) {
977 
978  paint.setPen(v->getForeground());
979  paint.setBrush(v->getForeground());
980 
981  QString vlabel = QString("%1%2").arg(p.value).arg(getScaleUnits());
983  x - paint.fontMetrics().width(vlabel) - 2,
984  y + paint.fontMetrics().height()/2
985  - paint.fontMetrics().descent(),
986  vlabel, View::OutlinedText);
987 
988  QString hlabel = RealTime::frame2RealTime
989  (p.frame, m_model->getSampleRate()).toText(true).c_str();
991  x,
992  y - h/2 - paint.fontMetrics().descent() - 2,
993  hlabel, View::OutlinedText);
994  }
995 
996  paint.drawLine(x, y-1, x + w, y-1);
997  paint.drawLine(x, y+1, x + w, y+1);
998  paint.drawLine(x, y - h/2, x, y + h/2);
999  paint.drawLine(x+w, y - h/2, x + w, y + h/2);
1000  }
1001  }
1002 
1003  int nextLabelMinX = -100;
1004  int lastLabelY = 0;
1005 
1006  for (RegionModel::PointList::const_iterator i = points.begin();
1007  i != points.end(); ++i) {
1008 
1009  const RegionModel::Point &p(*i);
1010 
1011  int x = v->getXForFrame(p.frame);
1012  int y = getYForValue(v, p.value);
1013 
1014  bool illuminated = false;
1015 
1016  if (m_plotStyle != PlotSegmentation) {
1017 
1018  if (shouldIlluminate &&
1019  // "illuminatePoint == p"
1020  !RegionModel::Point::Comparator()(illuminatePoint, p) &&
1021  !RegionModel::Point::Comparator()(p, illuminatePoint)) {
1022 
1023  illuminated = true;
1024  }
1025  }
1026 
1027  if (!illuminated) {
1028  QString label = p.label;
1029  if (label == "") {
1030  label = QString("%1%2").arg(p.value).arg(getScaleUnits());
1031  }
1032 
1033  int labelX, labelY;
1034 
1035  if (m_plotStyle != PlotSegmentation) {
1036  labelX = x - paint.fontMetrics().width(label) - 2;
1037  labelY = y + paint.fontMetrics().height()/2
1038  - paint.fontMetrics().descent();
1039  } else {
1040  labelX = x + 5;
1041  labelY = v->getTextLabelHeight(this, paint);
1042  if (labelX < nextLabelMinX) {
1043  if (lastLabelY < v->height()/2) {
1044  labelY = lastLabelY + fontHeight;
1045  }
1046  }
1047  lastLabelY = labelY;
1048  nextLabelMinX = labelX + paint.fontMetrics().width(label);
1049  }
1050 
1051  v->drawVisibleText(paint, labelX, labelY, label, View::OutlinedText);
1052  }
1053  }
1054 
1055  paint.restore();
1056 }
1057 
1058 int
1059 RegionLayer::getVerticalScaleWidth(View *v, bool, QPainter &paint) const
1060 {
1061  if (!m_model ||
1064  return 0;
1065  } else if (m_plotStyle == PlotSegmentation) {
1066  if (m_verticalScale == LogScale) {
1067  return LogColourScale().getWidth(v, paint);
1068  } else {
1069  return LinearColourScale().getWidth(v, paint);
1070  }
1071  } else {
1072  if (m_verticalScale == LogScale) {
1073  return LogNumericalScale().getWidth(v, paint);
1074  } else {
1075  return LinearNumericalScale().getWidth(v, paint);
1076  }
1077  }
1078 }
1079 
1080 void
1081 RegionLayer::paintVerticalScale(View *v, bool, QPainter &paint, QRect) const
1082 {
1083  if (!m_model || m_model->getPoints().empty()) return;
1084 
1085  QString unit;
1086  float min, max;
1087  bool logarithmic;
1088 
1089  int w = getVerticalScaleWidth(v, false, paint);
1090 
1091  if (m_plotStyle == PlotSegmentation) {
1092 
1093  getValueExtents(min, max, logarithmic, unit);
1094 
1095  if (logarithmic) {
1096  LogRange::mapRange(min, max);
1097  LogColourScale().paintVertical(v, this, paint, 0, min, max);
1098  } else {
1099  LinearColourScale().paintVertical(v, this, paint, 0, min, max);
1100  }
1101 
1102  } else {
1103 
1104  getScaleExtents(v, min, max, logarithmic);
1105 
1106  if (logarithmic) {
1107  LogNumericalScale().paintVertical(v, this, paint, 0, min, max);
1108  } else {
1109  LinearNumericalScale().paintVertical(v, this, paint, 0, min, max);
1110  }
1111  }
1112 
1113  if (getScaleUnits() != "") {
1114  int mw = w - 5;
1115  paint.drawText(5,
1116  5 + paint.fontMetrics().ascent(),
1118  paint.fontMetrics(),
1119  mw));
1120  }
1121 }
1122 
1123 void
1124 RegionLayer::drawStart(View *v, QMouseEvent *e)
1125 {
1126  if (!m_model) return;
1127 
1128  long frame = v->getFrameForX(e->x());
1129  if (frame < 0) frame = 0;
1130  frame = frame / m_model->getResolution() * m_model->getResolution();
1131 
1132  float value = getValueForY(v, e->y());
1133 
1134  m_editingPoint = RegionModel::Point(frame, value, 0, "");
1136 
1138  m_editingCommand = new RegionModel::EditCommand(m_model,
1139  tr("Draw Region"));
1140  m_editingCommand->addPoint(m_editingPoint);
1141 
1142  recalcSpacing();
1143 
1144  m_editing = true;
1145 }
1146 
1147 void
1148 RegionLayer::drawDrag(View *v, QMouseEvent *e)
1149 {
1150  if (!m_model || !m_editing) return;
1151 
1152  long frame = v->getFrameForX(e->x());
1153  if (frame < 0) frame = 0;
1154  frame = frame / m_model->getResolution() * m_model->getResolution();
1155 
1156  float newValue = m_editingPoint.value;
1157  if (m_verticalScale != EqualSpaced) newValue = getValueForY(v, e->y());
1158 
1159  long newFrame = m_editingPoint.frame;
1160  long newDuration = frame - newFrame;
1161  if (newDuration < 0) {
1162  newFrame = frame;
1163  newDuration = -newDuration;
1164  } else if (newDuration == 0) {
1165  newDuration = 1;
1166  }
1167 
1168  m_editingCommand->deletePoint(m_editingPoint);
1169  m_editingPoint.frame = newFrame;
1170  m_editingPoint.value = newValue;
1171  m_editingPoint.duration = newDuration;
1172  m_editingCommand->addPoint(m_editingPoint);
1173 
1174  recalcSpacing();
1175 }
1176 
1177 void
1178 RegionLayer::drawEnd(View *, QMouseEvent *)
1179 {
1180  if (!m_model || !m_editing) return;
1182  m_editingCommand = 0;
1183  m_editing = false;
1184 
1185  recalcSpacing();
1186 }
1187 
1188 void
1189 RegionLayer::eraseStart(View *v, QMouseEvent *e)
1190 {
1191  if (!m_model) return;
1192 
1193  if (!getPointToDrag(v, e->x(), e->y(), m_editingPoint)) return;
1194 
1195  if (m_editingCommand) {
1197  m_editingCommand = 0;
1198  }
1199 
1200  m_editing = true;
1201  recalcSpacing();
1202 }
1203 
1204 void
1205 RegionLayer::eraseDrag(View *, QMouseEvent *)
1206 {
1207 }
1208 
1209 void
1210 RegionLayer::eraseEnd(View *v, QMouseEvent *e)
1211 {
1212  if (!m_model || !m_editing) return;
1213 
1214  m_editing = false;
1215 
1216  RegionModel::Point p(0);
1217  if (!getPointToDrag(v, e->x(), e->y(), p)) return;
1218  if (p.frame != m_editingPoint.frame || p.value != m_editingPoint.value) return;
1219 
1220  m_editingCommand = new RegionModel::EditCommand
1221  (m_model, tr("Erase Region"));
1222 
1223  m_editingCommand->deletePoint(m_editingPoint);
1224 
1226  m_editingCommand = 0;
1227  m_editing = false;
1228  recalcSpacing();
1229 }
1230 
1231 void
1232 RegionLayer::editStart(View *v, QMouseEvent *e)
1233 {
1234  if (!m_model) return;
1235 
1236  if (!getPointToDrag(v, e->x(), e->y(), m_editingPoint)) {
1237  return;
1238  }
1239 
1242 
1244 
1245  if (m_editingCommand) {
1247  m_editingCommand = 0;
1248  }
1249 
1250  m_editing = true;
1251  m_dragStartX = e->x();
1252  m_dragStartY = e->y();
1253  recalcSpacing();
1254 }
1255 
1256 void
1257 RegionLayer::editDrag(View *v, QMouseEvent *e)
1258 {
1259  if (!m_model || !m_editing) return;
1260 
1261  int xdist = e->x() - m_dragStartX;
1262  int ydist = e->y() - m_dragStartY;
1263  int newx = m_dragPointX + xdist;
1264  int newy = m_dragPointY + ydist;
1265 
1266  long frame = v->getFrameForX(newx);
1267  if (frame < 0) frame = 0;
1268  frame = frame / m_model->getResolution() * m_model->getResolution();
1269 
1270  // Do not bisect between two values, if one of those values is
1271  // that of the point we're actually moving ...
1272  int avoid = m_spacingMap[m_editingPoint.value];
1273 
1274  // ... unless there are other points with the same value
1275  if (m_distributionMap[m_editingPoint.value] > 1) avoid = -1;
1276 
1277  float value = getValueForY(v, newy, avoid);
1278 
1279  if (!m_editingCommand) {
1280  m_editingCommand = new RegionModel::EditCommand(m_model,
1281  tr("Drag Region"));
1282  }
1283 
1284  m_editingCommand->deletePoint(m_editingPoint);
1285  m_editingPoint.frame = frame;
1286  m_editingPoint.value = value;
1287  m_editingCommand->addPoint(m_editingPoint);
1288  recalcSpacing();
1289 }
1290 
1291 void
1292 RegionLayer::editEnd(View *, QMouseEvent *)
1293 {
1294  if (!m_model || !m_editing) return;
1295 
1296  if (m_editingCommand) {
1297 
1298  QString newName = m_editingCommand->getName();
1299 
1300  if (m_editingPoint.frame != m_originalPoint.frame) {
1301  if (m_editingPoint.value != m_originalPoint.value) {
1302  newName = tr("Edit Region");
1303  } else {
1304  newName = tr("Relocate Region");
1305  }
1306  } else {
1307  newName = tr("Change Point Value");
1308  }
1309 
1310  m_editingCommand->setName(newName);
1312  }
1313 
1314  m_editingCommand = 0;
1315  m_editing = false;
1316  recalcSpacing();
1317 }
1318 
1319 bool
1320 RegionLayer::editOpen(View *v, QMouseEvent *e)
1321 {
1322  if (!m_model) return false;
1323 
1324  RegionModel::Point region(0);
1325  if (!getPointToDrag(v, e->x(), e->y(), region)) return false;
1326 
1327  ItemEditDialog *dialog = new ItemEditDialog
1328  (m_model->getSampleRate(),
1333  getScaleUnits());
1334 
1335  dialog->setFrameTime(region.frame);
1336  dialog->setValue(region.value);
1337  dialog->setFrameDuration(region.duration);
1338  dialog->setText(region.label);
1339 
1340  if (dialog->exec() == QDialog::Accepted) {
1341 
1342  RegionModel::Point newRegion = region;
1343  newRegion.frame = dialog->getFrameTime();
1344  newRegion.value = dialog->getValue();
1345  newRegion.duration = dialog->getFrameDuration();
1346  newRegion.label = dialog->getText();
1347 
1348  RegionModel::EditCommand *command = new RegionModel::EditCommand
1349  (m_model, tr("Edit Region"));
1350  command->deletePoint(region);
1351  command->addPoint(newRegion);
1352  finish(command);
1353  }
1354 
1355  delete dialog;
1356  recalcSpacing();
1357  return true;
1358 }
1359 
1360 void
1361 RegionLayer::moveSelection(Selection s, int newStartFrame)
1362 {
1363  if (!m_model) return;
1364 
1365  RegionModel::EditCommand *command =
1366  new RegionModel::EditCommand(m_model, tr("Drag Selection"));
1367 
1368  RegionModel::PointList points =
1369  m_model->getPoints(s.getStartFrame(), s.getEndFrame());
1370 
1371  for (RegionModel::PointList::iterator i = points.begin();
1372  i != points.end(); ++i) {
1373 
1374  if (s.contains(i->frame)) {
1375  RegionModel::Point newPoint(*i);
1376  newPoint.frame = i->frame + newStartFrame - s.getStartFrame();
1377  command->deletePoint(*i);
1378  command->addPoint(newPoint);
1379  }
1380  }
1381 
1382  finish(command);
1383  recalcSpacing();
1384 }
1385 
1386 void
1387 RegionLayer::resizeSelection(Selection s, Selection newSize)
1388 {
1389  if (!m_model) return;
1390 
1391  RegionModel::EditCommand *command =
1392  new RegionModel::EditCommand(m_model, tr("Resize Selection"));
1393 
1394  RegionModel::PointList points =
1395  m_model->getPoints(s.getStartFrame(), s.getEndFrame());
1396 
1397  double ratio =
1398  double(newSize.getEndFrame() - newSize.getStartFrame()) /
1399  double(s.getEndFrame() - s.getStartFrame());
1400 
1401  for (RegionModel::PointList::iterator i = points.begin();
1402  i != points.end(); ++i) {
1403 
1404  if (s.contains(i->frame)) {
1405 
1406  double targetStart = i->frame;
1407  targetStart = newSize.getStartFrame() +
1408  double(targetStart - s.getStartFrame()) * ratio;
1409 
1410  double targetEnd = i->frame + i->duration;
1411  targetEnd = newSize.getStartFrame() +
1412  double(targetEnd - s.getStartFrame()) * ratio;
1413 
1414  RegionModel::Point newPoint(*i);
1415  newPoint.frame = lrint(targetStart);
1416  newPoint.duration = lrint(targetEnd - targetStart);
1417  command->deletePoint(*i);
1418  command->addPoint(newPoint);
1419  }
1420  }
1421 
1422  finish(command);
1423  recalcSpacing();
1424 }
1425 
1426 void
1428 {
1429  if (!m_model) return;
1430 
1431  RegionModel::EditCommand *command =
1432  new RegionModel::EditCommand(m_model, tr("Delete Selected Points"));
1433 
1434  RegionModel::PointList points =
1435  m_model->getPoints(s.getStartFrame(), s.getEndFrame());
1436 
1437  for (RegionModel::PointList::iterator i = points.begin();
1438  i != points.end(); ++i) {
1439 
1440  if (s.contains(i->frame)) {
1441  command->deletePoint(*i);
1442  }
1443  }
1444 
1445  finish(command);
1446  recalcSpacing();
1447 }
1448 
1449 void
1450 RegionLayer::copy(View *v, Selection s, Clipboard &to)
1451 {
1452  if (!m_model) return;
1453 
1454  RegionModel::PointList points =
1455  m_model->getPoints(s.getStartFrame(), s.getEndFrame());
1456 
1457  for (RegionModel::PointList::iterator i = points.begin();
1458  i != points.end(); ++i) {
1459  if (s.contains(i->frame)) {
1460  Clipboard::Point point(i->frame, i->value, i->duration, i->label);
1461  point.setReferenceFrame(alignToReference(v, i->frame));
1462  to.addPoint(point);
1463  }
1464  }
1465 }
1466 
1467 bool
1468 RegionLayer::paste(View *v, const Clipboard &from, int /* frameOffset */, bool /* interactive */)
1469 {
1470  if (!m_model) return false;
1471 
1472  const Clipboard::PointList &points = from.getPoints();
1473 
1474  bool realign = false;
1475 
1476  if (clipboardHasDifferentAlignment(v, from)) {
1477 
1478  QMessageBox::StandardButton button =
1479  QMessageBox::question(v, tr("Re-align pasted items?"),
1480  tr("The items you are pasting came from a layer with different source material from this one. Do you want to re-align them in time, to match the source material for this layer?"),
1481  QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel,
1482  QMessageBox::Yes);
1483 
1484  if (button == QMessageBox::Cancel) {
1485  return false;
1486  }
1487 
1488  if (button == QMessageBox::Yes) {
1489  realign = true;
1490  }
1491  }
1492 
1493  RegionModel::EditCommand *command =
1494  new RegionModel::EditCommand(m_model, tr("Paste"));
1495 
1496  for (Clipboard::PointList::const_iterator i = points.begin();
1497  i != points.end(); ++i) {
1498 
1499  if (!i->haveFrame()) continue;
1500  int frame = 0;
1501 
1502  if (!realign) {
1503 
1504  frame = i->getFrame();
1505 
1506  } else {
1507 
1508  if (i->haveReferenceFrame()) {
1509  frame = i->getReferenceFrame();
1510  frame = alignFromReference(v, frame);
1511  } else {
1512  frame = i->getFrame();
1513  }
1514  }
1515 
1516  RegionModel::Point newPoint(frame);
1517 
1518  if (i->haveLabel()) newPoint.label = i->getLabel();
1519  if (i->haveValue()) newPoint.value = i->getValue();
1520  else newPoint.value = (m_model->getValueMinimum() +
1521  m_model->getValueMaximum()) / 2;
1522  if (i->haveDuration()) newPoint.duration = i->getDuration();
1523  else {
1524  int nextFrame = frame;
1525  Clipboard::PointList::const_iterator j = i;
1526  for (; j != points.end(); ++j) {
1527  if (!j->haveFrame()) continue;
1528  if (j != i) break;
1529  }
1530  if (j != points.end()) {
1531  nextFrame = j->getFrame();
1532  }
1533  if (nextFrame == frame) {
1534  newPoint.duration = m_model->getResolution();
1535  } else {
1536  newPoint.duration = nextFrame - frame;
1537  }
1538  }
1539 
1540  command->addPoint(newPoint);
1541  }
1542 
1543  finish(command);
1544  recalcSpacing();
1545  return true;
1546 }
1547 
1548 void
1549 RegionLayer::toXml(QTextStream &stream,
1550  QString indent, QString extraAttributes) const
1551 {
1552  SingleColourLayer::toXml(stream, indent, extraAttributes +
1553  QString(" verticalScale=\"%1\" plotStyle=\"%2\"")
1554  .arg(m_verticalScale)
1555  .arg(m_plotStyle));
1556 }
1557 
1558 void
1559 RegionLayer::setProperties(const QXmlAttributes &attributes)
1560 {
1562 
1563  bool ok;
1564  VerticalScale scale = (VerticalScale)
1565  attributes.value("verticalScale").toInt(&ok);
1566  if (ok) setVerticalScale(scale);
1567  PlotStyle style = (PlotStyle)
1568  attributes.value("plotStyle").toInt(&ok);
1569  if (ok) setPlotStyle(style);
1570 }
1571 
1572 
void getScaleExtents(View *, float &min, float &max, bool &log) const
int getFrameForX(int x) const
Return the closest frame to the given pixel x-coordinate.
Definition: View.cpp:363
virtual bool editOpen(View *v, QMouseEvent *)
Open an editor on the item under the mouse (e.g.
void setFrameTime(int frame)
virtual bool snapToFeatureFrame(View *v, int &frame, int &resolution, SnapType snap) const
Adjust the given frame to snap to the nearest feature, if possible.
float getValueForY(View *v, int y) const
void setPlotStyle(PlotStyle style)
virtual bool snapToFeatureFrame(View *, int &, int &resolution, SnapType) const
Adjust the given frame to snap to the nearest feature, if possible.
Definition: Layer.h:183
void connectSignals(const Model *)
Definition: Layer.cpp:49
virtual QColor getForeground() const
Definition: View.cpp:513
virtual bool snapToSimilarFeature(View *, int &, int &resolution, SnapType) const
Adjust the given frame to snap to the next feature that has "effectively" the same value as the featu...
Definition: Layer.h:207
virtual bool getValueExtents(QString unit, float &min, float &max, bool &log) const
Definition: View.cpp:185
void setProperties(const QXmlAttributes &attributes)
Set the particular properties of a layer (those specific to the subclass) from a set of XML attribute...
void modelReplaced()
static QString abbreviate(QString text, int maxLength, Policy policy=ElideEnd, bool fuzzy=true, QString ellipsis="")
Abbreviate the given text to the given maximum length (including ellipsis), using the given abbreviat...
Definition: TextAbbrev.cpp:74
virtual void deleteSelection(Selection s)
virtual void drawStart(View *v, QMouseEvent *)
int m_dragStartX
Definition: RegionLayer.h:152
void paintVertical(View *v, const ColourScaleLayer *layer, QPainter &paint, int x0, float minf, float maxf)
virtual void toXml(QTextStream &stream, QString indent="", QString extraAttributes="") const
Convert the layer's data (though not those of the model it refers to) into XML for file output.
bool m_editing
Definition: RegionLayer.h:149
virtual QString getFeatureDescription(View *v, QPoint &) const
int m_dragStartY
Definition: RegionLayer.h:153
virtual void editEnd(View *v, QMouseEvent *)
int m_dragPointX
Definition: RegionLayer.h:150
RegionModel::Point m_originalPoint
Definition: RegionLayer.h:154
virtual bool shouldIlluminateLocalFeatures(const Layer *, QPoint &) const
Definition: View.h:260
int getFrameTime() const
void setVerticalScale(VerticalScale scale)
static int getColourMapCount()
void paintVertical(View *v, const VerticalScaleLayer *layer, QPainter &paint, int x0, float minlog, float maxlog)
RegionModel::EditCommand * m_editingCommand
Definition: RegionLayer.h:156
virtual int getTextLabelHeight(const Layer *layer, QPainter &) const
Definition: View.cpp:222
virtual QColor getForegroundQColor(View *v) const
void layerParameterRangesChanged()
virtual QColor getBaseQColor() const
int getWidth(View *v, QPainter &paint)
virtual QString getScaleUnits() const
void setText(QString text)
virtual int getPropertyRangeAndValue(const PropertyName &, int *min, int *max, int *deflt) const
virtual QString getPropertyValueLabel(const PropertyName &, int value) const
virtual void editStart(View *v, QMouseEvent *)
VerticalScale m_verticalScale
Definition: RegionLayer.h:157
virtual bool isLayerScrollable(const View *v) const
This should return true if the layer can safely be scrolled automatically by a given view (simply cop...
int getColourIndex(QString name) const
int getWidth(View *v, QPainter &paint)
int m_dragPointY
Definition: RegionLayer.h:151
virtual void toXml(QTextStream &stream, QString indent="", QString extraAttributes="") const
Convert the layer's data (though not those of the model it refers to) into XML for file output.
int spacingIndexToY(View *v, int i) const
virtual QString getPropertyGroupName(const PropertyName &) const
virtual QString getPropertyLabel(const PropertyName &) const
int getStartFrame() const
Retrieve the first visible sample frame on the widget.
Definition: View.cpp:302
void setModel(RegionModel *model)
Definition: RegionLayer.cpp:65
RegionModel * m_model
Definition: RegionLayer.h:148
void paintVertical(View *v, const VerticalScaleLayer *layer, QPainter &paint, int x0, float minf, float maxf)
void layerParametersChanged()
virtual QString getPropertyGroupName(const PropertyName &) const
virtual void editDrag(View *v, QMouseEvent *)
virtual void drawDrag(View *v, QMouseEvent *)
int getWidth(View *v, QPainter &paint)
virtual void setProperties(const QXmlAttributes &attributes)
Set the particular properties of a layer (those specific to the subclass) from a set of XML attribute...
virtual void setProperty(const PropertyName &, int value)
int getEndFrame() const
Retrieve the last visible sample frame on the widget.
Definition: View.cpp:308
SnapType
Definition: Layer.h:157
virtual int getPropertyRangeAndValue(const PropertyName &, int *min, int *max, int *deflt) const
A class for mapping intensity values onto various colour maps.
Definition: ColourMapper.h:27
QColor map(float value) const
bool clipboardHasDifferentAlignment(View *v, const Clipboard &clip) const
Definition: Layer.cpp:193
virtual PropertyType getPropertyType(const PropertyName &) const
virtual void moveSelection(Selection s, int newStartFrame)
int getYForValue(View *v, float value) const
VerticalScaleLayer and ColourScaleLayer methods.
float yToSpacingIndex(View *v, int y) const
SpacingMap m_distributionMap
Definition: RegionLayer.h:167
void modelChanged()
virtual void eraseEnd(View *v, QMouseEvent *)
virtual PropertyList getProperties() const
Definition: RegionLayer.cpp:88
bool getPointToDrag(View *v, int x, int y, RegionModel::Point &) const
virtual bool getDisplayExtents(float &min, float &max) const
Return the minimum and maximum values within the displayed range for the y axis, if only a subset of ...
virtual int alignFromReference(View *v, int frame) const
Definition: Layer.cpp:181
virtual int alignToReference(View *v, int frame) const
Definition: Layer.cpp:169
virtual void resizeSelection(Selection s, Selection newSize)
RegionModel::PointList getLocalPoints(View *v, int x) const
View is the base class of widgets that display one or more overlaid views of data against a horizonta...
Definition: View.h:50
int getWidth(View *v, QPainter &paint)
float getValue() const
virtual bool snapToSimilarFeature(View *v, int &frame, int &resolution, SnapType snap) const
Adjust the given frame to snap to the next feature that has "effectively" the same value as the featu...
RegionModel::Point m_editingPoint
Definition: RegionLayer.h:155
virtual QString getLabelPreceding(int) const
virtual bool paste(View *v, const Clipboard &from, int frameOffset, bool interactive)
Paste from the given clipboard onto the layer at the given frame offset.
virtual QString getPropertyValueLabel(const PropertyName &, int value) const
virtual void drawEnd(View *v, QMouseEvent *)
virtual void drawVisibleText(QPainter &p, int x, int y, QString text, TextStyle style) const
Definition: View.cpp:787
virtual void eraseDrag(View *v, QMouseEvent *)
void paintVertical(View *v, const ColourScaleLayer *layer, QPainter &paint, int x0, float minf, float maxf)
int getFrameDuration() const
void finish(RegionModel::EditCommand *command)
Definition: RegionLayer.h:172
PlotStyle m_plotStyle
Definition: RegionLayer.h:159
virtual PropertyList getProperties() const
void recalcSpacing()
QColor getColourForValue(View *v, float value) const
void setFillColourMap(int)
virtual void copy(View *v, Selection s, Clipboard &to)
virtual bool getValueExtents(float &min, float &max, bool &log, QString &unit) const
Return the minimum and maximum values for the y axis of the model in this layer, as well as whether t...
virtual void eraseStart(View *v, QMouseEvent *)
SpacingMap m_spacingMap
Definition: RegionLayer.h:164
virtual int getVerticalScaleWidth(View *v, bool, QPainter &) const
virtual void paint(View *v, QPainter &paint, QRect rect) const
Paint the given rectangle of this layer onto the given view using the given painter,...
virtual PropertyType getPropertyType(const PropertyName &) const
virtual int getDefaultColourHint(bool dark, bool &impose)
virtual void paintVerticalScale(View *v, bool, QPainter &paint, QRect rect) const
int getXForFrame(int frame) const
Return the pixel x-coordinate corresponding to a given sample frame (which may be negative).
Definition: View.cpp:357
static ColourDatabase * getInstance()
virtual void setProperty(const PropertyName &, int value)
void setValue(float value)
void setFrameDuration(int frame)
virtual QString getPropertyLabel(const PropertyName &) const
Definition: RegionLayer.cpp:98
static QString getColourMapName(int n)
QString getText() const