/** ** 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 "smeter.h" #include #include SMeter::SMeter(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 = 100; gateValue = 80; longStep = 20; shortStep = 10; precision = 0; meterTx = false; currentValue = minValue; peakValue = minValue; peakFactor = 0.1; peakHold = true; } void SMeter::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); drawScaleSMeter(&painter); drawScalePWRMeter(&painter); } void SMeter::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 SMeter::drawProgress(QPainter *painter) { double max, min; double gate; painter->save(); painter->setPen(Qt::NoPen); painter->setBrush(progressColor); if (meterTx) //RF power meter { max = maxValue; min = minValue; gate = gateValue; } else //SMeter { max = 60; min = -54; gate = 0; } double length = width()-14; double increment = length / (max - min); double initX, initXX; if (currentValue>max) currentValue = max; if (currentValue>gate) { initX = (gate - min) * increment; QRect rect(1, height()/3+2+1, initX, height()/3-4-2); painter->drawRect(rect); //Red bar initXX = (currentValue - gate) * increment; QRect rect2(initX+1, height()/3+2+1, initXX, height()/3-4-2); painter->setBrush(Qt::red); painter->drawRect(rect2); } else { initX = (currentValue - min) * increment; QRect rect(1, height()/3+2+1, initX, height()/3-4-2); painter->drawRect(rect); } painter->restore(); } void SMeter::drawPeak(QPainter *painter) { double max, min; double gate; painter->save(); painter->setPen(Qt::NoPen); if (meterTx) //RF power meter { max = maxValue; min = minValue; gate = gateValue; } else //SMeter { max = 60; min = -54; gate = 0; } double length = width()-14; double increment = length / (max - min); 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); initX = (peakValue - min) * increment; QRect rect(initX - 2, height()/3+2+1, 2, height()/3-4-2); painter->drawRect(rect); painter->restore(); } void SMeter::drawScalePWRMeter(QPainter *painter) { painter->save(); painter->setPen(scaleColor); double initX = 0; double initTopY = height()*2/3-2; double length = width()-12; double increment = length / (maxValue - minValue); int longLineLen = 6; int shortLineLen = 3; QFontMetrics meterFont(painter->font()); double textHeight = meterFont.height(); //Draw scale and scale values based on range values Long lines 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 { QPointF textPot = QPointF(initX, initTopY + textHeight); painter->drawText(textPot, "PO"); 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 SMeter::drawScaleSMeter(QPainter *painter) { int minValue = -54; //Set min and max value according to Hamlib SMeter definition int maxValue = 60; int longLineLen = 6; int shortLineLen = 3; double initX = 0; int sUnit = 0; double initBottomY = height()/3+2; double length = width()-12; double increment = length / (maxValue - minValue); QFontMetrics meterFont(painter->font()); double textHeight = meterFont.height(); painter->save(); painter->setPen(scaleColor); //Draw scale and scale values based on range values int longStep = 12; int shortStep = 6; for (int i = minValue; i <= 0; i = i + shortStep) //S0 to S9 { if (i == minValue) { QPointF textPot = QPointF(initX, initBottomY - 2); painter->drawText(textPot, "S"); initX += increment * shortStep; sUnit = sUnit + 1; continue; } if (i % longStep == 0) { QPointF topPot = QPointF(initX, initBottomY); QPointF bottomPot = QPointF(initX, initBottomY - longLineLen); painter->drawLine(topPot, bottomPot); QString strValue = QString::number(sUnit); double textWidth = fontMetrics().horizontalAdvance(strValue); QPointF textPot = QPointF(initX - textWidth / 2, initBottomY - textHeight / 2 - longLineLen + 2); painter->drawText(textPot, strValue); } else { QPointF topPot = QPointF(initX, initBottomY); QPointF bottomPot = QPointF(initX, initBottomY - shortLineLen); painter->drawLine(topPot, bottomPot); } sUnit = sUnit + 1; initX += increment * shortStep; } initX -= increment * shortStep; shortStep = 10; longStep = 20; for (int i = 0; i <= maxValue; i = i + shortStep) //S9+ to S9+60 { if (i % longStep == 0) { QPointF topPot = QPointF(initX, initBottomY); QPointF bottomPot = QPointF(initX, initBottomY - longLineLen); painter->drawLine(topPot, bottomPot); if (i == 0) //Do not draw the first value { initX += increment * shortStep; continue; } QString strValue = "+" + QString::number(i); double textWidth = fontMetrics().horizontalAdvance(strValue); QPointF textPot = QPointF(initX - textWidth / 2, initBottomY - textHeight / 2 - longLineLen + 2); painter->drawText(textPot, strValue); } else { QPointF topPot = QPointF(initX, initBottomY); QPointF bottomPot = QPointF(initX, initBottomY - shortLineLen); painter->drawLine(topPot, bottomPot); } initX += increment * shortStep; } painter->restore(); } void SMeter::setMinValue(double value) { minValue = value; } void SMeter::setMaxValue(double value) { maxValue = value; update(); } void SMeter::setGateValue(double value) { gateValue = value; } void SMeter::setLongStep(double value) { longStep = value; } void SMeter::setShortStep(double value) { shortStep = value; } void SMeter::setPrecision(int value) { precision = value; } void SMeter::setBgColor(QColor color) { bgColor = color; } void SMeter::setLineColor(QColor color) { lineColor = color; } void SMeter::setProgressColor(QColor color) { progressColor = color; } void SMeter::setScaleColor(QColor color) { scaleColor = color; } void SMeter::setValue(double value) { currentValue = value; update(1, height()/3+2+1, width()-14, height()/3-4-2); } void SMeter::setValue(int value) { setValue(double(value)); } void SMeter::setTx(bool Tx) { meterTx = Tx; } bool SMeter::getTx() { return meterTx; } void SMeter::setPeak(bool Peak) { peakHold = Peak; } void SMeter::setPeakFactor(double factor) { peakFactor = factor; } void SMeter::resetPeakValue() { if (meterTx) peakValue = minValue; else peakValue = -54; }