Mercurial > hg > easaier-soundaccess
diff layer/TimeRulerLayer.cpp @ 0:fc9323a41f5a
start base : Sonic Visualiser sv1-1.0rc1
author | lbajardsilogic |
---|---|
date | Fri, 11 May 2007 09:08:14 +0000 |
parents | |
children | d8e6709e9075 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/layer/TimeRulerLayer.cpp Fri May 11 09:08:14 2007 +0000 @@ -0,0 +1,312 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Sonic Visualiser + An audio file viewer and annotation editor. + Centre for Digital Music, Queen Mary, University of London. + This file copyright 2006 Chris Cannam. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. See the file + COPYING included with this distribution for more information. +*/ + +#include "TimeRulerLayer.h" + +#include "data/model/Model.h" +#include "base/RealTime.h" +#include "view/View.h" + +#include <QPainter> + +#include <iostream> + +using std::cerr; +using std::endl; + +TimeRulerLayer::TimeRulerLayer() : + Layer(), + m_model(0), + m_colour(Qt::black), + m_labelHeight(LabelTop) +{ + +} + +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("Colour"); + return list; +} + +QString +TimeRulerLayer::getPropertyLabel(const PropertyName &name) const +{ + if (name == "Colour") return tr("Colour"); + return ""; +} + +Layer::PropertyType +TimeRulerLayer::getPropertyType(const PropertyName &) const +{ + return ValueProperty; +} + +int +TimeRulerLayer::getPropertyRangeAndValue(const PropertyName &name, + int *min, int *max, int *deflt) const +{ + int val = 0; + + if (name == "Colour") { + + if (min) *min = 0; + if (max) *max = 5; + if (deflt) *deflt = 0; + + if (m_colour == Qt::black) val = 0; + else if (m_colour == Qt::darkRed) val = 1; + else if (m_colour == Qt::darkBlue) val = 2; + else if (m_colour == Qt::darkGreen) val = 3; + else if (m_colour == QColor(200, 50, 255)) val = 4; + else if (m_colour == QColor(255, 150, 50)) val = 5; + + } else { + + val = Layer::getPropertyRangeAndValue(name, min, max, deflt); + } + + return val; +} + +QString +TimeRulerLayer::getPropertyValueLabel(const PropertyName &name, + int value) const +{ + if (name == "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 == "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(View *v, 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 = v->getStartFrame(); + long endFrame = v->getEndFrame(); + + int zoomLevel = v->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(v->rect()); + + int minPixelSpacing = 50; + + RealTime rtStart = RealTime::frame2RealTime(startFrame, sampleRate); + RealTime rtEnd = RealTime::frame2RealTime(endFrame, sampleRate); +// cerr << "startFrame " << startFrame << ", endFrame " << v->getEndFrame() << ", rtStart " << rtStart << ", rtEnd " << rtEnd << endl; + int count = v->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::fromMilliseconds(incms); + 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); + paint.setClipRect(rect); + + QColor greyColour(m_colour); + if (m_colour == Qt::black) { + greyColour = QColor(200,200,200); + } else { + greyColour = m_colour.light(150); + } + + while (1) { + + rt = RealTime::fromMilliseconds(ms); + 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, v->height()); + + paint.setPen(m_colour); + paint.drawLine(x, 0, x, 5); + paint.drawLine(x, v->height() - 6, x, v->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 = v->height() / 2 - metrics.height() / 2 + metrics.ascent(); + break; + case LabelBottom: + y = v->height() - metrics.height() + metrics.ascent() - 6; + } + + int tw = metrics.width(text); + + if (v->getViewManager() && v->getViewManager()->getOverlayMode() != + ViewManager::NoOverlays) { + + if (v->getLayer(0) == this) { + // backmost layer, don't worry about outlining the text + paint.drawText(x+2 - tw/2, y, text); + } else { + v->drawVisibleText(paint, x+2 - tw/2, y, text, View::OutlinedText); + } + } + + 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, v->height()); + } else sz = 3; + } else { + sz = 7; + } + } + paint.drawLine(x, 0, x, sz); + paint.drawLine(x, v->height() - sz - 1, x, v->height() - 1); + } + } + + paint.restore(); +} + +QString +TimeRulerLayer::toXmlString(QString indent, QString extraAttributes) const +{ + return Layer::toXmlString(indent, extraAttributes + + QString(" colour=\"%1\"").arg(encodeColour(m_colour))); +} + +void +TimeRulerLayer::setProperties(const QXmlAttributes &attributes) +{ + QString colourSpec = attributes.value("colour"); + if (colourSpec != "") { + QColor colour(colourSpec); + if (colour.isValid()) { + setBaseColour(QColor(colourSpec)); + } + } +} +