# HG changeset patch # User Chris Cannam # Date 1139246692 0 # Node ID 202d1dca67d2f47ef3cb190ea75c26dfd1949daf # Parent 38fe0ea9e46ea5b445db3070da13870e3ba6c84c * Rationalise the local feature identification API in Layer subclasses * Add segmentation mode to TimeInstantLayer diff -r 38fe0ea9e46e -r 202d1dca67d2 layer/Colour3DPlotLayer.cpp --- a/layer/Colour3DPlotLayer.cpp Fri Feb 03 17:30:47 2006 +0000 +++ b/layer/Colour3DPlotLayer.cpp Mon Feb 06 17:24:52 2006 +0000 @@ -374,21 +374,30 @@ */ } -int -Colour3DPlotLayer::getNearestFeatureFrame(int frame, - size_t &resolution, - bool snapRight) const +bool +Colour3DPlotLayer::snapToFeatureFrame(int &frame, + size_t &resolution, + SnapType snap) const { if (!m_model) { - return Layer::getNearestFeatureFrame(frame, resolution, snapRight); + return Layer::snapToFeatureFrame(frame, resolution, snap); } resolution = m_model->getWindowSize(); + int left = (frame / resolution) * resolution; + int right = left + resolution; + + switch (snap) { + case SnapLeft: frame = left; break; + case SnapRight: frame = right; break; + case SnapNearest: + case SnapNeighbouring: + if (frame - left > right - frame) frame = right; + else frame = left; + break; + } - int returnFrame = (frame / resolution) * resolution; - if (snapRight) returnFrame += resolution; - - return returnFrame; + return true; } #ifdef INCLUDE_MOCFILES diff -r 38fe0ea9e46e -r 202d1dca67d2 layer/Colour3DPlotLayer.h --- a/layer/Colour3DPlotLayer.h Fri Feb 03 17:30:47 2006 +0000 +++ b/layer/Colour3DPlotLayer.h Mon Feb 06 17:24:52 2006 +0000 @@ -48,9 +48,9 @@ virtual QString getFeatureDescription(QPoint &) const; - virtual int getNearestFeatureFrame(int frame, - size_t &resolution, - bool snapRight = true) const; + virtual bool snapToFeatureFrame(int &frame, + size_t &resolution, + SnapType snap) const; virtual bool isLayerScrollable() const; diff -r 38fe0ea9e46e -r 202d1dca67d2 layer/SpectrogramLayer.cpp --- a/layer/SpectrogramLayer.cpp Fri Feb 03 17:30:47 2006 +0000 +++ b/layer/SpectrogramLayer.cpp Mon Feb 06 17:24:52 2006 +0000 @@ -1483,16 +1483,27 @@ return completion; } -int -SpectrogramLayer::getNearestFeatureFrame(int frame, - size_t &resolution, - bool snapRight) const +bool +SpectrogramLayer::snapToFeatureFrame(int &frame, + size_t &resolution, + SnapType snap) const { resolution = getWindowIncrement(); - int snapFrame = (frame / resolution) * resolution; - if (snapRight) snapFrame += resolution; - return snapFrame; -} + int left = (frame / resolution) * resolution; + int right = left + resolution; + + switch (snap) { + case SnapLeft: frame = left; break; + case SnapRight: frame = right; break; + case SnapNearest: + case SnapNeighbouring: + if (frame - left > right - frame) frame = right; + else frame = left; + break; + } + + return true; +} QString SpectrogramLayer::getFeatureDescription(QPoint &pos) const diff -r 38fe0ea9e46e -r 202d1dca67d2 layer/SpectrogramLayer.h --- a/layer/SpectrogramLayer.h Fri Feb 03 17:30:47 2006 +0000 +++ b/layer/SpectrogramLayer.h Mon Feb 06 17:24:52 2006 +0000 @@ -53,9 +53,9 @@ virtual QString getFeatureDescription(QPoint &) const; - virtual int getNearestFeatureFrame(int frame, - size_t &resolution, - bool snapRight = true) const; + virtual bool snapToFeatureFrame(int &frame, + size_t &resolution, + SnapType snap) const; void setModel(const DenseTimeValueModel *model); diff -r 38fe0ea9e46e -r 202d1dca67d2 layer/TimeInstantLayer.cpp --- a/layer/TimeInstantLayer.cpp Fri Feb 03 17:30:47 2006 +0000 +++ b/layer/TimeInstantLayer.cpp Mon Feb 06 17:24:52 2006 +0000 @@ -27,7 +27,8 @@ m_editing(false), m_editingPoint(0, tr("New Point")), m_editingCommand(0), - m_colour(QColor(200, 50, 255)) + m_colour(QColor(200, 50, 255)), + m_plotStyle(PlotInstants) { m_view->addLayer(this); } @@ -55,6 +56,7 @@ { PropertyList list; list.push_back(tr("Colour")); + list.push_back(tr("Plot Type")); return list; } @@ -82,6 +84,13 @@ else if (m_colour == QColor(200, 50, 255)) deft = 4; else if (m_colour == QColor(255, 150, 50)) deft = 5; + } else if (name == tr("Plot Type")) { + + if (min) *min = 0; + if (max) *max = 1; + + deft = int(m_plotStyle); + } else { deft = Layer::getPropertyRangeAndValue(name, min, max); @@ -104,6 +113,12 @@ case 4: return tr("Purple"); case 5: return tr("Orange"); } + } else if (name == tr("Plot Type")) { + switch (value) { + default: + case 0: return tr("Instants"); + case 1: return tr("Segmentation"); + } } return tr(""); } @@ -121,6 +136,8 @@ case 4: setBaseColour(QColor(200, 50, 255)); break; case 5: setBaseColour(QColor(255, 150, 50)); break; } + } else if (name == tr("Plot Type")) { + setPlotStyle(PlotStyle(value)); } } @@ -132,6 +149,14 @@ emit layerParametersChanged(); } +void +TimeInstantLayer::setPlotStyle(PlotStyle style) +{ + if (m_plotStyle == style) return; + m_plotStyle = style; + emit layerParametersChanged(); +} + bool TimeInstantLayer::isLayerScrollable() const { @@ -142,6 +167,10 @@ SparseOneDimensionalModel::PointList TimeInstantLayer::getLocalPoints(int x) const { + // Return a set of points that all have the same frame number, the + // nearest to the given x coordinate, and that are within a + // certain fuzz distance of that x coordinate. + if (!m_model) return SparseOneDimensionalModel::PointList(); long frame = getFrameForX(x); @@ -170,6 +199,15 @@ usePoints = nextPoints; } + if (!usePoints.empty()) { + int fuzz = 2; + int px = getXForFrame(usePoints.begin()->frame); + if ((px > x && px - x > fuzz) || + (px < x && x - px > fuzz + 1)) { + usePoints.clear(); + } + } + return usePoints; } @@ -209,36 +247,76 @@ return text; } -int -TimeInstantLayer::getNearestFeatureFrame(int frame, - size_t &resolution, - bool snapRight) const +bool +TimeInstantLayer::snapToFeatureFrame(int &frame, + size_t &resolution, + SnapType snap) const { if (!m_model) { - return Layer::getNearestFeatureFrame(frame, resolution, snapRight); + return Layer::snapToFeatureFrame(frame, resolution, snap); } resolution = m_model->getResolution(); - SparseOneDimensionalModel::PointList points(m_model->getPoints(frame, frame)); + SparseOneDimensionalModel::PointList points; - int returnFrame = frame; + if (snap == SnapNeighbouring) { + + points = getLocalPoints(getXForFrame(frame)); + if (points.empty()) return false; + frame = points.begin()->frame; + return true; + } + + points = m_model->getPoints(frame, frame); + int snapped = frame; + bool found = false; for (SparseOneDimensionalModel::PointList::const_iterator i = points.begin(); i != points.end(); ++i) { - if (snapRight) { - if (i->frame > frame) { - returnFrame = i->frame; + if (snap == SnapRight) { + + if (i->frame >= frame) { + snapped = i->frame; + found = true; break; } - } else { + + } else if (snap == SnapLeft) { + if (i->frame <= frame) { - returnFrame = i->frame; + snapped = i->frame; + found = true; // don't break, as the next may be better + } else { + break; + } + + } else { // nearest + + SparseOneDimensionalModel::PointList::const_iterator j = i; + ++j; + + if (j == points.end()) { + + snapped = i->frame; + found = true; + break; + + } else if (j->frame >= frame) { + + if (j->frame - frame < frame - i->frame) { + snapped = j->frame; + } else { + snapped = i->frame; + } + found = true; + break; } } } - return returnFrame; + frame = snapped; + return found; } void @@ -256,12 +334,34 @@ SparseOneDimensionalModel::PointList points(m_model->getPoints (frame0, frame1)); + bool odd = false; + if (m_plotStyle == PlotSegmentation && !points.empty()) { + int index = m_model->getIndexOf(*points.begin()); + odd = ((index % 2) == 1); + } + paint.setPen(m_colour); QColor brushColour(m_colour); brushColour.setAlpha(100); paint.setBrush(brushColour); + QColor oddBrushColour(brushColour); + if (m_plotStyle == PlotSegmentation) { + if (m_colour == Qt::black) { + oddBrushColour = Qt::gray; + } else if (m_colour == Qt::darkRed) { + oddBrushColour = Qt::red; + } else if (m_colour == Qt::darkBlue) { + oddBrushColour = Qt::blue; + } else if (m_colour == Qt::darkGreen) { + oddBrushColour = Qt::green; + } else { + oddBrushColour = oddBrushColour.light(150); + } + oddBrushColour.setAlpha(100); + } + // std::cerr << "TimeInstantLayer::paint: resolution is " // << m_model->getResolution() << " frames" << std::endl; @@ -305,11 +405,39 @@ paint.setPen(brushColour); } - if (iw > 1) { - paint.drawRect(x, 0, iw - 1, m_view->height() - 1); + if (m_plotStyle == PlotInstants) { + if (iw > 1) { + paint.drawRect(x, 0, iw - 1, m_view->height() - 1); + } else { + paint.drawLine(x, 0, x, m_view->height() - 1); + } } else { - paint.drawLine(x, 0, x, m_view->height() - 1); + + if (odd) paint.setBrush(oddBrushColour); + else paint.setBrush(brushColour); + + int nx; + + if (j != points.end()) { + const SparseOneDimensionalModel::Point &q(*j); + nx = getXForFrame(q.frame); + } else { + nx = getXForFrame(m_model->getEndFrame()); + } + + if (nx >= x) { + + if (illuminateFrame != p.frame && + (nx < x + 5 || x >= m_view->width() - 1)) { + paint.setPen(Qt::NoPen); + } + + paint.drawRect(x, -1, nx - x, m_view->height() + 1); + } + + odd = !odd; } + paint.setPen(m_colour); if (p.label != "") { @@ -448,7 +576,8 @@ TimeInstantLayer::toXmlString(QString indent, QString extraAttributes) const { return Layer::toXmlString(indent, extraAttributes + - QString(" colour=\"%1\"").arg(encodeColour(m_colour))); + QString(" colour=\"%1\" plotStyle=\"%2\"") + .arg(encodeColour(m_colour)).arg(m_plotStyle)); } void @@ -461,6 +590,11 @@ setBaseColour(QColor(colourSpec)); } } + + bool ok; + PlotStyle style = (PlotStyle) + attributes.value("plotStyle").toInt(&ok); + if (ok) setPlotStyle(style); } #ifdef INCLUDE_MOCFILES diff -r 38fe0ea9e46e -r 202d1dca67d2 layer/TimeInstantLayer.h --- a/layer/TimeInstantLayer.h Fri Feb 03 17:30:47 2006 +0000 +++ b/layer/TimeInstantLayer.h Mon Feb 06 17:24:52 2006 +0000 @@ -30,9 +30,9 @@ virtual QString getFeatureDescription(QPoint &) const; - virtual int getNearestFeatureFrame(int frame, - size_t &resolution, - bool snapRight = true) const; + virtual bool snapToFeatureFrame(int &frame, + size_t &resolution, + SnapType snap) const; virtual void drawStart(QMouseEvent *); virtual void drawDrag(QMouseEvent *); @@ -56,6 +56,14 @@ void setBaseColour(QColor); QColor getBaseColour() const { return m_colour; } + enum PlotStyle { + PlotInstants, + PlotSegmentation + }; + + void setPlotStyle(PlotStyle style); + PlotStyle getPlotStyle() const { return m_plotStyle; } + virtual bool isLayerScrollable() const; virtual bool isLayerEditable() const { return true; } @@ -75,6 +83,7 @@ SparseOneDimensionalModel::Point m_editingPoint; SparseOneDimensionalModel::EditCommand *m_editingCommand; QColor m_colour; + PlotStyle m_plotStyle; }; #endif diff -r 38fe0ea9e46e -r 202d1dca67d2 layer/TimeValueLayer.cpp --- a/layer/TimeValueLayer.cpp Fri Feb 03 17:30:47 2006 +0000 +++ b/layer/TimeValueLayer.cpp Mon Feb 06 17:24:52 2006 +0000 @@ -210,6 +210,15 @@ usePoints = nextPoints; } + if (!usePoints.empty()) { + int fuzz = 2; + int px = getXForFrame(usePoints.begin()->frame); + if ((px > x && px - x > fuzz) || + (px < x && x - px > fuzz + 1)) { + usePoints.clear(); + } + } + return usePoints; } @@ -251,36 +260,76 @@ return text; } -int -TimeValueLayer::getNearestFeatureFrame(int frame, - size_t &resolution, - bool snapRight) const +bool +TimeValueLayer::snapToFeatureFrame(int &frame, + size_t &resolution, + SnapType snap) const { if (!m_model) { - return Layer::getNearestFeatureFrame(frame, resolution, snapRight); + return Layer::snapToFeatureFrame(frame, resolution, snap); } resolution = m_model->getResolution(); - SparseTimeValueModel::PointList points(m_model->getPoints(frame, frame)); + SparseTimeValueModel::PointList points; - int returnFrame = frame; + if (snap == SnapNeighbouring) { + + points = getLocalPoints(getXForFrame(frame)); + if (points.empty()) return false; + frame = points.begin()->frame; + return true; + } + + points = m_model->getPoints(frame, frame); + int snapped = frame; + bool found = false; for (SparseTimeValueModel::PointList::const_iterator i = points.begin(); i != points.end(); ++i) { - if (snapRight) { + if (snap == SnapRight) { + if (i->frame > frame) { - returnFrame = i->frame; + snapped = i->frame; + found = true; break; } - } else { + + } else if (snap == SnapLeft) { + if (i->frame <= frame) { - returnFrame = i->frame; + snapped = i->frame; + found = true; // don't break, as the next may be better + } else { + break; + } + + } else { // nearest + + SparseTimeValueModel::PointList::const_iterator j = i; + ++j; + + if (j == points.end()) { + + snapped = i->frame; + found = true; + break; + + } else if (j->frame >= frame) { + + if (j->frame - frame < frame - i->frame) { + snapped = j->frame; + } else { + snapped = i->frame; + } + found = true; + break; } } } - return returnFrame; + frame = snapped; + return found; } int @@ -473,7 +522,8 @@ if (nx <= x) continue; - if (nx < x + 5 && illuminateFrame != p.frame) { + if (illuminateFrame != p.frame && + (nx < x + 5 || x >= m_view->width() - 1)) { paint.setPen(Qt::NoPen); } diff -r 38fe0ea9e46e -r 202d1dca67d2 layer/TimeValueLayer.h --- a/layer/TimeValueLayer.h Fri Feb 03 17:30:47 2006 +0000 +++ b/layer/TimeValueLayer.h Mon Feb 06 17:24:52 2006 +0000 @@ -30,9 +30,9 @@ virtual QString getFeatureDescription(QPoint &) const; - virtual int getNearestFeatureFrame(int frame, - size_t &resolution, - bool snapRight = true) const; + virtual bool snapToFeatureFrame(int &frame, + size_t &resolution, + SnapType snap) const; virtual void drawStart(QMouseEvent *); virtual void drawDrag(QMouseEvent *); diff -r 38fe0ea9e46e -r 202d1dca67d2 layer/WaveformLayer.cpp --- a/layer/WaveformLayer.cpp Fri Feb 03 17:30:47 2006 +0000 +++ b/layer/WaveformLayer.cpp Mon Feb 06 17:24:52 2006 +0000 @@ -385,12 +385,12 @@ paint->setPen(Qt::black); paint->setBrush(Qt::NoBrush); - paint->setRenderHint(QPainter::Antialiasing, false); - } else { paint = &viewPainter; } + paint->setRenderHint(QPainter::Antialiasing, false); + int x0 = 0, x1 = w - 1; int y0 = 0, y1 = h - 1; @@ -399,6 +399,9 @@ y0 = rect.top(); y1 = rect.bottom(); + if (x0 > 0) --x0; + if (x1 < m_view->width()) ++x1; + long frame0 = getFrameForX(x0); long frame1 = getFrameForX(x1 + 1); @@ -440,6 +443,7 @@ for (size_t ch = minChannel; ch <= maxChannel; ++ch) { int prevRangeBottom = -1, prevRangeTop = -1; + QColor prevRangeBottomColour = m_colour, prevRangeTopColour = m_colour; int m = (h / channels) / 2; int my = m + (((ch - minChannel) * h) / channels); @@ -593,15 +597,17 @@ if (x != x0 && prevRangeBottom != -1) { if (prevRangeBottom > rangeBottom && prevRangeTop > rangeBottom) { - paint->setPen(midColour); +// paint->setPen(midColour); + paint->setPen(m_colour); paint->drawLine(x-1, prevRangeTop, x, rangeBottom); - paint->setPen(m_colour); + paint->setPen(prevRangeTopColour); paint->drawPoint(x-1, prevRangeTop); } else if (prevRangeBottom < rangeTop && prevRangeTop < rangeTop) { - paint->setPen(midColour); +// paint->setPen(midColour); + paint->setPen(m_colour); paint->drawLine(x-1, prevRangeBottom, x, rangeTop); - paint->setPen(m_colour); + paint->setPen(prevRangeBottomColour); paint->drawPoint(x-1, prevRangeBottom); } } @@ -620,6 +626,9 @@ paint->drawLine(x, rangeBottom, x, rangeTop); + prevRangeTopColour = m_colour; + prevRangeBottomColour = m_colour; + if (m_greyscale && (m_scale == LinearScale) && ready) { if (!clipped) { if (rangeTop < rangeBottom) { @@ -627,11 +636,13 @@ (!drawMean || (rangeTop < meanTop - 1))) { paint->setPen(greys[topFill - 1]); paint->drawPoint(x, rangeTop); + prevRangeTopColour = greys[topFill - 1]; } if (bottomFill > 0 && (!drawMean || (rangeBottom > meanBottom + 1))) { paint->setPen(greys[bottomFill - 1]); paint->drawPoint(x, rangeBottom); + prevRangeBottomColour = greys[bottomFill - 1]; } } } diff -r 38fe0ea9e46e -r 202d1dca67d2 widgets/Pane.cpp --- a/widgets/Pane.cpp Fri Feb 03 17:30:47 2006 +0000 +++ b/widgets/Pane.cpp Mon Feb 06 17:24:52 2006 +0000 @@ -40,14 +40,6 @@ bool Pane::shouldIlluminateLocalFeatures(const Layer *layer, QPoint &pos) { -/*!!! - for (LayerList::iterator vi = m_layers.end(); vi != m_layers.begin(); ) { - --vi; - if (layer != *vi) return false; - pos = m_identifyPoint; - return m_identifyFeatures; - } -*/ if (layer == getSelectedLayer()) { pos = m_identifyPoint; return m_identifyFeatures; @@ -352,8 +344,7 @@ Layer *layer = getSelectedLayer(); if (layer) { - snapFrame = layer->getNearestFeatureFrame(mouseFrame, resolution, - false); + layer->snapToFeatureFrame(snapFrame, resolution, Layer::SnapLeft); } if (snapFrame < 0) snapFrame = 0; @@ -486,6 +477,9 @@ ViewManager::ToolMode mode = ViewManager::NavigateMode; if (m_manager) mode = m_manager->getToolMode(); + QPoint prevPoint = m_identifyPoint; + m_identifyPoint = e->pos(); + if (!m_clickedInRange) { if (mode == ViewManager::SelectMode) { @@ -501,10 +495,7 @@ if (mode != ViewManager::DrawMode) { bool previouslyIdentifying = m_identifyFeatures; - QPoint prevPoint = m_identifyPoint; - m_identifyFeatures = true; - m_identifyPoint = e->pos(); if (m_identifyFeatures != previouslyIdentifying || m_identifyPoint != prevPoint) { @@ -555,12 +546,12 @@ Layer *layer = getSelectedLayer(); if (layer) { - snapFrameLeft = layer->getNearestFeatureFrame(mouseFrame, resolution, - false); - snapFrameRight = layer->getNearestFeatureFrame(mouseFrame, resolution, - true); + layer->snapToFeatureFrame(snapFrameLeft, resolution, Layer::SnapLeft); + layer->snapToFeatureFrame(snapFrameRight, resolution, Layer::SnapRight); } + std::cerr << "snap: frame = " << mouseFrame << ", start frame = " << m_selectionStartFrame << ", left = " << snapFrameLeft << ", right = " << snapFrameRight << std::endl; + if (snapFrameLeft < 0) snapFrameLeft = 0; if (snapFrameRight < 0) snapFrameRight = 0;