Mercurial > hg > svgui
view layer/TimeValueLayer.cpp @ 1:ab83c415a6cd
* Backed out partially complete changes to make the spectrogram only
store results up to the requested max frequency. The speed improvement
was minimal at the expense of annoyance when changing frequency limit,
and although it did save memory, it wasn't yet reliable and fixing it
is not a high enough priority.
author | Chris Cannam |
---|---|
date | Tue, 10 Jan 2006 17:04:02 +0000 |
parents | 2a4f26e85b4c |
children | 7af44e8578c8 |
line wrap: on
line source
/* -*- c-basic-offset: 4 -*- vi:set ts=8 sts=4 sw=4: */ /* A waveform viewer and audio annotation editor. Chris Cannam, Queen Mary University of London, 2005 This is experimental software. Not for distribution. */ #include "TimeValueLayer.h" #include "base/Model.h" #include "base/RealTime.h" #include "base/Profiler.h" #include "base/View.h" #include "model/SparseTimeValueModel.h" #include <QPainter> #include <iostream> #include <cmath> TimeValueLayer::TimeValueLayer(View *w) : Layer(w), m_model(0), m_colour(Qt::black), m_plotStyle(PlotLines) { m_view->addLayer(this); } void TimeValueLayer::setModel(SparseTimeValueModel *model) { if (m_model == model) return; m_model = model; connect(m_model, SIGNAL(modelChanged()), this, SIGNAL(modelChanged())); connect(m_model, SIGNAL(modelChanged(size_t, size_t)), this, SIGNAL(modelChanged(size_t, size_t))); connect(m_model, SIGNAL(completionChanged()), this, SIGNAL(modelCompletionChanged())); std::cerr << "TimeValueLayer::setModel(" << model << ")" << std::endl; emit modelReplaced(); } Layer::PropertyList TimeValueLayer::getProperties() const { PropertyList list; list.push_back(tr("Colour")); list.push_back(tr("Plot Type")); return list; } Layer::PropertyType TimeValueLayer::getPropertyType(const PropertyName &name) const { return ValueProperty; } int TimeValueLayer::getPropertyRangeAndValue(const PropertyName &name, int *min, int *max) const { //!!! factor this colour handling stuff out into a colour manager class int deft = 0; if (name == tr("Colour")) { *min = 0; *max = 5; if (m_colour == Qt::black) deft = 0; else if (m_colour == Qt::darkRed) deft = 1; else if (m_colour == Qt::darkBlue) deft = 2; else if (m_colour == Qt::darkGreen) deft = 3; 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")) { *min = 0; *max = 2; deft = int(m_plotStyle); } else { deft = Layer::getPropertyRangeAndValue(name, min, max); } return deft; } QString TimeValueLayer::getPropertyValueLabel(const PropertyName &name, int value) const { if (name == tr("Colour")) { switch (value) { default: case 0: return tr("Black"); case 1: return tr("Red"); case 2: return tr("Blue"); case 3: return tr("Green"); case 4: return tr("Purple"); case 5: return tr("Orange"); } } else if (name == tr("Plot Type")) { switch (value) { default: case 0: return tr("Points"); case 1: return tr("Stems"); case 2: return tr("Lines"); } } return tr("<unknown>"); } void TimeValueLayer::setProperty(const PropertyName &name, int value) { if (name == tr("Colour")) { switch (value) { default: case 0: setBaseColour(Qt::black); break; case 1: setBaseColour(Qt::darkRed); break; case 2: setBaseColour(Qt::darkBlue); break; case 3: setBaseColour(Qt::darkGreen); break; 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)); } } void TimeValueLayer::setBaseColour(QColor colour) { if (m_colour == colour) return; m_colour = colour; emit layerParametersChanged(); } void TimeValueLayer::setPlotStyle(PlotStyle style) { if (m_plotStyle == style) return; m_plotStyle = style; emit layerParametersChanged(); } bool TimeValueLayer::isLayerScrollable() const { QPoint discard; return !m_view->shouldIlluminateLocalFeatures(this, discard); } QRect TimeValueLayer::getFeatureDescriptionRect(QPainter &paint, QPoint pos) const { return QRect(0, 0, std::max(100, paint.fontMetrics().width(tr("No local points"))), 70); //!!! } //!!! too much in common with TimeInstantLayer SparseTimeValueModel::PointList TimeValueLayer::getLocalPoints(int x) const { if (!m_model) return SparseTimeValueModel::PointList(); long startFrame = m_view->getStartFrame(); long endFrame = m_view->getEndFrame(); int zoomLevel = m_view->getZoomLevel(); long frame = startFrame + x * zoomLevel; SparseTimeValueModel::PointList onPoints = m_model->getPoints(frame); if (!onPoints.empty()) { return onPoints; } SparseTimeValueModel::PointList prevPoints = m_model->getPreviousPoints(frame); SparseTimeValueModel::PointList nextPoints = m_model->getNextPoints(frame); SparseTimeValueModel::PointList usePoints = prevPoints; if (prevPoints.empty()) { usePoints = nextPoints; } else if (prevPoints.begin()->frame < startFrame && !(nextPoints.begin()->frame > endFrame)) { usePoints = nextPoints; } else if (nextPoints.begin()->frame - frame < frame - prevPoints.begin()->frame) { usePoints = nextPoints; } return usePoints; } void TimeValueLayer::paintLocalFeatureDescription(QPainter &paint, QRect rect, QPoint pos) const { //!!! bleagh int x = pos.x(); if (!m_model || !m_model->getSampleRate()) return; SparseTimeValueModel::PointList points = getLocalPoints(x); QFontMetrics metrics = paint.fontMetrics(); int xbase = rect.x() + 5; int ybase = rect.y() + 5; if (points.empty()) { QString label = tr("No local points"); if (!m_model->isReady()) { label = tr("In progress"); } paint.drawText(xbase + 5, ybase + 5 + metrics.ascent(), label); return; } long useFrame = points.begin()->frame; RealTime rt = RealTime::frame2RealTime(useFrame, m_model->getSampleRate()); QString timeText = QString("%1").arg(rt.toText(true).c_str()); QString valueText = QString("%1").arg(points.begin()->value); int timewidth = metrics.width(timeText); int valuewidth = metrics.width(valueText); int labelwidth = metrics.width(points.begin()->label); int boxheight = metrics.height() * 3 + 4; int boxwidth = std::max(std::max(timewidth, labelwidth), valuewidth); paint.drawRect(xbase, ybase, boxwidth + 10, boxheight + 10 - metrics.descent() + 1); paint.drawText(xbase + 5, ybase + 5 + metrics.ascent(), timeText); paint.drawText(xbase + 5, ybase + 7 + metrics.ascent() + metrics.height(), valueText); paint.drawText(xbase + 5, ybase + 9 + metrics.ascent() + 2*metrics.height(), points.begin()->label); } void TimeValueLayer::paint(QPainter &paint, QRect rect) const { if (!m_model || !m_model->isOK()) return; int sampleRate = m_model->getSampleRate(); if (!sampleRate) return; // Profiler profiler("TimeValueLayer::paint", true); long startFrame = m_view->getStartFrame(); int zoomLevel = m_view->getZoomLevel(); int x0 = rect.left(), x1 = rect.right(); long frame0 = startFrame + x0 * zoomLevel; long frame1 = startFrame + x1 * zoomLevel; SparseTimeValueModel::PointList points(m_model->getPoints (frame0, frame1)); paint.setPen(m_colour); QColor brushColour(m_colour); brushColour.setAlpha(80); paint.setBrush(brushColour); // std::cerr << "TimeValueLayer::paint: resolution is " // << m_model->getResolution() << " frames" << std::endl; float min = m_model->getValueMinimum(); float max = m_model->getValueMaximum(); if (max == min) max = min + 1.0; int origin = int(nearbyint(m_view->height() - (-min * m_view->height()) / (max - min))); QPoint localPos; long illuminateFrame = -1; if (m_view->shouldIlluminateLocalFeatures(this, localPos)) { SparseTimeValueModel::PointList localPoints = getLocalPoints(localPos.x()); if (!localPoints.empty()) illuminateFrame = localPoints.begin()->frame; } for (SparseTimeValueModel::PointList::const_iterator i = points.begin(); i != points.end(); ++i) { const SparseTimeValueModel::Point &p(*i); int x = (p.frame - startFrame) / zoomLevel; int y = int(nearbyint(m_view->height() - ((p.value - min) * m_view->height()) / (max - min))); int w = m_model->getResolution() / zoomLevel; if (w < 1) w = 1; paint.setPen(m_colour); paint.setBrush(brushColour); if (m_plotStyle == PlotStems) { paint.setPen(brushColour); if (y < origin - 1) { paint.drawRect(x + w/2, y + 1, 1, origin - y); } else if (y > origin + 1) { paint.drawRect(x + w/2, origin, 1, y - origin - 1); } paint.setPen(m_colour); } if (illuminateFrame == p.frame) { //!!! aside from the problem of choosing a colour, it'd be //better to save the highlighted rects and draw them at //the end perhaps paint.setPen(Qt::black);//!!! paint.setBrush(Qt::black);//!!! } paint.drawRect(x, y - 1, w, 2); // if (w > 1) { // paint.setPen(brushColour); // paint.drawRect(x, y - 1, w - 1, 2); // paint.setPen(m_colour); // } // paint.drawLine(x, 0, x, m_view->height()); if (m_plotStyle == PlotLines) { paint.setPen(brushColour); SparseTimeValueModel::PointList::const_iterator j = i; ++j; if (j != points.end()) { const SparseTimeValueModel::Point &q(*j); int nx = (q.frame - startFrame) / zoomLevel; int ny = int(nearbyint(m_view->height() - ((q.value - min) * m_view->height()) / (max - min))); paint.drawLine(x + w, y, nx, ny); } } /// if (p.label != "") { /// paint.drawText(x + 5, y - paint.fontMetrics().height() + paint.fontMetrics().ascent(), p.label); /// } } } #ifdef INCLUDE_MOCFILES #include "TimeValueLayer.moc.cpp" #endif