2021-02-24 00:18:19 -08:00
|
|
|
#include "meter.h"
|
|
|
|
|
#include <QDebug>
|
|
|
|
|
|
|
|
|
|
meter::meter(QWidget *parent) : QWidget(parent)
|
|
|
|
|
{
|
|
|
|
|
//QPainter painter(this);
|
|
|
|
|
|
|
|
|
|
// Colors from qdarkstylesheet:
|
|
|
|
|
// $COLOR_BACKGROUND_LIGHT: #505F69;
|
|
|
|
|
// $COLOR_BACKGROUND_NORMAL: #32414B;
|
|
|
|
|
// $COLOR_BACKGROUND_DARK: #19232D;
|
|
|
|
|
// $COLOR_FOREGROUND_LIGHT: #F0F0F0; // grey
|
|
|
|
|
// $COLOR_FOREGROUND_NORMAL: #AAAAAA; // grey
|
|
|
|
|
// $COLOR_FOREGROUND_DARK: #787878; // grey
|
|
|
|
|
// $COLOR_SELECTION_LIGHT: #148CD2;
|
|
|
|
|
// $COLOR_SELECTION_NORMAL: #1464A0;
|
|
|
|
|
// $COLOR_SELECTION_DARK: #14506E;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Colors I found that I liked from VFD images:
|
|
|
|
|
// 3FB7CD
|
|
|
|
|
// 3CA0DB
|
|
|
|
|
//
|
|
|
|
|
// Text in qdarkstylesheet seems to be #EFF0F1
|
|
|
|
|
|
2021-08-16 23:25:11 -07:00
|
|
|
if(drawLabels)
|
|
|
|
|
{
|
|
|
|
|
mXstart = 32;
|
|
|
|
|
} else {
|
|
|
|
|
mXstart = 0;
|
|
|
|
|
}
|
|
|
|
|
|
2024-11-05 18:46:21 +00:00
|
|
|
meterType = meterNone;
|
2021-07-16 17:45:07 -07:00
|
|
|
|
2024-06-23 11:59:41 +01:00
|
|
|
currentColor = colorFromString("#148CD2");
|
2021-02-24 00:18:19 -08:00
|
|
|
currentColor = currentColor.darker();
|
|
|
|
|
|
2024-06-23 11:59:41 +01:00
|
|
|
peakColor = colorFromString("#3CA0DB");
|
2021-02-24 00:18:19 -08:00
|
|
|
peakColor = peakColor.lighter();
|
|
|
|
|
|
2024-06-23 11:59:41 +01:00
|
|
|
averageColor = colorFromString("#3FB7CD");
|
2021-02-24 00:18:19 -08:00
|
|
|
|
2024-06-23 11:59:41 +01:00
|
|
|
lowTextColor = colorFromString("#eff0f1");
|
2021-02-24 00:18:19 -08:00
|
|
|
lowLineColor = lowTextColor;
|
|
|
|
|
|
2021-07-18 14:27:21 -07:00
|
|
|
avgLevels.resize(averageBalisticLength, 0);
|
|
|
|
|
peakLevels.resize(peakBalisticLength, 0);
|
|
|
|
|
|
2025-02-17 11:24:04 -08:00
|
|
|
scaleCache = new QImage(QSize(255+mXstart+15, widgetWindowHeight), QImage::Format_ARGB32);
|
2025-02-17 11:20:26 -08:00
|
|
|
scaleCache->fill(Qt::transparent);
|
2024-11-05 18:46:21 +00:00
|
|
|
|
2024-02-05 21:03:08 -08:00
|
|
|
combo = new QComboBox(this);
|
2024-11-07 19:13:32 +00:00
|
|
|
combo->addItem("None", meterNone);
|
2025-01-09 00:35:26 +00:00
|
|
|
combo->addItem("Sub S-Meter", meterSubS);
|
2025-01-10 15:16:16 +00:00
|
|
|
combo->addItem("SWR", meterSWR);
|
2024-11-07 19:13:32 +00:00
|
|
|
combo->addItem("ALC", meterALC);
|
|
|
|
|
combo->addItem("Compression", meterComp);
|
|
|
|
|
combo->addItem("Voltage", meterVoltage);
|
|
|
|
|
combo->addItem("Current", meterCurrent);
|
|
|
|
|
combo->addItem("Center", meterCenter);
|
|
|
|
|
combo->addItem("TxRxAudio", meterAudio);
|
|
|
|
|
combo->addItem("RxAudio", meterRxAudio);
|
|
|
|
|
combo->addItem("TxAudio", meterTxMod);
|
2024-02-05 21:03:08 -08:00
|
|
|
|
2024-11-05 18:46:21 +00:00
|
|
|
combo->blockSignals(false);
|
2024-02-05 21:03:08 -08:00
|
|
|
connect(combo, SIGNAL(activated(int)), this, SLOT(acceptComboItem(int)));
|
|
|
|
|
//connect(combo, SIGNAL(currentIndexChanged(int)), this, SLOT(acceptComboItem(int)));
|
|
|
|
|
|
2024-02-10 12:40:17 -08:00
|
|
|
this->setToolTip("");
|
2024-02-05 21:03:08 -08:00
|
|
|
combo->hide();
|
|
|
|
|
this->installEventFilter(this);
|
2021-02-24 00:18:19 -08:00
|
|
|
}
|
|
|
|
|
|
2024-02-06 11:06:50 -08:00
|
|
|
void meter::setCompReverse(bool reverse) {
|
|
|
|
|
this->reverseCompMeter = reverse;
|
2025-02-17 10:29:05 -08:00
|
|
|
recentlyChangedParameters = true; // force scale redraw
|
2024-02-06 11:06:50 -08:00
|
|
|
}
|
|
|
|
|
|
2025-02-17 14:36:32 -08:00
|
|
|
void meter::setUseGradients(bool useGrads) {
|
|
|
|
|
this->useGradients = useGrads;
|
|
|
|
|
}
|
|
|
|
|
|
2022-08-22 21:22:01 -07:00
|
|
|
void meter::setColors(QColor current, QColor peakScale, QColor peakLevel,
|
2022-08-21 16:47:17 -07:00
|
|
|
QColor average, QColor lowLine,
|
|
|
|
|
QColor lowText)
|
|
|
|
|
{
|
|
|
|
|
currentColor = current;
|
2022-08-22 21:22:01 -07:00
|
|
|
|
|
|
|
|
peakColor = peakLevel; // color for the peak level indicator
|
|
|
|
|
highLineColor = peakScale; // color for the red side of the scale
|
|
|
|
|
highTextColor = peakScale; // color for the red side of the scale's text
|
|
|
|
|
|
2022-08-21 16:47:17 -07:00
|
|
|
averageColor = average;
|
2022-08-22 21:22:01 -07:00
|
|
|
|
|
|
|
|
midScaleColor = QColor(Qt::yellow);
|
|
|
|
|
centerTuningColor = QColor(Qt::green);
|
|
|
|
|
|
2022-08-21 16:47:17 -07:00
|
|
|
lowLineColor = lowLine;
|
|
|
|
|
lowTextColor = lowText;
|
2022-08-22 18:09:20 -07:00
|
|
|
this->update();
|
2022-08-21 16:47:17 -07:00
|
|
|
}
|
|
|
|
|
|
2021-08-20 22:19:47 -07:00
|
|
|
void meter::clearMeterOnPTTtoggle()
|
2021-07-16 17:45:07 -07:00
|
|
|
{
|
2021-08-20 22:19:47 -07:00
|
|
|
// When a meter changes type, such as the fixed S -- TxPo meter,
|
2022-03-23 15:45:51 +00:00
|
|
|
// there is automatic clearing. However, some meters do not switch on their own,
|
2021-08-20 22:19:47 -07:00
|
|
|
// and thus we are providing this clearing method. We are careful
|
|
|
|
|
// not to clear meters that don't make sense to clear (such as Vd and Id)
|
2021-07-17 23:39:40 -07:00
|
|
|
|
2021-08-20 22:19:47 -07:00
|
|
|
|
|
|
|
|
if( (meterType == meterALC) || (meterType == meterSWR)
|
2021-08-20 22:23:16 -07:00
|
|
|
|| (meterType == meterComp) || (meterType == meterTxMod)
|
|
|
|
|
|| (meterType == meterCenter ))
|
2021-08-20 22:19:47 -07:00
|
|
|
{
|
|
|
|
|
clearMeter();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void meter::clearMeter()
|
|
|
|
|
{
|
2021-07-20 11:11:51 -07:00
|
|
|
current = 0;
|
|
|
|
|
average = 0;
|
|
|
|
|
peak = 0;
|
|
|
|
|
|
2021-07-18 14:27:21 -07:00
|
|
|
avgLevels.clear();
|
|
|
|
|
peakLevels.clear();
|
|
|
|
|
avgLevels.resize(averageBalisticLength, 0);
|
|
|
|
|
peakLevels.resize(peakBalisticLength, 0);
|
2021-07-17 23:39:40 -07:00
|
|
|
|
2021-07-18 14:27:21 -07:00
|
|
|
peakPosition = 0;
|
|
|
|
|
avgPosition = 0;
|
2021-07-16 17:45:07 -07:00
|
|
|
// re-draw scale:
|
2021-07-20 11:11:51 -07:00
|
|
|
update();
|
2021-07-16 17:45:07 -07:00
|
|
|
}
|
|
|
|
|
|
2024-02-10 12:40:17 -08:00
|
|
|
void meter::setMeterType(meter_t m_type_req)
|
2021-08-20 22:19:47 -07:00
|
|
|
{
|
2024-02-10 12:40:17 -08:00
|
|
|
if(m_type_req == meterType)
|
2021-08-20 22:19:47 -07:00
|
|
|
return;
|
|
|
|
|
|
2025-02-17 10:29:05 -08:00
|
|
|
|
2024-11-05 18:46:21 +00:00
|
|
|
this->setToolTip("Double-click to select meter type.");
|
|
|
|
|
|
|
|
|
|
combo->blockSignals(true);
|
|
|
|
|
combo->clear();
|
|
|
|
|
switch (m_type_req)
|
|
|
|
|
{
|
|
|
|
|
case meterS:
|
|
|
|
|
case meterPower:
|
|
|
|
|
case meterdBm:
|
|
|
|
|
case meterdBu:
|
|
|
|
|
case meterdBuEMF:
|
2025-01-09 00:35:26 +00:00
|
|
|
combo->addItem("Main S-Meter", meterS);
|
2024-11-05 18:46:21 +00:00
|
|
|
combo->addItem("dBu Meter", meterdBu);
|
|
|
|
|
combo->addItem("dBu EMF", meterdBuEMF);
|
|
|
|
|
combo->addItem("dBm Meter", meterdBm);
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
combo->addItem("None", meterNone);
|
2025-01-09 00:35:26 +00:00
|
|
|
combo->addItem("Sub S-Meter", meterSubS);
|
2025-01-10 15:16:16 +00:00
|
|
|
combo->addItem("SWR", meterSWR);
|
2024-11-05 18:46:21 +00:00
|
|
|
combo->addItem("ALC", meterALC);
|
|
|
|
|
combo->addItem("Compression", meterComp);
|
|
|
|
|
combo->addItem("Voltage", meterVoltage);
|
|
|
|
|
combo->addItem("Current", meterCurrent);
|
|
|
|
|
combo->addItem("Center", meterCenter);
|
|
|
|
|
combo->addItem("TxRxAudio", meterAudio);
|
|
|
|
|
combo->addItem("RxAudio", meterRxAudio);
|
|
|
|
|
combo->addItem("TxAudio", meterTxMod);
|
|
|
|
|
break;
|
2024-02-10 12:40:17 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int m_index = combo->findData(m_type_req);
|
|
|
|
|
combo->setCurrentIndex(m_index);
|
|
|
|
|
combo->blockSignals(false);
|
|
|
|
|
|
|
|
|
|
meterType = m_type_req;
|
2025-02-17 10:29:05 -08:00
|
|
|
this->meterShortString = getMeterDebug(meterType);
|
|
|
|
|
recentlyChangedParameters = true;
|
2021-08-20 22:19:47 -07:00
|
|
|
// clear average and peak vectors:
|
|
|
|
|
this->clearMeter();
|
|
|
|
|
}
|
|
|
|
|
|
2025-02-17 10:29:05 -08:00
|
|
|
void meter::setMeterExtremities(double min, double max, double redline) {
|
|
|
|
|
this->scaleMin = min;
|
|
|
|
|
this->scaleMax = max;
|
|
|
|
|
this->scaleRedline = redline;
|
|
|
|
|
recentlyChangedParameters = true;
|
|
|
|
|
haveExtremities = true;
|
|
|
|
|
qDebug() << "Meter extremities set: shortString: " << meterShortString
|
|
|
|
|
<< ", min: " << min << ", max: " << max
|
|
|
|
|
<< ", redline: " << redline << "meter: " << meterType;
|
|
|
|
|
}
|
|
|
|
|
|
2024-02-05 21:03:08 -08:00
|
|
|
void meter::blockMeterType(meter_t mtype) {
|
|
|
|
|
enableAllComboBoxItems(combo);
|
2025-02-17 10:29:05 -08:00
|
|
|
//qDebug() << "Asked to block meter of type: " << getMeterDebug(mtype);
|
2024-02-05 21:03:08 -08:00
|
|
|
if(mtype != meterNone) {
|
|
|
|
|
int m_index = combo->findData(mtype);
|
|
|
|
|
setComboBoxItemEnabled(combo, m_index, false);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-05-15 13:47:45 +01:00
|
|
|
meter_t meter::getMeterType()
|
2021-07-17 23:39:40 -07:00
|
|
|
{
|
|
|
|
|
return meterType;
|
|
|
|
|
}
|
2021-02-24 00:18:19 -08:00
|
|
|
|
2021-07-19 23:46:11 -07:00
|
|
|
void meter::setMeterShortString(QString s)
|
|
|
|
|
{
|
|
|
|
|
meterShortString = s;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QString meter::getMeterShortString()
|
|
|
|
|
{
|
|
|
|
|
return meterShortString;
|
|
|
|
|
}
|
|
|
|
|
|
2024-02-05 21:03:08 -08:00
|
|
|
void meter::acceptComboItem(int item) {
|
|
|
|
|
qDebug() << "Meter selected combo item number: " << item;
|
|
|
|
|
|
|
|
|
|
meter_t meterTypeRequested = static_cast<meter_t>(combo->itemData(item).toInt());
|
|
|
|
|
if(meterType != meterTypeRequested) {
|
|
|
|
|
qDebug() << "Changing meter to type: " << getMeterDebug(meterTypeRequested) << ", with item index: " << item;
|
|
|
|
|
emit configureMeterSignal(meterTypeRequested);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
combo->hide();
|
|
|
|
|
freezeDrawing = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void meter::handleDoubleClick() {
|
|
|
|
|
freezeDrawing = true;
|
|
|
|
|
combo->show();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool meter::eventFilter(QObject *object, QEvent *event) {
|
2024-02-10 12:40:17 -08:00
|
|
|
|
|
|
|
|
if( (freezeDrawing) && (event->type() == QEvent::MouseButtonPress) ) {
|
|
|
|
|
combo->hide();
|
|
|
|
|
freezeDrawing = false;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if( (freezeDrawing) && (event->type() == QEvent::MouseButtonDblClick) ) {
|
|
|
|
|
combo->hide();
|
|
|
|
|
freezeDrawing = false;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2024-02-05 21:03:08 -08:00
|
|
|
if(event->type() == QEvent::MouseButtonDblClick) {
|
2024-11-05 18:46:21 +00:00
|
|
|
//if( !(meterType == meterS || meterType == meterPower)) {
|
|
|
|
|
handleDoubleClick();
|
|
|
|
|
//}
|
2024-02-05 21:03:08 -08:00
|
|
|
return true;
|
|
|
|
|
}
|
2024-02-10 12:40:17 -08:00
|
|
|
|
2024-02-05 21:03:08 -08:00
|
|
|
(void)object;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2021-02-24 00:18:19 -08:00
|
|
|
void meter::paintEvent(QPaintEvent *)
|
|
|
|
|
{
|
2024-02-05 21:03:08 -08:00
|
|
|
if(freezeDrawing)
|
|
|
|
|
return;
|
2024-02-05 21:39:23 -08:00
|
|
|
|
2025-02-17 10:29:05 -08:00
|
|
|
if(!haveExtremities) {
|
|
|
|
|
qWarning() << "Cannot draw meter without scale data!";
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2021-02-24 00:18:19 -08:00
|
|
|
QPainter painter(this);
|
|
|
|
|
// This next line sets up a canvis within the
|
2022-03-23 15:45:51 +00:00
|
|
|
// space of the widget, and gives it coordinates.
|
2021-02-24 00:18:19 -08:00
|
|
|
// The end effect, is that the drawing functions will all
|
|
|
|
|
// scale to the window size.
|
2021-08-16 23:25:11 -07:00
|
|
|
painter.setRenderHint(QPainter::SmoothPixmapTransform);
|
|
|
|
|
painter.setFont(QFont(this->fontInfo().family(), fontSize));
|
|
|
|
|
widgetWindowHeight = this->height();
|
|
|
|
|
painter.setWindow(QRect(0, 0, 255+mXstart+15, widgetWindowHeight));
|
|
|
|
|
barHeight = widgetWindowHeight / 2;
|
2021-07-19 23:46:11 -07:00
|
|
|
|
2025-02-17 11:20:26 -08:00
|
|
|
// We regenerate the scale graphics if:
|
|
|
|
|
// 1. The meter type changed, or,
|
2025-02-17 10:29:05 -08:00
|
|
|
// 2. The meter extremities changed
|
|
|
|
|
|
2025-02-17 11:20:26 -08:00
|
|
|
if( (lastDrawMeterType != meterType)
|
|
|
|
|
|| (recentlyChangedParameters)) {
|
|
|
|
|
regenerateScale(&painter);
|
|
|
|
|
}
|
2025-02-17 10:29:05 -08:00
|
|
|
|
2025-02-17 11:20:26 -08:00
|
|
|
if(scaleReady) {
|
|
|
|
|
recallScale(&painter);
|
|
|
|
|
}
|
2025-02-17 10:29:05 -08:00
|
|
|
|
2025-02-17 11:20:26 -08:00
|
|
|
// Guard against drawing empty or garbage data:
|
|
|
|
|
if(haveReceivedSomeData) {
|
|
|
|
|
painter.setPen(currentColor);
|
|
|
|
|
painter.setBrush(currentColor);
|
2025-02-17 10:29:05 -08:00
|
|
|
|
2025-02-17 11:20:26 -08:00
|
|
|
if(meterType == meterCenter)
|
2025-02-17 10:29:05 -08:00
|
|
|
{
|
2025-02-17 11:20:26 -08:00
|
|
|
drawValue_Center(&painter);
|
|
|
|
|
} else if ( (meterType == meterAudio) ||
|
|
|
|
|
(meterType == meterTxMod) ||
|
|
|
|
|
(meterType == meterRxAudio))
|
2025-02-17 10:29:05 -08:00
|
|
|
{
|
2025-02-17 11:20:26 -08:00
|
|
|
drawValue_Log(&painter);
|
|
|
|
|
} else {
|
|
|
|
|
if(meterType==meterComp)
|
|
|
|
|
drawValue_Linear(&painter, this->reverseCompMeter);
|
|
|
|
|
else
|
|
|
|
|
drawValue_Linear(&painter, false);
|
2025-02-17 10:29:05 -08:00
|
|
|
}
|
2025-02-17 11:20:26 -08:00
|
|
|
haveUpdatedData = false;
|
2021-07-16 17:45:07 -07:00
|
|
|
}
|
2025-02-17 11:20:26 -08:00
|
|
|
}
|
2021-02-24 00:18:19 -08:00
|
|
|
|
2025-02-17 11:20:26 -08:00
|
|
|
void meter::regenerateScale(QPainter *screenPainterHints) {
|
|
|
|
|
// draw a scale and save to scaleCache
|
2025-02-17 10:29:05 -08:00
|
|
|
|
2025-02-17 11:52:41 -08:00
|
|
|
QSize sizeHint = screenPainterHints->window().size();
|
2025-02-17 11:38:15 -08:00
|
|
|
|
2025-02-17 11:52:41 -08:00
|
|
|
if(sizeHint != scaleCache->size()) {
|
|
|
|
|
qDebug() << "Meter Widget painter window does not match cache image size.";
|
2025-02-17 11:38:15 -08:00
|
|
|
qDebug() << "Meter Scale cache image size: " << scaleCache->size();
|
|
|
|
|
qDebug() << "Meter Widget size: " << this->size();
|
2025-02-17 11:52:41 -08:00
|
|
|
qDebug() << "Meter painter window: " << sizeHint;
|
2025-02-17 11:38:15 -08:00
|
|
|
delete scaleCache;
|
2025-02-17 11:52:41 -08:00
|
|
|
scaleCache = new QImage(sizeHint, QImage::Format_ARGB32);
|
2025-02-17 11:38:15 -08:00
|
|
|
}
|
2025-02-21 09:57:10 -08:00
|
|
|
#ifdef QT_DEBUG
|
|
|
|
|
QString fontName = screenPainterHints->font().family();
|
|
|
|
|
int fontSize = screenPainterHints->font().pointSize();
|
|
|
|
|
qDebug() << "screenPainterHints: Font: " << fontName << ", size: " << fontSize;
|
|
|
|
|
#endif
|
|
|
|
|
|
2025-02-17 11:38:15 -08:00
|
|
|
|
2025-02-17 21:00:11 -08:00
|
|
|
scaleCache->fill(Qt::transparent);
|
2025-02-17 11:20:26 -08:00
|
|
|
QPainter painter(scaleCache);
|
|
|
|
|
painter.setRenderHints(screenPainterHints->renderHints()); // Copy render hints
|
2025-02-17 11:38:15 -08:00
|
|
|
//painter.setRenderHint(QPainter::Antialiasing); // fuzz city
|
2025-02-17 11:20:26 -08:00
|
|
|
//painter.setRenderHint(QPainter::HighQualityAntialiasing); // depreciated
|
|
|
|
|
//painter.setRenderHint(QPainter::TextAntialiasing);
|
2025-02-17 11:38:15 -08:00
|
|
|
//painter.setRenderHint(QPainter::SmoothPixmapTransform);
|
2021-07-18 14:27:21 -07:00
|
|
|
|
2025-02-17 11:20:26 -08:00
|
|
|
painter.setCompositionMode(QPainter::CompositionMode_Source); // Important for correct alpha blending
|
|
|
|
|
|
|
|
|
|
painter.setFont(QFont(this->fontInfo().family(), fontSize));
|
|
|
|
|
painter.fillRect(rect(), Qt::transparent); // Clear the image before redrawing
|
|
|
|
|
|
2025-02-21 09:57:10 -08:00
|
|
|
#ifdef QT_DEBUG
|
|
|
|
|
QString fontNameP = painter.font().family();
|
|
|
|
|
int fontSizeP = painter.font().pointSize();
|
2025-02-21 10:22:26 -08:00
|
|
|
qDebug() << "cache painter: Font: " << fontNameP << ", size: " << fontSizeP
|
|
|
|
|
<< "infoFamily: " << painter.fontInfo().family();
|
2025-02-21 09:57:10 -08:00
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
QFontMetrics fm = painter.fontMetrics();
|
|
|
|
|
|
2025-02-17 11:20:26 -08:00
|
|
|
switch(meterType)
|
2022-08-23 23:10:58 -07:00
|
|
|
{
|
2025-02-17 11:20:26 -08:00
|
|
|
case meterS:
|
|
|
|
|
label = "S";
|
2025-02-21 09:57:10 -08:00
|
|
|
labelWidth = fm.boundingRect(label).width();
|
2025-02-17 11:20:26 -08:00
|
|
|
drawScaleS(&painter);
|
|
|
|
|
break;
|
|
|
|
|
case meterSubS:
|
|
|
|
|
label = "Sub";
|
2025-02-21 09:57:10 -08:00
|
|
|
labelWidth = fm.boundingRect(label).width();
|
2025-02-17 11:20:26 -08:00
|
|
|
drawScaleS(&painter);
|
|
|
|
|
break;
|
|
|
|
|
case meterPower:
|
|
|
|
|
label = "PWR";
|
2025-02-21 09:57:10 -08:00
|
|
|
labelWidth = fm.boundingRect(label).width();
|
2025-02-17 11:20:26 -08:00
|
|
|
drawScalePo(&painter);
|
|
|
|
|
break;
|
|
|
|
|
case meterALC:
|
|
|
|
|
label = "ALC";
|
2025-02-21 09:57:10 -08:00
|
|
|
labelWidth = fm.boundingRect(label).width();
|
2025-02-17 11:20:26 -08:00
|
|
|
drawScaleALC(&painter);
|
|
|
|
|
break;
|
|
|
|
|
case meterSWR:
|
|
|
|
|
label = "SWR";
|
2025-02-21 09:57:10 -08:00
|
|
|
labelWidth = fm.boundingRect(label).width();
|
2025-02-17 11:20:26 -08:00
|
|
|
drawScaleSWR(&painter);
|
|
|
|
|
break;
|
|
|
|
|
case meterCenter:
|
|
|
|
|
label = "CTR";
|
2025-02-21 09:57:10 -08:00
|
|
|
labelWidth = fm.boundingRect(label).width();
|
2025-02-17 11:20:26 -08:00
|
|
|
drawScaleCenter(&painter);
|
|
|
|
|
break;
|
|
|
|
|
case meterVoltage:
|
|
|
|
|
label = "Vd";
|
2025-02-21 09:57:10 -08:00
|
|
|
labelWidth = fm.boundingRect(label).width();
|
2025-02-17 11:20:26 -08:00
|
|
|
drawScaleVd(&painter);
|
|
|
|
|
break;
|
|
|
|
|
case meterCurrent:
|
|
|
|
|
label = "Id";
|
2025-02-21 09:57:10 -08:00
|
|
|
labelWidth = fm.boundingRect(label).width();
|
2025-02-17 11:20:26 -08:00
|
|
|
drawScaleId(&painter);
|
|
|
|
|
break;
|
|
|
|
|
case meterComp:
|
|
|
|
|
label = "CMP(dB)";
|
2025-02-21 09:57:10 -08:00
|
|
|
labelWidth = fm.boundingRect(label).width();
|
2025-02-17 11:20:26 -08:00
|
|
|
if(reverseCompMeter) {
|
|
|
|
|
drawScaleCompInverted(&painter);
|
|
|
|
|
} else {
|
|
|
|
|
drawScaleComp(&painter);
|
2022-08-23 23:10:58 -07:00
|
|
|
}
|
2025-02-17 11:20:26 -08:00
|
|
|
break;
|
|
|
|
|
case meterNone:
|
|
|
|
|
label = tr("Double-click to set meter");
|
2025-02-21 09:57:10 -08:00
|
|
|
labelWidth = fm.boundingRect(label).width();
|
2025-02-17 11:20:26 -08:00
|
|
|
drawLabel(&painter);
|
|
|
|
|
return;
|
|
|
|
|
break;
|
|
|
|
|
case meterAudio:
|
|
|
|
|
label = "dBfs";
|
|
|
|
|
peakRedLevel = 241;
|
2025-02-21 09:57:10 -08:00
|
|
|
labelWidth = fm.boundingRect(label).width();
|
2025-02-17 11:20:26 -08:00
|
|
|
drawScale_dBFs(&painter);
|
|
|
|
|
break;
|
|
|
|
|
case meterRxAudio:
|
|
|
|
|
label = "Rx(dBfs)";
|
|
|
|
|
peakRedLevel = 241;
|
2025-02-21 09:57:10 -08:00
|
|
|
labelWidth = fm.boundingRect(label).width();
|
2025-02-17 11:20:26 -08:00
|
|
|
drawScale_dBFs(&painter);
|
|
|
|
|
break;
|
|
|
|
|
case meterTxMod:
|
|
|
|
|
label = "Tx(dBfs)";
|
2025-02-21 09:57:10 -08:00
|
|
|
labelWidth = fm.boundingRect(label).width();
|
2025-02-17 11:20:26 -08:00
|
|
|
peakRedLevel = 241;
|
|
|
|
|
drawScale_dBFs(&painter);
|
|
|
|
|
break;
|
|
|
|
|
case meterdBu:
|
|
|
|
|
label = "dBu";
|
2025-02-21 09:57:10 -08:00
|
|
|
labelWidth = fm.boundingRect(label).width();
|
2025-02-20 19:12:29 +00:00
|
|
|
peakRedLevel = 241;
|
2025-02-21 09:57:10 -08:00
|
|
|
drawScaledBPositive(&painter);
|
2025-02-17 11:20:26 -08:00
|
|
|
break;
|
|
|
|
|
case meterdBuEMF:
|
|
|
|
|
label = "dBu(EMF)";
|
2025-02-21 09:57:10 -08:00
|
|
|
labelWidth = fm.boundingRect(label).width();
|
2025-02-20 19:12:29 +00:00
|
|
|
peakRedLevel = 241;
|
2025-02-21 09:57:10 -08:00
|
|
|
drawScaledBPositive(&painter);
|
2025-02-17 11:20:26 -08:00
|
|
|
break;
|
|
|
|
|
case meterdBm:
|
|
|
|
|
label = "dBm";
|
2025-02-21 09:57:10 -08:00
|
|
|
labelWidth = fm.boundingRect(label).width();
|
2025-02-20 19:12:29 +00:00
|
|
|
peakRedLevel = 241;
|
2025-02-21 09:57:10 -08:00
|
|
|
drawScaledBNegative(&painter);
|
2025-02-17 11:20:26 -08:00
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
label = "DN";
|
2025-02-21 09:57:10 -08:00
|
|
|
labelWidth = fm.boundingRect(label).width();
|
2025-02-17 11:20:26 -08:00
|
|
|
peakRedLevel = 241;
|
|
|
|
|
drawScaleRaw(&painter);
|
|
|
|
|
break;
|
2025-02-17 10:29:05 -08:00
|
|
|
}
|
2025-02-17 11:20:26 -08:00
|
|
|
if(drawLabels)
|
|
|
|
|
{
|
|
|
|
|
// We are tracking the drawLabels parameter,
|
|
|
|
|
// because we may some day want to squeeze this widget
|
|
|
|
|
// into a place where the label cannot fit.
|
2025-02-21 09:57:10 -08:00
|
|
|
|
2025-02-17 11:20:26 -08:00
|
|
|
drawLabel(&painter);
|
2025-02-17 10:29:05 -08:00
|
|
|
}
|
2025-02-17 11:20:26 -08:00
|
|
|
|
|
|
|
|
painter.end();
|
|
|
|
|
recentlyChangedParameters = false;
|
|
|
|
|
lastDrawMeterType = meterType;
|
|
|
|
|
scaleReady = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void meter::recallScale(QPainter *painter) {
|
|
|
|
|
// read the scaleCache onto the canvas
|
2025-02-21 10:10:35 -08:00
|
|
|
//painter->drawImage(0, 0, *scaleCache);
|
|
|
|
|
// This should prevent image scaling, which makest the text less clear:
|
|
|
|
|
painter->drawImage(QPoint(0,0), *scaleCache, scaleCache->rect());
|
2025-02-17 10:29:05 -08:00
|
|
|
}
|
2022-08-23 23:10:58 -07:00
|
|
|
|
2025-02-17 10:29:05 -08:00
|
|
|
void meter::drawLabel(QPainter *qp)
|
|
|
|
|
{
|
|
|
|
|
qp->setPen(lowTextColor);
|
|
|
|
|
qp->drawText(0,scaleTextYstart, label );
|
|
|
|
|
}
|
2024-11-05 18:46:21 +00:00
|
|
|
|
2025-02-17 10:29:05 -08:00
|
|
|
void meter::scaleLinearNumbersForDrawing() {
|
|
|
|
|
// input: current, average, peak (double)
|
|
|
|
|
// output: currentRect, averageRect, peakRect (int)
|
2024-11-05 18:46:21 +00:00
|
|
|
|
2025-02-17 10:29:05 -08:00
|
|
|
currentRect = getPixelScaleFromValue(current);
|
|
|
|
|
averageRect = getPixelScaleFromValue(average);
|
|
|
|
|
peakRect = getPixelScaleFromValue(peak);
|
|
|
|
|
}
|
2024-11-05 18:46:21 +00:00
|
|
|
|
2025-02-17 10:29:05 -08:00
|
|
|
double meter::getValueFromPixelScale(int p) {
|
|
|
|
|
// Give a value 0-255 and receive a scaled value in return
|
|
|
|
|
return (p*(scaleMax-scaleMin)/255) + scaleMin;
|
|
|
|
|
}
|
2024-11-05 18:46:21 +00:00
|
|
|
|
2025-02-17 10:29:05 -08:00
|
|
|
int meter::getPixelScaleFromValue(double v) {
|
|
|
|
|
// give a value within the scale and receive a pixel scale value (0-255)
|
|
|
|
|
return (v-scaleMin) * (255/(scaleMax-scaleMin));
|
|
|
|
|
}
|
2024-11-05 18:46:21 +00:00
|
|
|
|
2025-02-21 09:57:10 -08:00
|
|
|
int meter::nearestStep(double d, int stepSize) {
|
|
|
|
|
// This function was only tested with negative numbers,
|
|
|
|
|
// and produces the rounding edge at the correct spot for
|
|
|
|
|
// our dBm (R8600) scale.
|
|
|
|
|
bool flipped = false;
|
|
|
|
|
if(d < 0) {
|
|
|
|
|
d *= -1;
|
|
|
|
|
flipped = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int n = round(d/stepSize);
|
|
|
|
|
// 99 becomes 9.9 becomes 10
|
|
|
|
|
// 95 becomes 9.5 becomes 10
|
|
|
|
|
// 94 becomes 9.4 becomes 9
|
|
|
|
|
|
|
|
|
|
if(flipped)
|
|
|
|
|
n*=-stepSize;
|
|
|
|
|
else
|
|
|
|
|
n *= stepSize;
|
|
|
|
|
|
|
|
|
|
return n;
|
|
|
|
|
}
|
|
|
|
|
|
2025-02-17 10:29:05 -08:00
|
|
|
void meter::scaleLogNumbersForDrawing() {
|
|
|
|
|
currentRect = (int)((1-audiopot[255-(int)current])*255);
|
|
|
|
|
averageRect = (int)((1-audiopot[255-(int)average])*255);
|
|
|
|
|
peakRect = (int)((1-audiopot[255-(int)peak])*255);
|
|
|
|
|
}
|
2024-11-05 18:46:21 +00:00
|
|
|
|
2025-02-17 10:29:05 -08:00
|
|
|
void meter::drawValue_Linear(QPainter *qp, bool reverse) {
|
|
|
|
|
// Draw a rectangle.
|
2024-11-05 18:46:21 +00:00
|
|
|
|
2025-02-17 10:29:05 -08:00
|
|
|
// The parameters current, peak, and average need to be scaled
|
|
|
|
|
// to 0-255.
|
2024-11-05 18:46:21 +00:00
|
|
|
|
2025-02-20 19:12:29 +00:00
|
|
|
// Data input: scaleMin ---- scaleMax
|
|
|
|
|
// Data output: 0 ---- 255
|
|
|
|
|
scaleLinearNumbersForDrawing();
|
2021-07-18 14:27:21 -07:00
|
|
|
|
2025-02-23 13:31:41 -08:00
|
|
|
this->setAccessibleName(QString("Meter: %1 percent").arg( (int)(100*(double)(currentRect/255.0))));
|
|
|
|
|
|
2025-02-17 10:29:05 -08:00
|
|
|
if(currentRect < 0) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
2021-07-18 14:27:21 -07:00
|
|
|
|
2025-02-20 19:12:29 +00:00
|
|
|
if (this->meterType == meterdBuEMF || this->meterType == meterdBm || this->meterType == meterdBu)
|
|
|
|
|
{
|
|
|
|
|
qp->setPen(lowTextColor);
|
|
|
|
|
uchar prec=1;
|
|
|
|
|
if (current >= 100.0 || current <= -100.0)
|
|
|
|
|
prec=0;
|
|
|
|
|
qp->drawText(0,scaleTextYstart+20, QString("%0").arg(current,0,'f',prec,'0'));
|
|
|
|
|
|
|
|
|
|
}
|
2025-02-17 10:29:05 -08:00
|
|
|
// And then, we can just plot them, since we already scaled
|
|
|
|
|
// the scales, right?
|
2025-02-17 14:36:32 -08:00
|
|
|
if(useGradients) {
|
|
|
|
|
QLinearGradient grad(QPointF(0, 0), QPointF(255, 0));
|
|
|
|
|
if(reverse) {
|
|
|
|
|
grad.setColorAt(1, currentColor.darker().darker());
|
|
|
|
|
grad.setColorAt(0, currentColor.lighter());
|
|
|
|
|
} else {
|
|
|
|
|
grad.setColorAt(0, currentColor.darker().darker());
|
|
|
|
|
grad.setColorAt(1, currentColor.lighter());
|
|
|
|
|
}
|
|
|
|
|
qp->setBrush(grad);
|
|
|
|
|
} else {
|
|
|
|
|
qp->setBrush(currentColor);
|
|
|
|
|
}
|
2025-02-17 14:11:44 -08:00
|
|
|
qp->setPen(currentColor);
|
2025-02-17 10:29:05 -08:00
|
|
|
if(reverse) {
|
|
|
|
|
qp->drawRect(255+mXstart,mYstart,-currentRect,barHeight);
|
|
|
|
|
} else {
|
|
|
|
|
qp->drawRect(mXstart,mYstart,currentRect,barHeight);
|
2021-07-18 14:27:21 -07:00
|
|
|
}
|
2024-02-06 11:06:50 -08:00
|
|
|
|
2025-02-17 10:29:05 -08:00
|
|
|
// Average:
|
|
|
|
|
qp->setPen(averageColor);
|
|
|
|
|
qp->setBrush(averageColor);
|
|
|
|
|
if(reverse) {
|
|
|
|
|
qp->drawRect(255+mXstart-averageRect,mYstart,-1,barHeight); // bar is 1 pixel wide, height = meter start?
|
|
|
|
|
} else {
|
|
|
|
|
qp->drawRect(mXstart+averageRect-1,mYstart,1,barHeight); // bar is 1 pixel wide, height = meter start?
|
|
|
|
|
}
|
2024-11-05 18:46:21 +00:00
|
|
|
|
2025-02-17 10:29:05 -08:00
|
|
|
// Peak:
|
|
|
|
|
qp->setPen(peakColor);
|
|
|
|
|
qp->setBrush(peakColor);
|
|
|
|
|
if(peak > peakRedLevel)
|
2021-08-16 23:25:11 -07:00
|
|
|
{
|
2025-02-17 10:29:05 -08:00
|
|
|
qp->setBrush(Qt::red);
|
|
|
|
|
qp->setPen(Qt::red);
|
|
|
|
|
}
|
|
|
|
|
if(reverse) {
|
|
|
|
|
qp->drawRect(255+mXstart-peakRect+1,mYstart,-1,barHeight);
|
|
|
|
|
} else {
|
|
|
|
|
qp->drawRect(mXstart+peakRect-1,mYstart,2,barHeight);
|
2021-08-16 23:25:11 -07:00
|
|
|
}
|
2025-02-17 10:29:05 -08:00
|
|
|
}
|
2024-11-05 18:46:21 +00:00
|
|
|
|
2025-02-17 10:29:05 -08:00
|
|
|
void meter::drawValue_Center(QPainter *qp) {
|
|
|
|
|
// Draw a center-referenced rectangle
|
2024-11-05 18:46:21 +00:00
|
|
|
|
2025-02-17 10:29:05 -08:00
|
|
|
// First, scale the data for 0-255:
|
|
|
|
|
// Not exactly needed for this since only icom data uses this function currently and that data are already 0-255
|
|
|
|
|
// But we are going to call it anyway to prove that our code is good:
|
|
|
|
|
scaleLinearNumbersForDrawing();
|
2021-08-16 23:25:11 -07:00
|
|
|
|
2025-02-17 10:29:05 -08:00
|
|
|
// Current value:
|
|
|
|
|
// starting at the center (mXstart+128) and offset by (current-128)
|
2025-02-17 14:36:32 -08:00
|
|
|
if(useGradients) {
|
|
|
|
|
QLinearGradient grad(QPointF(0, 0), QPointF(255, 0));
|
|
|
|
|
grad.setColorAt(0, currentColor.darker().darker());
|
|
|
|
|
grad.setColorAt(0.5, currentColor.lighter());
|
|
|
|
|
grad.setColorAt(1, currentColor.darker().darker());
|
|
|
|
|
qp->setBrush(grad);
|
|
|
|
|
} else {
|
|
|
|
|
qp->setBrush(currentColor);
|
|
|
|
|
}
|
|
|
|
|
|
2025-02-17 14:11:44 -08:00
|
|
|
qp->setPen(currentColor);
|
2025-02-17 10:29:05 -08:00
|
|
|
qp->drawRect(mXstart+128,mYstart,currentRect-128,barHeight);
|
2021-02-24 00:18:19 -08:00
|
|
|
|
2025-02-17 10:29:05 -08:00
|
|
|
// Average:
|
|
|
|
|
qp->setPen(averageColor);
|
|
|
|
|
qp->setBrush(averageColor);
|
|
|
|
|
qp->drawRect(mXstart+averageRect-1,mYstart,1,barHeight); // bar is 1 pixel wide, height = meter start?
|
2024-11-05 18:46:21 +00:00
|
|
|
|
2025-02-17 10:29:05 -08:00
|
|
|
// Peak: (what does peak mean for off-center deviation?)
|
|
|
|
|
qp->setPen(peakColor);
|
|
|
|
|
qp->setBrush(peakColor);
|
|
|
|
|
if((peak > 191) || (peak < 63))
|
|
|
|
|
{
|
|
|
|
|
qp->setBrush(Qt::red);
|
|
|
|
|
qp->setPen(Qt::red);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
qp->drawRect(mXstart+peakRect-1,mYstart,1,barHeight);
|
2024-11-05 18:46:21 +00:00
|
|
|
}
|
|
|
|
|
|
2025-02-17 10:29:05 -08:00
|
|
|
void meter::drawValue_Log(QPainter *qp) {
|
|
|
|
|
// Log scale but still 0-255:
|
|
|
|
|
scaleLogNumbersForDrawing();
|
|
|
|
|
|
|
|
|
|
// Current value:
|
|
|
|
|
// X, Y, Width, Height
|
2025-02-17 14:36:32 -08:00
|
|
|
if(useGradients) {
|
|
|
|
|
QLinearGradient grad(QPointF(0, 0), QPointF(255, 0));
|
|
|
|
|
grad.setColorAt(0, currentColor.darker().darker());
|
|
|
|
|
grad.setColorAt(1, currentColor.lighter());
|
|
|
|
|
|
|
|
|
|
qp->setBrush(grad);
|
|
|
|
|
} else {
|
|
|
|
|
qp->setBrush(currentColor);
|
|
|
|
|
}
|
2025-02-17 14:11:44 -08:00
|
|
|
qp->setPen(currentColor);
|
2025-02-17 14:36:32 -08:00
|
|
|
|
2025-02-17 10:29:05 -08:00
|
|
|
qp->drawRect(mXstart,mYstart,currentRect,barHeight);
|
|
|
|
|
|
|
|
|
|
// Average:
|
|
|
|
|
qp->setPen(averageColor);
|
|
|
|
|
qp->setBrush(averageColor);
|
|
|
|
|
qp->drawRect(mXstart+averageRect-1,mYstart,1,barHeight); // bar is 1 pixel wide, height = meter start?
|
|
|
|
|
|
|
|
|
|
// Peak:
|
|
|
|
|
qp->setPen(peakColor);
|
|
|
|
|
qp->setBrush(peakColor);
|
|
|
|
|
if(peak > peakRedLevel)
|
|
|
|
|
{
|
|
|
|
|
qp->setBrush(Qt::red);
|
|
|
|
|
qp->setPen(Qt::red);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
qp->drawRect(mXstart+peakRect-1,mYstart,2,barHeight);
|
2024-11-05 18:46:21 +00:00
|
|
|
}
|
|
|
|
|
|
2025-02-15 18:24:33 +00:00
|
|
|
void meter::setLevel(double current)
|
2021-02-24 00:18:19 -08:00
|
|
|
{
|
2025-02-17 10:29:05 -08:00
|
|
|
// "current" means "now", ie, the value at this moment.
|
|
|
|
|
|
2021-02-24 00:18:19 -08:00
|
|
|
this->current = current;
|
2021-07-18 14:27:21 -07:00
|
|
|
|
|
|
|
|
avgLevels[(avgPosition++)%averageBalisticLength] = current;
|
|
|
|
|
peakLevels[(peakPosition++)%peakBalisticLength] = current;
|
|
|
|
|
|
2025-02-15 18:24:33 +00:00
|
|
|
double sum=0.0;
|
2021-07-18 14:27:21 -07:00
|
|
|
|
|
|
|
|
for(unsigned int i=0; i < (unsigned int)std::min(avgPosition, (int)avgLevels.size()); i++)
|
|
|
|
|
{
|
2025-02-17 10:29:05 -08:00
|
|
|
sum += avgLevels[i];
|
2021-07-18 14:27:21 -07:00
|
|
|
}
|
2025-02-17 10:29:05 -08:00
|
|
|
|
|
|
|
|
// This never divides by zero because the above section of this code
|
|
|
|
|
// inserts data, thus assuring that we will never have a zero for both
|
|
|
|
|
// the position and the size.
|
2021-07-18 14:27:21 -07:00
|
|
|
this->average = sum / std::min(avgPosition, (int)avgLevels.size());
|
|
|
|
|
|
2025-02-17 10:29:05 -08:00
|
|
|
this->peak = (-1)*UINT16_MAX;
|
2021-07-18 14:27:21 -07:00
|
|
|
|
|
|
|
|
for(unsigned int i=0; i < peakLevels.size(); i++)
|
|
|
|
|
{
|
2025-02-17 10:29:05 -08:00
|
|
|
if( peakLevels[i] > this->peak)
|
|
|
|
|
this->peak = peakLevels[i];
|
2021-07-18 14:27:21 -07:00
|
|
|
}
|
|
|
|
|
|
2024-02-05 21:39:23 -08:00
|
|
|
haveUpdatedData = true;
|
2025-02-17 10:29:05 -08:00
|
|
|
haveReceivedSomeData = true;
|
|
|
|
|
|
|
|
|
|
if(meterType==meterS) {
|
|
|
|
|
// This is just so I can catch it in the debugger
|
|
|
|
|
sum++;
|
|
|
|
|
volatile int ooo = 0;
|
|
|
|
|
(void)ooo;
|
|
|
|
|
}
|
|
|
|
|
|
2021-07-19 16:56:04 -07:00
|
|
|
this->update();
|
|
|
|
|
}
|
|
|
|
|
|
2025-02-15 18:24:33 +00:00
|
|
|
void meter::setLevels(double current, double peak)
|
2022-08-24 16:06:41 -07:00
|
|
|
{
|
|
|
|
|
this->current = current;
|
|
|
|
|
this->peak = peak;
|
|
|
|
|
|
|
|
|
|
avgLevels[(avgPosition++)%averageBalisticLength] = current;
|
2025-02-15 18:24:33 +00:00
|
|
|
double sum=0;
|
2022-08-24 16:06:41 -07:00
|
|
|
for(unsigned int i=0; i < (unsigned int)std::min(avgPosition, (int)avgLevels.size()); i++)
|
|
|
|
|
{
|
|
|
|
|
sum += avgLevels.at(i);
|
|
|
|
|
}
|
|
|
|
|
this->average = sum / std::min(avgPosition, (int)avgLevels.size());
|
|
|
|
|
|
2024-02-05 21:39:23 -08:00
|
|
|
haveUpdatedData = true;
|
2025-02-17 10:29:05 -08:00
|
|
|
haveReceivedSomeData = true;
|
2024-02-05 21:39:23 -08:00
|
|
|
this->update(); // place repaint event on the event queue
|
2022-08-24 16:06:41 -07:00
|
|
|
}
|
|
|
|
|
|
2025-02-15 18:24:33 +00:00
|
|
|
void meter::setLevels(double current, double peak, double average)
|
2021-07-19 16:56:04 -07:00
|
|
|
{
|
|
|
|
|
this->current = current;
|
|
|
|
|
this->peak = peak;
|
|
|
|
|
this->average = average;
|
|
|
|
|
|
2024-02-05 21:39:23 -08:00
|
|
|
haveUpdatedData = true;
|
2025-02-17 10:29:05 -08:00
|
|
|
haveReceivedSomeData = true;
|
2024-02-05 21:39:23 -08:00
|
|
|
this->update(); // place repaint event on the event queue
|
2021-02-24 00:18:19 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void meter::updateDrawing(int num)
|
|
|
|
|
{
|
|
|
|
|
fontSize = num;
|
|
|
|
|
length = num;
|
|
|
|
|
}
|
|
|
|
|
|
2021-07-16 17:45:07 -07:00
|
|
|
// The drawScale functions draw the numbers and number unerline for each type of meter
|
|
|
|
|
|
2021-07-18 14:27:21 -07:00
|
|
|
void meter::drawScaleRaw(QPainter *qp)
|
|
|
|
|
{
|
|
|
|
|
qp->setPen(lowTextColor);
|
2021-07-19 23:46:11 -07:00
|
|
|
//qp->setFont(QFont("Arial", fontSize));
|
2021-07-18 14:27:21 -07:00
|
|
|
int i=mXstart;
|
2021-08-16 23:25:11 -07:00
|
|
|
for(; i<mXstart+256; i+=25)
|
2021-07-18 14:27:21 -07:00
|
|
|
{
|
|
|
|
|
qp->drawText(i,scaleTextYstart, QString("%1").arg(i) );
|
|
|
|
|
}
|
|
|
|
|
|
2024-11-05 18:46:21 +00:00
|
|
|
// Now the lines:
|
|
|
|
|
qp->setPen(lowLineColor);
|
|
|
|
|
|
|
|
|
|
// Line: X1, Y1 -->to--> X2, Y2
|
2025-02-17 10:29:05 -08:00
|
|
|
qp->drawLine(mXstart,scaleLineYstart,255/2+mXstart,scaleLineYstart);
|
2024-11-05 18:46:21 +00:00
|
|
|
qp->setPen(highLineColor);
|
2025-02-17 10:29:05 -08:00
|
|
|
qp->drawLine(255/2+mXstart,scaleLineYstart,255+mXstart,scaleLineYstart);
|
2024-11-05 18:46:21 +00:00
|
|
|
}
|
|
|
|
|
|
2025-02-21 09:57:10 -08:00
|
|
|
void meter::drawScaledBPositive(QPainter *qp)
|
2025-02-20 19:12:29 +00:00
|
|
|
{
|
2025-02-21 09:57:10 -08:00
|
|
|
// dB scale which is mostly (or all) positive numbers
|
|
|
|
|
// used for dBu EMF and dBu
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2025-02-20 19:12:29 +00:00
|
|
|
int redLevelRect = getPixelScaleFromValue(scaleRedline);
|
|
|
|
|
|
2024-11-05 18:46:21 +00:00
|
|
|
qp->setPen(lowTextColor);
|
|
|
|
|
|
2025-02-20 19:12:29 +00:00
|
|
|
int scaleSpan = scaleMax - scaleMin;
|
2025-02-21 09:57:10 -08:00
|
|
|
scaleSpan = (scaleSpan/10) * 10;
|
2025-02-20 19:12:29 +00:00
|
|
|
int stepDelta = 0;
|
|
|
|
|
if(scaleSpan < 100) {
|
|
|
|
|
stepDelta = 10;
|
|
|
|
|
} else {
|
|
|
|
|
stepDelta = 20;
|
|
|
|
|
}
|
2024-11-05 18:46:21 +00:00
|
|
|
|
2025-02-21 09:57:10 -08:00
|
|
|
QFontMetrics fm = qp->fontMetrics();
|
|
|
|
|
QRect textRect = fm.boundingRect(QString::number(scaleMax));
|
|
|
|
|
int textMaxLength = textRect.width();
|
|
|
|
|
int scaleCacheWidth = scaleCache->size().width();
|
|
|
|
|
|
2025-02-20 19:12:29 +00:00
|
|
|
int db = 0;
|
2025-02-21 09:57:10 -08:00
|
|
|
int dbPrior = -10;
|
2025-02-20 19:12:29 +00:00
|
|
|
double val = 0;
|
2024-11-05 18:46:21 +00:00
|
|
|
|
2025-02-20 19:12:29 +00:00
|
|
|
QString formattedString;
|
|
|
|
|
for(int p=mXstart; p < mXstart+255; p++) {
|
|
|
|
|
val = getValueFromPixelScale(p-mXstart);
|
2025-02-21 09:57:10 -08:00
|
|
|
db = ((int)round(val)/stepDelta) * stepDelta;
|
|
|
|
|
//db = ((int)(round(val/10.0))*10 / stepDelta) * stepDelta; // round to nearest step
|
2024-11-05 18:46:21 +00:00
|
|
|
|
2025-02-20 19:12:29 +00:00
|
|
|
if(db != dbPrior) {
|
|
|
|
|
if(db > scaleRedline) {
|
|
|
|
|
qp->setPen(highTextColor);
|
|
|
|
|
} else {
|
|
|
|
|
qp->setPen(lowTextColor);
|
|
|
|
|
}
|
|
|
|
|
formattedString = QString::number(db);
|
2025-02-21 09:57:10 -08:00
|
|
|
// qDebug() << "p: " << p << "val: " << val
|
|
|
|
|
// << "dB: " << db << "dBprior: " << dbPrior;
|
|
|
|
|
if( (p + textMaxLength < scaleCacheWidth)
|
|
|
|
|
&& (p > labelWidth ) ){
|
|
|
|
|
qp->drawText(p,scaleTextYstart, formattedString );
|
|
|
|
|
}
|
2025-02-20 19:12:29 +00:00
|
|
|
qp->drawLine(p,scaleTextYstart, p, scaleTextYstart+5);
|
|
|
|
|
dbPrior = db;
|
2025-02-21 09:57:10 -08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Now the lines:
|
|
|
|
|
qp->setPen(lowLineColor);
|
|
|
|
|
|
|
|
|
|
// Line: X1, Y1 -->to--> X2, Y2
|
|
|
|
|
qp->drawLine(mXstart,scaleLineYstart,redLevelRect+mXstart,scaleLineYstart);
|
|
|
|
|
qp->setPen(highLineColor);
|
|
|
|
|
qp->drawLine(redLevelRect+mXstart,scaleLineYstart,255+mXstart,scaleLineYstart);
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void meter::drawScaledBNegative(QPainter *qp)
|
|
|
|
|
{
|
|
|
|
|
// dB scale which is mostly (or all) negative numbers
|
|
|
|
|
// used for dBm
|
2024-11-05 18:46:21 +00:00
|
|
|
|
2025-02-21 09:57:10 -08:00
|
|
|
int redLevelRect = getPixelScaleFromValue(scaleRedline);
|
|
|
|
|
QFontMetrics fm = qp->fontMetrics();
|
|
|
|
|
QRect textRect = fm.boundingRect(QString::number(-100));
|
|
|
|
|
int textMaxLength = textRect.width();
|
|
|
|
|
int scaleCacheWidth = scaleCache->size().width();
|
|
|
|
|
|
|
|
|
|
qp->setPen(lowTextColor);
|
|
|
|
|
|
|
|
|
|
int scaleSpan = scaleMax - scaleMin;
|
|
|
|
|
scaleSpan = (scaleSpan*10) / 10;
|
|
|
|
|
int stepDelta = 0;
|
|
|
|
|
if(scaleSpan < 100) {
|
|
|
|
|
stepDelta = 10;
|
|
|
|
|
} else {
|
|
|
|
|
stepDelta = 20;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int db = 0;
|
|
|
|
|
int dbPrior = -10;
|
|
|
|
|
double val = 0;
|
|
|
|
|
|
|
|
|
|
QString formattedString;
|
|
|
|
|
for(int p=mXstart; p < mXstart+255; p++) {
|
|
|
|
|
val = getValueFromPixelScale(p-mXstart);
|
|
|
|
|
db = nearestStep(val, stepDelta);
|
|
|
|
|
|
|
|
|
|
if( (db != dbPrior) && ((int)round(val)%10==0)) {
|
|
|
|
|
if(db > scaleRedline) {
|
|
|
|
|
qp->setPen(highTextColor);
|
|
|
|
|
} else {
|
|
|
|
|
qp->setPen(lowTextColor);
|
|
|
|
|
}
|
|
|
|
|
formattedString = QString::number(db);
|
|
|
|
|
// qDebug() << "p: " << p << "val: " << val
|
|
|
|
|
// << "dB: " << db << "dBprior: " << dbPrior;
|
|
|
|
|
if ( (p + textMaxLength < scaleCacheWidth)
|
|
|
|
|
&& (p > labelWidth) ){
|
|
|
|
|
qp->drawText(p,scaleTextYstart, formattedString );
|
|
|
|
|
}
|
|
|
|
|
qp->drawLine(p,scaleTextYstart, p, scaleTextYstart+5);
|
|
|
|
|
dbPrior = db;
|
2025-02-20 19:12:29 +00:00
|
|
|
}
|
|
|
|
|
}
|
2024-11-05 18:46:21 +00:00
|
|
|
|
2021-07-18 14:27:21 -07:00
|
|
|
// Now the lines:
|
|
|
|
|
qp->setPen(lowLineColor);
|
|
|
|
|
|
|
|
|
|
// Line: X1, Y1 -->to--> X2, Y2
|
2025-02-20 19:12:29 +00:00
|
|
|
qp->drawLine(mXstart,scaleLineYstart,redLevelRect+mXstart,scaleLineYstart);
|
2022-08-22 21:22:01 -07:00
|
|
|
qp->setPen(highLineColor);
|
2025-02-20 19:12:29 +00:00
|
|
|
qp->drawLine(redLevelRect+mXstart,scaleLineYstart,255+mXstart,scaleLineYstart);
|
|
|
|
|
|
2021-07-18 14:27:21 -07:00
|
|
|
}
|
|
|
|
|
|
2022-08-23 23:10:58 -07:00
|
|
|
void meter::drawScale_dBFs(QPainter *qp)
|
|
|
|
|
{
|
|
|
|
|
qp->setPen(lowTextColor);
|
|
|
|
|
peakRedLevel = 193;
|
|
|
|
|
|
2022-08-24 22:23:32 -07:00
|
|
|
if(meterType==meterAudio)
|
|
|
|
|
qp->drawText(20+mXstart,scaleTextYstart, QString("-30"));
|
|
|
|
|
qp->drawText(38+mXstart+2,scaleTextYstart, QString("-24"));
|
|
|
|
|
qp->drawText(71+mXstart,scaleTextYstart, QString("-18"));
|
|
|
|
|
qp->drawText(124+mXstart,scaleTextYstart, QString("-12"));
|
|
|
|
|
qp->drawText(193+mXstart,scaleTextYstart, QString("-6"));
|
2022-08-24 21:52:36 -07:00
|
|
|
qp->drawText(255+mXstart,scaleTextYstart, QString("0"));
|
|
|
|
|
|
|
|
|
|
// Low ticks:
|
|
|
|
|
qp->setPen(lowLineColor);
|
|
|
|
|
qp->drawLine(20+mXstart,scaleTextYstart, 20+mXstart, scaleTextYstart+5);
|
|
|
|
|
qp->drawLine(38+mXstart,scaleTextYstart, 38+mXstart, scaleTextYstart+5);
|
|
|
|
|
qp->drawLine(71+mXstart,scaleTextYstart, 71+mXstart, scaleTextYstart+5);
|
|
|
|
|
qp->drawLine(124+mXstart,scaleTextYstart, 124+mXstart, scaleTextYstart+5);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// High ticks:
|
|
|
|
|
qp->setPen(highLineColor);
|
|
|
|
|
qp->drawLine(193+mXstart,scaleTextYstart, 193+mXstart, scaleTextYstart+5);
|
|
|
|
|
qp->drawLine(255+mXstart,scaleTextYstart, 255+mXstart, scaleTextYstart+5);
|
2022-08-23 23:10:58 -07:00
|
|
|
|
|
|
|
|
// Now the lines:
|
|
|
|
|
qp->setPen(lowLineColor);
|
|
|
|
|
|
|
|
|
|
// Line: X1, Y1 -->to--> X2, Y2
|
|
|
|
|
qp->drawLine(mXstart,scaleLineYstart,peakRedLevel+mXstart,scaleLineYstart);
|
2022-08-24 10:17:11 -07:00
|
|
|
qp->setPen(highLineColor);
|
2022-08-23 23:10:58 -07:00
|
|
|
qp->drawLine(peakRedLevel+mXstart,scaleLineYstart,255+mXstart,scaleLineYstart);
|
|
|
|
|
}
|
|
|
|
|
|
2021-07-19 23:46:11 -07:00
|
|
|
void meter::drawScaleVd(QPainter *qp)
|
|
|
|
|
{
|
2025-02-17 10:29:05 -08:00
|
|
|
int redLevelRect = getPixelScaleFromValue(scaleRedline);
|
|
|
|
|
|
2021-07-19 23:46:11 -07:00
|
|
|
qp->setPen(lowTextColor);
|
|
|
|
|
|
2025-02-17 10:29:05 -08:00
|
|
|
int scaleSpan = scaleMax - scaleMin;
|
|
|
|
|
scaleSpan = (scaleSpan*10) / 10;
|
|
|
|
|
int stepDelta = 0;
|
|
|
|
|
if(scaleSpan < 20) {
|
|
|
|
|
stepDelta = 1;
|
|
|
|
|
} else {
|
|
|
|
|
stepDelta = 2;
|
|
|
|
|
}
|
2021-07-19 23:46:11 -07:00
|
|
|
|
2025-02-20 19:12:29 +00:00
|
|
|
int volt = int(scaleMin);
|
|
|
|
|
int voltPrior = int(scaleMin); // causes the zero to be skipped
|
2025-02-17 10:29:05 -08:00
|
|
|
double val = 0;
|
2021-07-19 23:46:11 -07:00
|
|
|
|
2025-02-17 10:29:05 -08:00
|
|
|
QString formattedString;
|
|
|
|
|
for(int p=mXstart; p < mXstart+255; p++) {
|
|
|
|
|
val = getValueFromPixelScale(p-mXstart);
|
|
|
|
|
volt = ((int)val / stepDelta) * stepDelta; // round to nearest step
|
2021-07-19 23:46:11 -07:00
|
|
|
|
2025-02-17 10:29:05 -08:00
|
|
|
if(volt != voltPrior) {
|
|
|
|
|
//qDebug() << "val: " << val << ", power: " << power << ", powerPrior: " << powerPrior << " scaleSpan:" << scaleSpan << "stepDelta: " << stepDelta;
|
|
|
|
|
if(volt > scaleRedline) {
|
|
|
|
|
qp->setPen(highTextColor);
|
|
|
|
|
} else {
|
|
|
|
|
qp->setPen(lowTextColor);
|
|
|
|
|
}
|
|
|
|
|
formattedString = QString::number(volt);
|
|
|
|
|
qp->drawText(p,scaleTextYstart, formattedString );
|
|
|
|
|
qp->drawLine(p,scaleTextYstart, p, scaleTextYstart+5);
|
|
|
|
|
voltPrior = volt;
|
2021-07-19 23:46:11 -07:00
|
|
|
|
2025-02-17 10:29:05 -08:00
|
|
|
}
|
2021-07-19 23:46:11 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Now the lines:
|
|
|
|
|
qp->setPen(lowLineColor);
|
|
|
|
|
|
|
|
|
|
// Line: X1, Y1 -->to--> X2, Y2
|
2025-02-17 10:29:05 -08:00
|
|
|
qp->drawLine(mXstart,scaleLineYstart,redLevelRect+mXstart,scaleLineYstart);
|
2022-08-22 21:22:01 -07:00
|
|
|
qp->setPen(highLineColor);
|
2025-02-17 10:29:05 -08:00
|
|
|
qp->drawLine(redLevelRect+mXstart,scaleLineYstart,255+mXstart,scaleLineYstart);
|
2021-07-19 23:46:11 -07:00
|
|
|
}
|
|
|
|
|
|
2021-07-18 14:27:21 -07:00
|
|
|
void meter::drawScaleCenter(QPainter *qp)
|
|
|
|
|
{
|
|
|
|
|
// No known units
|
|
|
|
|
qp->setPen(lowLineColor);
|
|
|
|
|
qp->drawText(60+mXstart,scaleTextYstart, QString("-"));
|
|
|
|
|
|
2022-08-22 21:22:01 -07:00
|
|
|
qp->setPen(centerTuningColor);
|
2021-07-18 14:27:21 -07:00
|
|
|
// Attempt to draw the zero at the actual center
|
|
|
|
|
qp->drawText(128-2+mXstart,scaleTextYstart, QString("0"));
|
|
|
|
|
|
|
|
|
|
qp->setPen(lowLineColor);
|
|
|
|
|
qp->drawText(195+mXstart,scaleTextYstart, QString("+"));
|
|
|
|
|
|
|
|
|
|
qp->setPen(lowLineColor);
|
|
|
|
|
qp->drawLine(mXstart,scaleLineYstart,128-32+mXstart,scaleLineYstart);
|
|
|
|
|
|
2022-08-22 21:22:01 -07:00
|
|
|
qp->setPen(centerTuningColor);
|
2021-07-18 14:27:21 -07:00
|
|
|
qp->drawLine(128-32+mXstart,scaleLineYstart,128+32+mXstart,scaleLineYstart);
|
|
|
|
|
|
|
|
|
|
qp->setPen(lowLineColor);
|
|
|
|
|
qp->drawLine(128+32+mXstart,scaleLineYstart,255+mXstart,scaleLineYstart);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2021-07-16 17:45:07 -07:00
|
|
|
void meter::drawScalePo(QPainter *qp)
|
|
|
|
|
{
|
2025-02-17 10:29:05 -08:00
|
|
|
int redLevelRect = getPixelScaleFromValue(scaleRedline);
|
2021-07-16 17:45:07 -07:00
|
|
|
|
|
|
|
|
qp->setPen(lowTextColor);
|
2021-07-19 23:46:11 -07:00
|
|
|
|
2025-02-17 10:29:05 -08:00
|
|
|
int scaleSpan = scaleMax - scaleMin;
|
|
|
|
|
scaleSpan = (scaleSpan*10) / 10;
|
|
|
|
|
int stepDelta = 0;
|
|
|
|
|
if(scaleSpan < 20) {
|
|
|
|
|
// Low power radio, show each 1 watt on the scale
|
|
|
|
|
stepDelta = 1;
|
|
|
|
|
} else {
|
|
|
|
|
// High power radio, show every 10 watts on the scale.
|
|
|
|
|
stepDelta = 20;
|
2021-07-16 17:45:07 -07:00
|
|
|
}
|
|
|
|
|
|
2025-02-17 10:29:05 -08:00
|
|
|
int power = 0;
|
|
|
|
|
int powerPrior = 0; // causes the zero to be skipped
|
|
|
|
|
double val = 0;
|
2021-07-16 17:45:07 -07:00
|
|
|
|
2025-02-17 10:29:05 -08:00
|
|
|
QString formattedString;
|
|
|
|
|
for(int p=mXstart; p < mXstart+255; p++) {
|
|
|
|
|
val = getValueFromPixelScale(p-mXstart);
|
|
|
|
|
power = ((int)val / stepDelta) * stepDelta; // round to nearest step
|
2021-07-16 17:45:07 -07:00
|
|
|
|
2025-02-17 10:29:05 -08:00
|
|
|
|
|
|
|
|
if(power != powerPrior) {
|
|
|
|
|
//qDebug() << "val: " << val << ", power: " << power << ", powerPrior: " << powerPrior << " scaleSpan:" << scaleSpan << "stepDelta: " << stepDelta;
|
|
|
|
|
if(power > scaleRedline) {
|
|
|
|
|
qp->setPen(highTextColor);
|
|
|
|
|
} else {
|
|
|
|
|
qp->setPen(lowTextColor);
|
|
|
|
|
}
|
|
|
|
|
formattedString = QString::number(power);
|
|
|
|
|
qp->drawText(p,scaleTextYstart, formattedString );
|
|
|
|
|
qp->drawLine(p,scaleTextYstart, p, scaleTextYstart+5);
|
|
|
|
|
powerPrior = power;
|
|
|
|
|
|
|
|
|
|
}
|
2021-07-16 17:45:07 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Now the lines:
|
|
|
|
|
qp->setPen(lowLineColor);
|
|
|
|
|
|
2021-07-16 23:23:29 -07:00
|
|
|
// Line: X1, Y1 -->to--> X2, Y2
|
2025-02-17 10:29:05 -08:00
|
|
|
qp->drawLine(mXstart,scaleLineYstart,redLevelRect+mXstart,scaleLineYstart);
|
2022-08-22 21:22:01 -07:00
|
|
|
qp->setPen(highLineColor);
|
2025-02-17 10:29:05 -08:00
|
|
|
qp->drawLine(redLevelRect+mXstart,scaleLineYstart,255+mXstart,scaleLineYstart);
|
2021-07-16 17:45:07 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void meter::drawScaleRxdB(QPainter *qp)
|
|
|
|
|
{
|
2025-02-17 10:29:05 -08:00
|
|
|
// TODO: remove
|
2021-07-16 17:45:07 -07:00
|
|
|
(void)qp;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void meter::drawScaleALC(QPainter *qp)
|
|
|
|
|
{
|
2025-02-17 10:29:05 -08:00
|
|
|
int redLevelRect = getPixelScaleFromValue(scaleRedline);
|
2021-07-17 00:37:27 -07:00
|
|
|
|
|
|
|
|
qp->setPen(lowTextColor);
|
|
|
|
|
|
2025-02-17 10:29:05 -08:00
|
|
|
int scaleSpan = scaleMax - scaleMin;
|
|
|
|
|
scaleSpan = (scaleSpan*10) / 10;
|
|
|
|
|
int stepDelta = 25;
|
2021-07-17 00:37:27 -07:00
|
|
|
|
2025-02-17 10:29:05 -08:00
|
|
|
|
|
|
|
|
int alc = 0;
|
|
|
|
|
int alcPrior = -1; // causes the zero to be skipped
|
|
|
|
|
double val = 0;
|
|
|
|
|
|
|
|
|
|
QString formattedString;
|
|
|
|
|
for(int p=mXstart; p < mXstart+255; p++) {
|
|
|
|
|
val = getValueFromPixelScale(p-mXstart)*100; // values are 0-1-2, with 1 being 100%
|
|
|
|
|
alc = ((int)val / stepDelta) * stepDelta; // round to nearest step
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if(alc != alcPrior) {
|
|
|
|
|
//qDebug() << "val: " << val << ", alc: " << alc << ", alcPrior: " << alcPrior << " scaleSpan:" << scaleSpan << "stepDelta: " << stepDelta;
|
|
|
|
|
if(alc > scaleRedline*99) {
|
|
|
|
|
qp->setPen(highTextColor);
|
|
|
|
|
} else {
|
|
|
|
|
qp->setPen(lowTextColor);
|
|
|
|
|
}
|
|
|
|
|
formattedString = QString::number(alc);
|
|
|
|
|
qp->drawText(p,scaleTextYstart, formattedString );
|
|
|
|
|
qp->drawLine(p,scaleTextYstart, p, scaleTextYstart+5);
|
|
|
|
|
// qp->drawLine(p,scaleTextYstart, p, scaleTextYstart+5);
|
|
|
|
|
|
|
|
|
|
alcPrior = alc;
|
|
|
|
|
}
|
2021-07-17 00:37:27 -07:00
|
|
|
}
|
|
|
|
|
|
2025-02-17 10:29:05 -08:00
|
|
|
// Now the lines:
|
2021-07-17 00:37:27 -07:00
|
|
|
qp->setPen(lowLineColor);
|
|
|
|
|
|
2025-02-17 10:29:05 -08:00
|
|
|
// Line: X1, Y1 -->to--> X2, Y2
|
|
|
|
|
qp->drawLine(mXstart,scaleLineYstart,redLevelRect+mXstart,scaleLineYstart);
|
|
|
|
|
qp->setPen(highLineColor);
|
|
|
|
|
qp->drawLine(redLevelRect+mXstart,scaleLineYstart,255+mXstart,scaleLineYstart);
|
2021-07-17 00:37:27 -07:00
|
|
|
}
|
|
|
|
|
|
2021-08-16 23:25:11 -07:00
|
|
|
void meter::drawScaleComp(QPainter *qp)
|
|
|
|
|
{
|
2025-02-17 10:29:05 -08:00
|
|
|
int redLevelRect = getPixelScaleFromValue(scaleRedline);
|
2021-08-16 23:25:11 -07:00
|
|
|
|
|
|
|
|
qp->setPen(lowTextColor);
|
|
|
|
|
|
2025-02-17 10:29:05 -08:00
|
|
|
int scaleSpan = scaleMax - scaleMin;
|
|
|
|
|
scaleSpan = (scaleSpan*10) / 10;
|
|
|
|
|
int stepDelta = 0;
|
|
|
|
|
if(scaleSpan <= 30) {
|
|
|
|
|
stepDelta = 3;
|
|
|
|
|
} else {
|
|
|
|
|
stepDelta = 12;
|
2021-08-16 23:25:11 -07:00
|
|
|
}
|
|
|
|
|
|
2025-02-17 10:29:05 -08:00
|
|
|
int comp = 0;
|
|
|
|
|
int compPrior = 0; // causes the zero to be skipped
|
|
|
|
|
double val = 0;
|
|
|
|
|
|
|
|
|
|
QString formattedString;
|
|
|
|
|
// Adding stepDelta to the start means we skip the first step.
|
|
|
|
|
for(int p=mXstart; p < mXstart+255; p++) {
|
|
|
|
|
val = getValueFromPixelScale(p-mXstart);
|
|
|
|
|
comp = ((int)val / stepDelta) * stepDelta; // round to nearest step
|
|
|
|
|
if(comp != compPrior) {
|
|
|
|
|
//qDebug() << "val: " << val << ", comp: " << comp << ", compPrior: " << compPrior << " scaleSpan:" << scaleSpan << "stepDelta: " << stepDelta;
|
|
|
|
|
if(compPrior != 0) {
|
|
|
|
|
if(comp > scaleRedline) {
|
|
|
|
|
qp->setPen(highTextColor);
|
|
|
|
|
} else {
|
|
|
|
|
qp->setPen(lowTextColor);
|
|
|
|
|
}
|
|
|
|
|
formattedString = QString::number(comp);
|
|
|
|
|
qp->drawText(p,scaleTextYstart, formattedString );
|
|
|
|
|
qp->drawLine(p,scaleTextYstart, p, scaleTextYstart+5);
|
|
|
|
|
}
|
|
|
|
|
compPrior = comp;
|
|
|
|
|
}
|
2021-08-16 23:25:11 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Now the lines:
|
|
|
|
|
qp->setPen(lowLineColor);
|
|
|
|
|
|
|
|
|
|
// Line: X1, Y1 -->to--> X2, Y2
|
2025-02-17 10:29:05 -08:00
|
|
|
qp->drawLine(mXstart,scaleLineYstart,redLevelRect+mXstart,scaleLineYstart);
|
2022-08-22 21:22:01 -07:00
|
|
|
qp->setPen(highLineColor);
|
2025-02-17 10:29:05 -08:00
|
|
|
qp->drawLine(redLevelRect+mXstart,scaleLineYstart,255+mXstart,scaleLineYstart);
|
2021-08-16 23:25:11 -07:00
|
|
|
}
|
|
|
|
|
|
2024-02-06 11:06:50 -08:00
|
|
|
void meter::drawScaleCompInverted(QPainter *qp) {
|
|
|
|
|
// inverted scale
|
|
|
|
|
|
2025-02-17 10:29:05 -08:00
|
|
|
int redLevelRect = getPixelScaleFromValue(scaleRedline);
|
2024-02-06 11:06:50 -08:00
|
|
|
|
2025-02-17 10:29:05 -08:00
|
|
|
qp->setPen(lowTextColor);
|
2024-02-06 22:02:46 -08:00
|
|
|
|
2025-02-17 10:29:05 -08:00
|
|
|
int scaleSpan = scaleMax - scaleMin;
|
|
|
|
|
scaleSpan = (scaleSpan*10) / 10;
|
|
|
|
|
int stepDelta = 0;
|
|
|
|
|
if(scaleSpan <= 30) {
|
|
|
|
|
stepDelta = 3;
|
|
|
|
|
} else {
|
|
|
|
|
stepDelta = 12;
|
2024-02-06 11:06:50 -08:00
|
|
|
}
|
|
|
|
|
|
2025-02-17 10:29:05 -08:00
|
|
|
int comp = 0;
|
|
|
|
|
int compPrior = -1; // -1 allows the first value to be drawn
|
|
|
|
|
double val = 0;
|
|
|
|
|
QString formattedString;
|
|
|
|
|
// Adding stepDelta to the start means we skip the first step.
|
|
|
|
|
for(int p=mXstart; p < mXstart+255-64; p++) {
|
|
|
|
|
val = getValueFromPixelScale(p-mXstart);
|
|
|
|
|
comp = ((int)val / stepDelta) * stepDelta; // round to nearest step
|
|
|
|
|
if(comp != compPrior) {
|
|
|
|
|
//qDebug() << "p: " << p << ", val: " << val << ", comp: " << comp << ", compPrior: " << compPrior << " scaleSpan:" << scaleSpan << "stepDelta: " << stepDelta;
|
|
|
|
|
if(comp > scaleRedline-3) {
|
|
|
|
|
qp->setPen(highTextColor);
|
|
|
|
|
} else {
|
|
|
|
|
qp->setPen(lowTextColor);
|
|
|
|
|
}
|
|
|
|
|
formattedString = QString::number(comp);
|
|
|
|
|
qp->drawText(255+mXstart-p,scaleTextYstart, formattedString );
|
|
|
|
|
qp->drawLine(255+mXstart-p,scaleTextYstart, 255+mXstart-p, scaleTextYstart+5);
|
|
|
|
|
|
|
|
|
|
compPrior = comp;
|
|
|
|
|
}
|
2024-02-06 11:06:50 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Now the lines:
|
|
|
|
|
qp->setPen(lowLineColor);
|
|
|
|
|
|
|
|
|
|
// Line: X1, Y1 -->to--> X2, Y2
|
2025-02-17 10:29:05 -08:00
|
|
|
qp->drawLine(255+mXstart,scaleLineYstart,255-redLevelRect+mXstart,scaleLineYstart);
|
2024-02-06 11:06:50 -08:00
|
|
|
qp->setPen(highLineColor);
|
2025-02-17 10:29:05 -08:00
|
|
|
qp->drawLine(255-redLevelRect+mXstart,scaleLineYstart,mXstart,scaleLineYstart);
|
2024-02-06 11:06:50 -08:00
|
|
|
}
|
|
|
|
|
|
2021-07-17 00:37:27 -07:00
|
|
|
void meter::drawScaleSWR(QPainter *qp)
|
|
|
|
|
{
|
2025-02-17 10:29:05 -08:00
|
|
|
int redLevelRect = getPixelScaleFromValue(scaleRedline);
|
|
|
|
|
|
|
|
|
|
int scaleSpan = scaleMax - scaleMin;
|
|
|
|
|
scaleSpan = (scaleSpan*10) / 10;
|
|
|
|
|
bool smallSteps = false;
|
|
|
|
|
// Icom SWR scale goes up to 20:1
|
|
|
|
|
// Kenwood SWR scale goes up to 5:1
|
|
|
|
|
if(scaleSpan <= 6) {
|
|
|
|
|
smallSteps = true;
|
|
|
|
|
}
|
2021-07-17 00:37:27 -07:00
|
|
|
|
2025-02-17 10:29:05 -08:00
|
|
|
// Draw vertical tic marks and scale numbers:
|
2022-08-22 21:22:01 -07:00
|
|
|
qp->setPen(lowTextColor);
|
2025-02-17 10:29:05 -08:00
|
|
|
int swr = 0;
|
|
|
|
|
int swrPrior = -1;
|
|
|
|
|
double val = 0;
|
|
|
|
|
int fives = 0;
|
|
|
|
|
int tens = 0;
|
|
|
|
|
int decimals = 0;
|
|
|
|
|
QString formattedString;
|
|
|
|
|
for(int p=mXstart; p < mXstart+255; p++) {
|
|
|
|
|
val = getValueFromPixelScale(p-mXstart);
|
|
|
|
|
if(smallSteps) {
|
|
|
|
|
swr = (val * 50)/50;
|
|
|
|
|
swr = swr * 10;
|
|
|
|
|
fives = ((int)(val*10))%5;
|
|
|
|
|
tens = ((int)(val*10))%10;
|
|
|
|
|
if( (fives==0) && (tens!=0)) {
|
|
|
|
|
swr = swr + 5;
|
|
|
|
|
decimals = 1;
|
|
|
|
|
} else {
|
|
|
|
|
decimals = 0;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
swr = (val * 50)/50;
|
|
|
|
|
swr *= 10;
|
|
|
|
|
}
|
2021-07-17 00:37:27 -07:00
|
|
|
|
2025-02-17 10:29:05 -08:00
|
|
|
if( (swr != swrPrior) && (swr > swrPrior) ) {
|
|
|
|
|
if( (swr > 50) && (swr - swrPrior < 20) )
|
|
|
|
|
continue;
|
2021-08-16 23:25:11 -07:00
|
|
|
|
2025-02-17 10:29:05 -08:00
|
|
|
// qDebug() << "SWR meter: p: " << p << ", val: " << val << "swr: " << swr << "swrPrior: " << swrPrior << "fives: " << fives << "tens:" << tens;
|
|
|
|
|
if(val >= scaleRedline) {
|
|
|
|
|
qp->setPen(highTextColor);
|
|
|
|
|
} else {
|
|
|
|
|
qp->setPen(lowTextColor);
|
|
|
|
|
}
|
|
|
|
|
formattedString = QString::number(swr/10.0, 'f', decimals);
|
|
|
|
|
qp->drawText(p,scaleTextYstart, formattedString );
|
|
|
|
|
qp->drawLine(p,scaleTextYstart, p, scaleTextYstart+5);
|
|
|
|
|
swrPrior = swr;
|
|
|
|
|
}
|
|
|
|
|
}
|
2021-08-16 23:25:11 -07:00
|
|
|
|
2025-02-17 10:29:05 -08:00
|
|
|
// Draw horizontal underline:
|
2021-07-17 00:37:27 -07:00
|
|
|
qp->setPen(lowLineColor);
|
2025-02-17 10:29:05 -08:00
|
|
|
qp->drawLine(mXstart,scaleLineYstart,redLevelRect+mXstart,scaleLineYstart);
|
2022-08-22 21:22:01 -07:00
|
|
|
qp->setPen(highLineColor);
|
2025-02-17 10:29:05 -08:00
|
|
|
qp->drawLine(redLevelRect+mXstart,scaleLineYstart,255+mXstart,scaleLineYstart);
|
2021-07-16 17:45:07 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void meter::drawScaleId(QPainter *qp)
|
|
|
|
|
{
|
2025-02-17 10:29:05 -08:00
|
|
|
int redLevelRect = getPixelScaleFromValue(scaleRedline);
|
2021-08-16 23:25:11 -07:00
|
|
|
|
|
|
|
|
qp->setPen(lowTextColor);
|
|
|
|
|
|
2025-02-17 10:29:05 -08:00
|
|
|
int scaleSpan = scaleMax - scaleMin;
|
|
|
|
|
scaleSpan = (scaleSpan*10) / 10;
|
|
|
|
|
int stepDelta = 0;
|
|
|
|
|
if(scaleSpan < 20) {
|
|
|
|
|
stepDelta = 1;
|
|
|
|
|
} else if (scaleSpan < 40 ){
|
|
|
|
|
stepDelta = 2;
|
|
|
|
|
} else {
|
|
|
|
|
stepDelta = 5;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int current = 0;
|
|
|
|
|
int currentPrior = 0; // causes the zero to be skipped
|
|
|
|
|
double val = 0;
|
2021-08-16 23:25:11 -07:00
|
|
|
|
2025-02-17 10:29:05 -08:00
|
|
|
QString formattedString;
|
|
|
|
|
for(int p=mXstart; p < mXstart+255; p++) {
|
|
|
|
|
val = getValueFromPixelScale(p-mXstart);
|
|
|
|
|
current = ((int)val / stepDelta) * stepDelta; // round to nearest step
|
2021-08-16 23:25:11 -07:00
|
|
|
|
2025-02-17 10:29:05 -08:00
|
|
|
if(current != currentPrior) {
|
|
|
|
|
//qDebug() << "val: " << val << ", power: " << power << ", powerPrior: " << powerPrior << " scaleSpan:" << scaleSpan << "stepDelta: " << stepDelta;
|
|
|
|
|
if(current > scaleRedline) {
|
|
|
|
|
qp->setPen(highTextColor);
|
|
|
|
|
} else {
|
|
|
|
|
qp->setPen(lowTextColor);
|
|
|
|
|
}
|
|
|
|
|
formattedString = QString::number(current);
|
|
|
|
|
qp->drawText(p,scaleTextYstart, formattedString );
|
|
|
|
|
qp->drawLine(p,scaleTextYstart, p, scaleTextYstart+5);
|
|
|
|
|
currentPrior = current;
|
2021-08-16 23:25:11 -07:00
|
|
|
|
2025-02-17 10:29:05 -08:00
|
|
|
}
|
2021-08-16 23:25:11 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Now the lines:
|
|
|
|
|
qp->setPen(lowLineColor);
|
|
|
|
|
|
|
|
|
|
// Line: X1, Y1 -->to--> X2, Y2
|
2025-02-17 10:29:05 -08:00
|
|
|
qp->drawLine(mXstart,scaleLineYstart,redLevelRect+mXstart,scaleLineYstart);
|
2022-08-22 21:22:01 -07:00
|
|
|
qp->setPen(highLineColor);
|
2025-02-17 10:29:05 -08:00
|
|
|
qp->drawLine(redLevelRect+mXstart,scaleLineYstart,255+mXstart,scaleLineYstart);
|
2021-07-16 17:45:07 -07:00
|
|
|
}
|
2021-02-24 00:18:19 -08:00
|
|
|
|
2021-07-16 17:45:07 -07:00
|
|
|
void meter::drawScaleS(QPainter *qp)
|
2021-02-24 00:18:19 -08:00
|
|
|
{
|
2025-02-17 10:29:05 -08:00
|
|
|
// double --> S-Unit:
|
|
|
|
|
// -54 = S0
|
|
|
|
|
// -48 = S1
|
|
|
|
|
// -42 = S2
|
|
|
|
|
// -36 = S3
|
|
|
|
|
// -30 = S4
|
|
|
|
|
// -24 = S5
|
|
|
|
|
// -18 = S6
|
|
|
|
|
// -12 = S4
|
|
|
|
|
// -6 = S8
|
|
|
|
|
// 0 = S9
|
|
|
|
|
// 10 = +10
|
|
|
|
|
// 20 = +20
|
|
|
|
|
// 30 = +30 ... etc
|
|
|
|
|
int redLevelRect = getPixelScaleFromValue(scaleRedline);
|
2021-08-16 23:25:11 -07:00
|
|
|
|
2021-02-24 00:18:19 -08:00
|
|
|
qp->setPen(lowTextColor);
|
|
|
|
|
|
2025-02-17 10:29:05 -08:00
|
|
|
// We must find the pixel values (0-255) which correspond to those s-units
|
|
|
|
|
// and we are assuming a linear scale because 6dB per s-unit is a constant rate
|
|
|
|
|
|
|
|
|
|
int sunit = 0;
|
|
|
|
|
int sunitPrior = -1;
|
|
|
|
|
double val = 0;
|
|
|
|
|
bool plus = false;
|
|
|
|
|
for(int p=mXstart; p < mXstart+255; p++) {
|
|
|
|
|
val = getValueFromPixelScale(p-mXstart);
|
|
|
|
|
// Due to low precision, we have to set this threshold at 1 instead of 0.
|
|
|
|
|
// We also have to be carefuly not to double-write at S9
|
|
|
|
|
if(val <=1) {
|
|
|
|
|
sunit = (val-scaleMin)/6;
|
|
|
|
|
} else if (val >= 10 ){
|
|
|
|
|
sunit = ((int)val/10) * 10; // round to nearest ten
|
|
|
|
|
if(sunit==10) {
|
|
|
|
|
plus = true;
|
|
|
|
|
} else {
|
|
|
|
|
plus = false;
|
|
|
|
|
}
|
|
|
|
|
}
|
2021-02-24 00:18:19 -08:00
|
|
|
|
2025-02-17 10:29:05 -08:00
|
|
|
if(sunit != sunitPrior) {
|
|
|
|
|
if(val >= scaleRedline) {
|
|
|
|
|
qp->setPen(highTextColor);
|
|
|
|
|
//qDebug() << "pval: " << p-mXstart << "val: " << val << ", s-unit: " << sunit << ", sunit prior: " << sunitPrior;
|
|
|
|
|
} else {
|
|
|
|
|
qp->setPen(lowTextColor);
|
|
|
|
|
}
|
|
|
|
|
if(plus)
|
|
|
|
|
qp->drawText(p-10,scaleTextYstart, QString("+%1").arg(sunit) );
|
|
|
|
|
else
|
|
|
|
|
qp->drawText(p,scaleTextYstart, QString("%1").arg(sunit) );
|
|
|
|
|
qp->drawLine(p,scaleTextYstart, p, scaleTextYstart+5);
|
|
|
|
|
sunitPrior = sunit;
|
|
|
|
|
}
|
2021-02-24 00:18:19 -08:00
|
|
|
}
|
|
|
|
|
|
2025-02-17 10:29:05 -08:00
|
|
|
// Horizontal lines:
|
2021-02-24 00:18:19 -08:00
|
|
|
qp->setPen(lowLineColor);
|
2025-02-17 10:29:05 -08:00
|
|
|
qp->drawLine(mXstart,scaleLineYstart,redLevelRect+mXstart,scaleLineYstart);
|
2022-08-22 21:22:01 -07:00
|
|
|
qp->setPen(highLineColor);
|
2025-02-17 10:29:05 -08:00
|
|
|
qp->drawLine(redLevelRect+mXstart,scaleLineYstart,255+mXstart,scaleLineYstart);
|
2021-02-24 00:18:19 -08:00
|
|
|
}
|
2024-02-05 21:03:08 -08:00
|
|
|
|
|
|
|
|
void meter::muteSingleComboItem(QComboBox *comboBox, int index) {
|
|
|
|
|
enableAllComboBoxItems(comboBox);
|
|
|
|
|
setComboBoxItemEnabled(comboBox, index, false);
|
|
|
|
|
}
|
|
|
|
|
|
2024-11-06 09:27:15 +00:00
|
|
|
void meter::enableAllComboBoxItems(QComboBox *combobox, bool en) {
|
2024-02-05 21:03:08 -08:00
|
|
|
for(int i=0; i < combobox->count(); i++) {
|
2024-11-06 09:27:15 +00:00
|
|
|
setComboBoxItemEnabled(combobox, i, en);
|
2024-02-05 21:03:08 -08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void meter::setComboBoxItemEnabled(QComboBox * comboBox, int index, bool enabled)
|
|
|
|
|
{
|
|
|
|
|
auto * model = qobject_cast<QStandardItemModel*>(comboBox->model());
|
2025-01-09 09:24:55 +00:00
|
|
|
assert(model);
|
2024-02-05 21:03:08 -08:00
|
|
|
if(!model) return;
|
|
|
|
|
|
|
|
|
|
auto * item = model->item(index);
|
2025-01-09 09:24:55 +00:00
|
|
|
assert(item);
|
2024-02-05 21:03:08 -08:00
|
|
|
if(!item) return;
|
|
|
|
|
item->setEnabled(enabled);
|
|
|
|
|
}
|
|
|
|
|
|