Mercurial > hg > svgui
view layer/TimeRulerLayer.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 | 37b110168acf |
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 "TimeRulerLayer.h" #include "base/Model.h" #include "base/RealTime.h" #include "base/View.h" #include <QPainter> #include <iostream> using std::cerr; using std::endl; TimeRulerLayer::TimeRulerLayer(View *w) : Layer(w), m_model(0), m_colour(Qt::black), m_labelHeight(LabelTop) { m_view->addLayer(this); } void TimeRulerLayer::setModel(Model *model) { if (m_model == model) return; m_model = model; emit modelReplaced(); } void TimeRulerLayer::setBaseColour(QColor colour) { if (m_colour == colour) return; m_colour = colour; emit layerParametersChanged(); } Layer::PropertyList TimeRulerLayer::getProperties() const { PropertyList list; list.push_back(tr("Colour")); return list; } Layer::PropertyType TimeRulerLayer::getPropertyType(const PropertyName &name) const { return ValueProperty; } int TimeRulerLayer::getPropertyRangeAndValue(const PropertyName &name, int *min, int *max) const { 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 { deft = Layer::getPropertyRangeAndValue(name, min, max); } return deft; } QString TimeRulerLayer::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"); } } return tr("<unknown>"); } void TimeRulerLayer::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; } } } void TimeRulerLayer::paint(QPainter &paint, QRect rect) const { // std::cerr << "TimeRulerLayer::paint (" << rect.x() << "," << rect.y() // << ") [" << rect.width() << "x" << rect.height() << "]" << std::endl; if (!m_model || !m_model->isOK()) return; int sampleRate = m_model->getSampleRate(); if (!sampleRate) return; long startFrame = m_view->getStartFrame(); long endFrame = m_view->getEndFrame(); int zoomLevel = m_view->getZoomLevel(); long rectStart = startFrame + (rect.x() - 100) * zoomLevel; long rectEnd = startFrame + (rect.x() + rect.width() + 100) * zoomLevel; if (rectStart < startFrame) rectStart = startFrame; if (rectEnd > endFrame) rectEnd = endFrame; // std::cerr << "TimeRulerLayer::paint: calling paint.save()" << std::endl; paint.save(); //!!! paint.setClipRect(m_view->rect()); int minPixelSpacing = 50; RealTime rtStart = RealTime::frame2RealTime(startFrame, sampleRate); RealTime rtEnd = RealTime::frame2RealTime(endFrame, sampleRate); // cerr << "startFrame " << startFrame << ", endFrame " << m_view->getEndFrame() << ", rtStart " << rtStart << ", rtEnd " << rtEnd << endl; int count = m_view->width() / minPixelSpacing; if (count < 1) count = 1; RealTime rtGap = (rtEnd - rtStart) / count; // cerr << "rtGap is " << rtGap << endl; int incms; bool quarter = false; if (rtGap.sec > 0) { incms = 1000; int s = rtGap.sec; if (s > 0) { incms *= 5; s /= 5; } if (s > 0) { incms *= 2; s /= 2; } if (s > 0) { incms *= 6; s /= 6; quarter = true; } if (s > 0) { incms *= 5; s /= 5; quarter = false; } if (s > 0) { incms *= 2; s /= 2; } if (s > 0) { incms *= 6; s /= 6; quarter = true; } while (s > 0) { incms *= 10; s /= 10; quarter = false; } } else { incms = 1; int ms = rtGap.msec(); if (ms > 0) { incms *= 10; ms /= 10; } if (ms > 0) { incms *= 10; ms /= 10; } if (ms > 0) { incms *= 5; ms /= 5; } if (ms > 0) { incms *= 2; ms /= 2; } } // cerr << "incms is " << incms << endl; RealTime rt = RealTime::frame2RealTime(rectStart, sampleRate); long ms = rt.sec * 1000 + rt.msec(); ms = (ms / incms) * incms - incms; RealTime incRt = RealTime(incms / 1000, (incms % 1000) * 1000000); long incFrame = RealTime::realTime2Frame(incRt, sampleRate); int incX = incFrame / zoomLevel; int ticks = 10; if (incX < minPixelSpacing * 2) { ticks = quarter ? 4 : 5; } QRect oldClipRect = rect; QRect newClipRect(oldClipRect.x() - 25, oldClipRect.y(), oldClipRect.width() + 50, oldClipRect.height()); paint.setClipRect(newClipRect); QColor greyColour(m_colour); if (m_colour == Qt::black) { greyColour = QColor(200,200,200); } else { greyColour = m_colour.light(150); } while (1) { rt = RealTime(ms / 1000, (ms % 1000) * 1000000); ms += incms; long frame = RealTime::realTime2Frame(rt, sampleRate); if (frame >= rectEnd) break; int x = (frame - startFrame) / zoomLevel; if (x < rect.x() || x >= rect.x() + rect.width()) continue; paint.setPen(greyColour); paint.drawLine(x, 0, x, m_view->height()); paint.setPen(m_colour); paint.drawLine(x, 0, x, 5); paint.drawLine(x, m_view->height() - 6, x, m_view->height() - 1); QString text(QString::fromStdString(rt.toText())); int y; QFontMetrics metrics = paint.fontMetrics(); switch (m_labelHeight) { default: case LabelTop: y = 6 + metrics.ascent(); break; case LabelMiddle: y = m_view->height() / 2 - metrics.height() / 2 + metrics.ascent(); break; case LabelBottom: y = m_view->height() - metrics.height() + metrics.ascent() - 6; } int tw = metrics.width(text); paint.setPen(m_view->palette().background().color()); //!!! simple drawing function for this please //!!! and need getContrastingColour() in widget, or use the //palette properly -- get the base class able to draw text //using the proper colour (or this technique) automatically for (int dx = -1; dx <= 1; ++dx) { for (int dy = -1; dy <= 1; ++dy) { if ((dx && dy) || !(dx || dy)) continue; paint.drawText(x + 2 - tw / 2 + dx, y + dy, text); } } paint.setPen(m_colour); paint.drawText(x + 2 - tw / 2, y, text); paint.setPen(greyColour); for (int i = 1; i < ticks; ++i) { rt = rt + (incRt / ticks); frame = RealTime::realTime2Frame(rt, sampleRate); x = (frame - startFrame) / zoomLevel; int sz = 5; if (ticks == 10) { if ((i % 2) == 1) { if (i == 5) { paint.drawLine(x, 0, x, m_view->height()); } else sz = 3; } else { sz = 7; } } paint.drawLine(x, 0, x, sz); paint.drawLine(x, m_view->height() - sz - 1, x, m_view->height() - 1); } } paint.restore(); } #ifdef INCLUDE_MOCFILES #include "TimeRulerLayer.moc.cpp" #endif