CatRadio/submeter.cpp

341 wiersze
9.3 KiB
C++

/**
** This file is part of the CatRadio project.
** Copyright 2022 Gianfranco Sordetti IZ8EWD <iz8ewd@pianetaradio.it>.
**
** 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 3 of the License, or
** (at your option) any later version.
**
** 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, see <http://www.gnu.org/licenses/>.
**/
#include "submeter.h"
#include <QPainter>
#include <math.h>
SubMeter::SubMeter(QWidget *parent) : QWidget(parent)
{
lineColor = QColor(Qt::black);
bgColor = QColor(Qt::white);
progressColor = QColor(Qt::green);
scaleColor = QColor(Qt::black);
//Default value
minValue = 0;
maxValue = 10;
gateValue = 10;
longStep = 5;
shortStep = 1;
precision = 0;
meterSWR = 0;
currentValue = 0;
peakValue = minValue;
peakFactor = 0.1;
peakHold = true;
}
void SubMeter::paintEvent(QPaintEvent *)
{
QPainter painter(this);
painter.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing);
QFont font;
font = painter.font();
font.setPointSize(font.pointSize() - 2);
painter.setFont(font);
drawMeter(&painter);
drawProgress(&painter);
if (peakHold) drawPeak(&painter);
drawScale(&painter);
}
void SubMeter::drawMeter(QPainter *painter)
{
painter->save();
QPen pen(lineColor, 1, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin);
painter->setPen(pen);
painter->setBrush(bgColor);
painter->drawRect(0, height()/3+2, width()-12, height()/3-4);
painter->restore();
}
void SubMeter::drawProgress(QPainter *painter)
{
painter->save();
painter->setPen(Qt::NoPen);
painter->setBrush(progressColor);
double length = width()-14;
double increment;
double initX, initXX;
if (meterSWR) increment = length / (10 * log10(maxValue));
else increment = length / (maxValue - minValue);
if (currentValue>gateValue)
{
if (currentValue > maxValue) currentValue = maxValue; //Trim value if overload scale
if (meterSWR) initX = 10 * log10(gateValue) * increment;
else initX = (gateValue - minValue) * increment;
QRect rect(1, height()/3+2+1, initX, height()/3-4-2);
painter->drawRect(rect);
//Red bar
if (meterSWR)
{
if (currentValue > maxValue) currentValue = maxValue; //Trim value if overload scale
initXX = 10 * (log10(currentValue) - log10(gateValue)) * increment;
}
else
{
if (currentValue > maxValue) currentValue = maxValue; //Trim value if overload scale
initXX = (currentValue - gateValue) * increment;
}
QRect rect2(initX+1, height()/3+2+1, initXX+1, height()/3-4-2);
painter->setBrush(Qt::red);
painter->drawRect(rect2);
}
else
{
if (meterSWR) initX = 10 * log10(currentValue) * increment;
else initX = (currentValue - minValue) * increment;
QRect rect(1, height()/3+2+1, initX, height()/3-4-2);
painter->drawRect(rect);
}
painter->restore();
}
void SubMeter::drawPeak(QPainter *painter)
{
double max, min;
double gate;
painter->save();
painter->setPen(Qt::NoPen);
max = maxValue;
min = minValue;
gate = gateValue;
if (meterSWR) min = 1; //SWR meter
double length = width()-14;
double increment;
double initX;
if (currentValue>=peakValue) peakValue = currentValue;
else peakValue = peakValue - peakFactor*(peakValue - currentValue);
if (peakValue>max) peakValue = max;
if (peakValue>gate) painter->setBrush(QColor(Qt::red));
else painter->setBrush(progressColor);
if (meterSWR)
{
increment = length / (10 * log10(maxValue));
initX = 10 * log10(peakValue) * increment;
}
else
{
increment = length / (max - min);
initX = (peakValue - min) * increment;
}
//initX = (peakValue - min) * increment;
QRect rect(initX - 2, height()/3+2+1, 2, height()/3-4-2);
painter->drawRect(rect);
painter->restore();
}
void SubMeter::drawScale(QPainter *painter)
{
painter->save();
painter->setPen(scaleColor);
double initX = 0;
double initTopY = height()*2/3-2;
double length = width()-12;
double increment;
int longLineLen = 6;
int shortLineLen = 3;
QFontMetrics meterFont(painter->font());
double textHeight = meterFont.height();
if (meterSWR) increment = length / (10 * log10(maxValue));
else increment = length / (maxValue - minValue);
if (meterSWR) //Draw SWR meter with log scale
{
double j = 1.0;
for (int i = 0; i <= 10; i++) //1.0 to 2.0
{
QPointF topPot = QPointF(initX, initTopY);
QPointF bottomPot;
if (abs(j - 1.5) < 0.01 || abs(j - 2.0) < 0.01)
{
bottomPot = QPointF(initX, initTopY + longLineLen);
QString strValue = QString::number(j, 'f', 1);
double textWidth = fontMetrics().horizontalAdvance(strValue);
QPointF textPot = QPointF(initX - textWidth / 2, initTopY + textHeight + longLineLen - 2);
painter->drawText(textPot, strValue);
}
else bottomPot = QPointF(initX, initTopY + shortLineLen);
painter->drawLine(topPot, bottomPot);
j +=0.1;
initX = 10 * log10(j) * increment;
}
for (int i = 11; i <= 25; i++) //2.1 to 3.5
{
QPointF topPot = QPointF(initX, initTopY);
QPointF bottomPot;
if (abs(j - 2.5) < 0.01 || abs(j - 3.0) < 0.01 || abs(j - 3.5) < 0.01)
{
bottomPot = QPointF(initX, initTopY + longLineLen);
QString strValue = QString::number(j, 'f', 1);
double textWidth = fontMetrics().horizontalAdvance(strValue);
QPointF textPot = QPointF(initX - textWidth / 2, initTopY + textHeight + longLineLen - 2);
painter->drawText(textPot, strValue);
painter->drawLine(topPot, bottomPot);
}
j +=0.1;
initX = 10 * log10(j) * increment;
}
}
else //Draw scale and scale values based on range values
{
int stepNumber = (maxValue - minValue) / shortStep;
for (int i = 0; i <= stepNumber; i++)
{
double j = i * shortStep + minValue;
if (fmod(j,longStep) == 0)
{
if (j == minValue) //Do not draw the first value
{
initX += increment * shortStep;
continue;
}
QPointF topPot = QPointF(initX, initTopY);
QPointF bottomPot = QPointF(initX, initTopY + longLineLen);
painter->drawLine(topPot, bottomPot);
QString strValue = QString("%1").arg(j, 0, 'f', precision);
double textWidth = fontMetrics().horizontalAdvance(strValue);
QPointF textPot = QPointF(initX - textWidth / 2, initTopY + textHeight + longLineLen - 2);
painter->drawText(textPot, strValue);
}
else
{
QPointF topPot = QPointF(initX, initTopY);
QPointF bottomPot = QPointF(initX, initTopY + shortLineLen);
painter->drawLine(topPot, bottomPot);
}
initX += increment * shortStep;
}
}
painter->restore();
}
void SubMeter::setMinValue(double value)
{
minValue = value;
update();
}
void SubMeter::setMaxValue(double value)
{
maxValue = value;
update();
}
void SubMeter::setGateValue(double value)
{
gateValue = value;
}
void SubMeter::setLongStep(double value)
{
longStep = value;
update();
}
void SubMeter::setShortStep(double value)
{
shortStep = value;
update();
}
void SubMeter::setPrecision(int value)
{
precision = value;
update();
}
void SubMeter::setBgColor(QColor color)
{
bgColor = color;
}
void SubMeter::setLineColor(QColor color)
{
lineColor = color;
}
void SubMeter::setProgressColor(QColor color)
{
progressColor = color;
}
void SubMeter::setScaleColor(QColor color)
{
scaleColor = color;
}
void SubMeter::setValue(double value)
{
currentValue = value;
update();
}
void SubMeter::setValue(int value)
{
setValue(double(value));
}
void SubMeter::setMeterSWR(bool swr)
{
meterSWR = swr;
}
void SubMeter::setPeak(bool Peak)
{
peakHold = Peak;
}
void SubMeter::setPeakFactor(double factor)
{
peakFactor = factor;
}
void SubMeter::resetPeakValue()
{
if (!meterSWR) peakValue = minValue;
else peakValue = 1.0;
}