MuseScore/awl/mslider.cpp
mirabilos 65cd276439
remove RCS IDs from (almost) all files
they do not make any sense, nor do they get updated, if the
source code is kept in git
2018-11-02 23:53:21 +01:00

276 lines
8.9 KiB
C++

//=============================================================================
// Awl
// Audio Widget Library
//
// Copyright (C) 2002-2006 by Werner Schweer and others
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//=============================================================================
#include "fastlog.h"
#include "mslider.h"
namespace Awl {
#define METER_LEFT_EDGE 18
//---------------------------------------------------------
// MeterSlider
//---------------------------------------------------------
MeterSlider::MeterSlider(QWidget* parent)
: VolSlider(parent)
{
setAttribute(Qt::WA_NoSystemBackground, true);
_channel = 0;
yellowScale = -16; //-10;
redScale = 0;
_meterWidth = _scaleWidth * 3;
setChannel(1);
setMinimumHeight(50);
}
//---------------------------------------------------------
// sizeHint
//---------------------------------------------------------
QSize MeterSlider::sizeHint() const
{
int w = _meterWidth + _scaleWidth + _scaleWidth + 30;
return orientation() == Qt::Vertical ? QSize(w, 200) : QSize(200, w);
}
//---------------------------------------------------------
// setChannel
//---------------------------------------------------------
void MeterSlider::setChannel(int n)
{
if (n > _channel) {
for (int i = _channel; i < n; ++i) {
meterval.push_back(0.0f);
meterPeak.push_back(0.0f);
}
}
_channel = n;
}
//---------------------------------------------------------
// setMeterVal
//---------------------------------------------------------
void MeterSlider::setMeterVal(int channel, double v, double peak)
{
bool mustRedraw = false;
if (meterval[channel] != v) {
meterval[channel] = v;
mustRedraw = true;
}
if (peak != meterPeak[channel]) {
meterPeak[channel] = peak;
mustRedraw = true;
}
if (mustRedraw) {
int kh = sliderSize().height();
int mh = height() - kh;
update(METER_LEFT_EDGE, kh / 2, _meterWidth-1, mh);
}
}
//---------------------------------------------------------
// resetPeaks
// reset peak and overflow indicator
//---------------------------------------------------------
void MeterSlider::resetPeaks()
{
for (int i = 0; i < _channel; ++i)
meterPeak[i] = meterval[i];
update();
}
//---------------------------------------------------------
// resizeEvent
//---------------------------------------------------------
void MeterSlider::resizeEvent(QResizeEvent* /*ev*/)
{
int h = height();
int kh = sliderSize().height();
int mh = h - kh;
int mw = _meterWidth / _channel;
onPm = QPixmap(mw, mh);
offPm = QPixmap(mw, mh);
double range = maxValue() - minValue();
int h1 = mh - lrint((maxValue() - redScale) * mh / range);
int h2 = mh - lrint((maxValue() - yellowScale) * mh / range);
QColor yellowRed;
yellowRed.setHsv(QColor(Qt::yellow).hue() - 8,
QColor(Qt::yellow).saturation(),
QColor(Qt::yellow).value());
QColor yellRedRed;
yellRedRed.setHsv(QColor(Qt::yellow).hue() - 16,
QColor(Qt::yellow).saturation(),
QColor(Qt::yellow).value());
QLinearGradient linearGrad(QPointF(0, 0), QPointF(0, mh));
linearGrad.setColorAt(0, Qt::red);
linearGrad.setColorAt(1 - (double)(h1 - 5) / (double)mh, yellRedRed);
linearGrad.setColorAt(1 - (double)(h1 - 6) / (double)mh, yellowRed);
linearGrad.setColorAt(1 - (double)h2 / (double)mh, Qt::yellow);
linearGrad.setColorAt(1, Qt::green);
QColor darkYellowRed;
darkYellowRed.setHsv(QColor(Qt::darkYellow).hue()-8,
QColor(Qt::darkYellow).saturation(),
QColor(Qt::darkYellow).value());
QColor darkYellRedRed;
darkYellRedRed.setHsv(QColor(Qt::darkYellow).hue()-16,
QColor(Qt::darkYellow).saturation(),
QColor(Qt::darkYellow).value());
QLinearGradient linearDarkGrad(QPointF(0, 0), QPointF(0, mh));
linearDarkGrad.setColorAt(0, Qt::darkRed);
linearDarkGrad.setColorAt(1 - (double)(h1 - 5) / (double)mh, darkYellRedRed);
linearDarkGrad.setColorAt(1 - (double)(h1 - 6) / (double)mh, darkYellowRed);
linearDarkGrad.setColorAt(1 - (double)h2 / (double)mh, Qt::darkYellow);
linearDarkGrad.setColorAt(1, Qt::darkGreen);
QPainter p;
p.begin(&onPm);
p.fillRect(0, 0, mw, mh, linearGrad);
p.end();
p.begin(&offPm);
p.fillRect(0, 0, mw, mh, linearDarkGrad);
p.end();
}
//---------------------------------------------------------
// paintEvent
//---------------------------------------------------------
void MeterSlider::paintEvent(QPaintEvent* ev)
{
int h = height();
int kh = sliderSize().height();
int mh = h - kh;
double range = maxValue() - minValue();
int ppos = int(mh * (_value - minValue()) / range);
if (_invert)
ppos = mh - ppos;
QPainter p(this);
p.setRenderHint(QPainter::Antialiasing, false);
//---------------------------------------------------
// draw meter
//---------------------------------------------------
int mw = _meterWidth / _channel;
int x = METER_LEFT_EDGE;
int y1 = kh / 2;
int y3 = h - y1;
p.setPen(QPen(Qt::white, 2));
for (int i = 0; i < _channel; ++i) {
int h1 = mh - (lrint(fast_log10(meterval[i]) * -20.0f * mh / range));
if (h1 < 0)
h1 = 0;
else if (h1 > mh)
h1 = mh;
p.drawPixmap(x, y1 + mh - h1, mw, h1, onPm, 0, mh - h1, mw, h1);
p.drawPixmap(x, y1, mw, mh - h1, offPm, 0, 0, mw, mh - h1);
//---------------------------------------------------
// draw peak line
//---------------------------------------------------
h1 = mh - (lrint(fast_log10(meterPeak[i]) * -20.0f * mh / range));
if (h1 > mh)
h1 = mh;
if (h1 > 0)
p.drawLine(x, y3 - h1, x + mw, y3 - h1);
x += mw;
}
x += 4;
// optimize common case:
if (ev->rect() == QRect(METER_LEFT_EDGE, kh / 2, _meterWidth - 1, mh))
return;
QColor sc(isEnabled() ? _scaleColor : Qt::gray);
QColor svc(isEnabled() ? _scaleValueColor : Qt::gray);
p.setBrush(svc);
//---------------------------------------------------
// draw scale
//---------------------------------------------------
int y2 = h - (ppos + y1);
p.fillRect(x, y1, _scaleWidth, y2 - y1, sc);
p.fillRect(x, y2, _scaleWidth, y3 - y2, svc);
//---------------------------------------------------
// draw tick marks
//---------------------------------------------------
QFont f(p.font());
f.setPointSize(6);
p.setFont(f);
p.setPen(QPen(Qt::darkGray, 2));
QString s;
for (int i = 0; i <= range; i += 10) {
h = y1 + lrint(i * mh / range);
s.setNum(i);
if (i == 0) {
p.drawText(QRect(0, h - 3, METER_LEFT_EDGE - 3, 9), Qt::AlignRight, QString("dB"));
p.drawLine(METER_LEFT_EDGE - 1, h + 1, METER_LEFT_EDGE - 1, h + 1);
continue;
}
else if (i == range)
h -= 2;
p.drawText(QRect(0, h - 3, METER_LEFT_EDGE - 3, 9), Qt::AlignRight, QString("-") + s);
p.drawLine(METER_LEFT_EDGE - 1, h + 1, METER_LEFT_EDGE - 1, h + 1);
}
//---------------------------------------------------
// draw slider
//---------------------------------------------------
x += _scaleWidth / 2;
p.setPen(QPen(svc, 0));
p.translate(QPointF(x, y2));
p.setRenderHint(QPainter::Antialiasing, true);
p.drawPath(*points);
}
//---------------------------------------------------------
// mousePressEvent
//---------------------------------------------------------
void MeterSlider::mousePressEvent(QMouseEvent* ev)
{
if (ev->pos().x() < _meterWidth) {
emit meterClicked();
return;
}
VolSlider::mousePressEvent(ev);
}
}