/** ** This file is part of the CatRadio project. ** Copyright 2022 Gianfranco Sordetti IZ8EWD . ** ** 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 . **/ #include "submeter.h" #include #include 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; }