Mercurial > hg > svgui
diff layer/TimeRulerLayer.cpp @ 0:2a4f26e85b4c
initial import
author | Chris Cannam |
---|---|
date | Tue, 10 Jan 2006 16:33:16 +0000 |
parents | |
children | 37b110168acf |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/layer/TimeRulerLayer.cpp Tue Jan 10 16:33:16 2006 +0000 @@ -0,0 +1,288 @@ +/* -*- 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 +